Reduced example:
struct S {
int i;
}
void fun(T)(auto ref T x) {}
unittest {
enum s = S();
fun(s.i);
}
The call to fun() should infer x as int, but somehow thinks it's ref int.
Comment #2 by razvan.nitu1305 — 2019-08-19T15:19:46Z
I cannot reproduce this with the latest master branch. Also, running it on dlang.io [1] seems to successfully compile. Although on the nightly branch it is indeed failing.
[1] https://run.dlang.io/is/clMnj3
Comment #3 by b2.temp — 2019-12-10T00:19:09Z
The reduced test case is not catching the problem anymore. This one does:
---
void empty(T)(auto /*const*/ ref T a) { }
struct Foo {
int i;
}
void main() {
enum Foo foo = Foo(0);
foo.i.empty();
}
---
The regression is caused by a protection on function parameters (and on assign exp too) to prevent writing member of manifest constants that are aggregates, more specifically struct literals (`enum Foo foo` from the front-end POV is actually a struct literal).
Without the protection, in the past, `i` could be modified, which made no sense and could even create crashes.
See https://github.com/dlang/dmd/pull/10115, which added the protection.
Comment #4 by razvan.nitu1305 — 2021-12-07T13:28:32Z
(In reply to Basile-z from comment #3)
> The reduced test case is not catching the problem anymore. This one does:
>
> ---
> void empty(T)(auto /*const*/ ref T a) { }
>
>
> struct Foo {
> int i;
> }
>
> void main() {
> enum Foo foo = Foo(0);
> foo.i.empty();
> }
> ---
>
> The regression is caused by a protection on function parameters (and on
> assign exp too) to prevent writing member of manifest constants that are
> aggregates, more specifically struct literals (`enum Foo foo` from the
> front-end POV is actually a struct literal).
>
> Without the protection, in the past, `i` could be modified, which made no
> sense and could even create crashes.
>
> See https://github.com/dlang/dmd/pull/10115, which added the protection.
I cannot reproduce this. Running this code:
void empty(T)(auto ref T a)
{
pragma(msg, __traits(isRef, a));
}
struct Foo {
int i;
}
void main() {
enum Foo foo = Foo(0);
foo.i.empty();
}
Yields `false` which is correct. Closing as fixed, please reopen if I am missing something.