Bug 21748 – Return value of forward-referenced auto ref function mistakenly treated as lvalue

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2021-03-22T22:32:44Z
Last change time
2024-12-13T19:15:21Z
Keywords
accepts-invalid
Assigned to
uplink.coder
Creator
Paul Backus
Moved to GitHub: dmd#19893 →

Comments

Comment #0 by snarwin+bugzilla — 2021-03-22T22:32:44Z
As of DMD 2.096.0, the following program compiles and runs without error: --- void main() { fun() = 1; } auto ref int fun() { return 42; } --- However, if the order of the functions is swapped: --- auto ref int fun() { return 42; } void main() { fun() = 1; } --- ...then the compiler correctly issues the following error: --- bug.d(8): Error: `fun()` is not an lvalue and cannot be modified --- ​
Comment #1 by uplink.coder — 2021-03-28T10:31:39Z
I can add a bit of detail. The issue here is the determination of auto-ref. Generally the ref-ness of a function-type does not depend on the body of the function. auto ref being the exception. When an auto ref function is encountered without having gone through the semantic3 to flag isRef is set to true. Therefore if main goes through semantic3 first, and it checks the type of fun, it will see that fun returns ref. If fun() is first, it will resolve the auto-ref to be non-ref. and set the isRef of it's type to false. Causing the isLvalue check to fail.
Comment #2 by uplink.coder — 2021-03-28T10:32:03Z
I can add a bit of detail. The issue here is the determination of auto-ref. Generally the ref-ness of a function-type does not depend on the body of the function. auto ref being the exception. When an auto ref function is encountered without having gone through the semantic3 to flag isRef is set to true. Therefore if main goes through semantic3 first, and it checks the type of fun, it will see that fun returns ref. If fun() is first, it will resolve the auto-ref to be non-ref. and set the isRef of it's type to false. Causing the isLvalue check to fail.
Comment #3 by uplink.coder — 2021-03-28T11:04:40Z
This diff would fix it in a hacky way! BUT that does not address the systemic issue that the ast is in unstable states depending on resolve ordering! --- a/src/dmd/expression.d +++ b/src/dmd/expression.d @@ -5081,6 +5081,24 @@ extern (C++) final class CallExp : UnaExp if (tb.ty == Tdelegate || tb.ty == Tpointer) tb = tb.nextOf(); auto tf = tb.isTypeFunction(); + + // the real ref-ness of the function might not be inferred yet + // therefore we need to get the function out if there is one + if (tf) + { + if (auto ve = e1.isVarExp()) + { + if (ve.var) + { + if (auto fd = ve.var.isFuncDeclaration()) + { + fd.functionSemantic(); + fd.functionSemantic3(); + } + } + } + }
Comment #4 by robert.schadek — 2024-12-13T19:15:21Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19893 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB