Thx for digging. Just in case, the problem isn't the pragma(msg), but that `static assert(!is(typeof(mixin(foo()))));` newly fails.
Comment #3 by moonlightsentinel — 2021-03-21T16:45:35Z
Indeed but bisection yields the same commit for your example.
Comment #4 by boris2.9 — 2021-03-21T16:53:03Z
Regression?
I would call it 'progression', the behavior is totally more consistent now.
---
void foo() {}
pragma(msg, typeof(foo()));
pragma(msg, typeof(mixin("foo()")));
pragma(msg, typeof(mixin(foo())));
pragma(msg, typeof(mixin(foo().stringof)));
static assert(is(typeof(foo()) == void));
static assert(is(typeof(mixin("foo()")) == void));
static assert(is(typeof(mixin(foo())) == void));
static assert(is(typeof(mixin(foo().stringof)) == void));
---
Comment #5 by moonlightsentinel — 2021-03-21T16:56:15Z
(In reply to Boris Carvajal from comment #4)
> Regression?
>
> I would call it 'progression', the behavior is totally more consistent now.
>
> ---
> pragma(msg, typeof(mixin(foo())));
> ---
So the behaviour of this snippet now depends on the return type of foo AFAICT (CTFE vs. implicit .stringof). Doesn't seem consistent to me.
Comment #6 by moonlightsentinel — 2021-03-21T16:59:16Z
Assume pragma(msg, typeof(mixin(foo())));
void foo() {}
=> void
string foo() { return "foo"; }
=> string() // function type
Comment #7 by boris2.9 — 2021-03-21T17:40:08Z
The 'typeof' of any void expression should be 'void'.
The second case looks like another bug, why is the call expression "foo()", of void value, changing to a function symbol.
Comment #8 by moonlightsentinel — 2021-03-21T17:53:17Z
(In reply to Boris Carvajal from comment #7)
> The second case looks like another bug, why is the call expression "foo()",
> of void value, changing to a function symbol.
You misunderstood my second example, it changes foo to return a string.
Slightly modified example that should be less confusing:
----------------------------------------
string foo() { return "bar"; }
int bar;
pragma(msg, typeof(mixin(foo())));
----------------------------------------
=(CTFE)=> pragma(msg, typeof(mixin("bar"))); // int
Comment #9 by kinke — 2021-03-21T19:18:57Z
No idea what the spec says, but I expected `mixin(foo())`, i.e., `mixin(void)` to fail, and only string expressions to be allowed - `mixin("1 + 2")`, `mixin(q{1 + 2})` and `mixin((() => "1")() ~ " + " ~ 2.stringof)`.
Comment #10 by boris2.9 — 2021-03-21T19:32:19Z
(In reply to moonlightsentinel from comment #8)
> You misunderstood my second example, it changes foo to return a string.
Yep, now I get it, my bad.
I shouldn't have put the example, just think it doesn't exist.
So all it's reduced to whether mixin should be able to parse a void expression or not.
(In reply to kinke from comment #9)
> No idea what the spec says, but I expected `mixin(foo())`, i.e.,
> `mixin(void)` to fail
Yep, though this '(void)' was always something more, before there was no way to express it but the new 'cast(void)0' thing took over and now it's working.
Comment #11 by kinke — 2021-03-21T19:39:18Z
Ah, so the point is to allow stuff like `mixin((() => "1")(), " + ", 2)` too:
https://dlang.org/spec/expression.html#mixin_expressions
So with void expressions now being represented as "cast(void)0" strings instead of "<void>", there's a chance that a previously invalid mixin with some void expression argument doesn't fail anymore.
Do type arguments make a lot of sense for mixin expressions? `mixin("int") d = 3;` works fine; `mixin(int) d = 3;` yields:
Error: found `)` when expecting `.` following int
Error: found `;` when expecting `)`
Error: no identifier for declarator `mixin((int).d = 3)`
Comment #12 by kinke — 2021-03-21T19:59:40Z
Scratch the type thing above, I wasn't thinking clearly.
(In reply to Boris Carvajal from comment #10)
> So all it's reduced to whether mixin should be able to parse a void
> expression or not.
Yes, but I'm not sure it's worth it, as the new behaviour seems indeed consistent. FWIW, this 'issue' newly manifested in https://github.com/dlang/dmd/blob/98ec2d4946f69c74d008e2a97c3a9e7252da9a1e/test/runnable/test42.d#L2776 for LDC when merging 2.096, i.e., some edge-case test and no 'real' code. (Still works with DMD for another, possibly invalid reason apparently.)
Closing.
Comment #13 by moonlightsentinel — 2021-03-21T20:07:29Z
Fair enough, it's fine as long as both examples are run via CTFE (which dmd actually does for the `void` version)