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