Bug 24003 – return/scope inference does not end up in type to some degree

Status
NEW
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2023-06-20T14:25:16Z
Last change time
2024-12-13T19:29:46Z
Assigned to
No Owner
Creator
Bolpat
Blocks
23300
Moved to GitHub: dmd#20302 →

Comments

Comment #0 by qs.il.paperinik — 2023-06-20T14:25:16Z
When function attributes are inferred, they end up in the type: ```d auto f() {} static assert(is(typeof(&f) == void function() @safe nothrow @nogc pure)); ``` However, when parameters’ `scope` and `return` attributes are inferred, they are not displayed in error messages or `pragma(msg)`. They might not be displayed, but could still (silently) be part of the type; but in a Schrödinger fashion, they are and they are not: ```d auto f(int[] xs) @safe { static int ctr; ctr++; // force impure return xs; } void tplTypeInfer(F)(ref F fp1, ref F fp2) { int[3] xs; fp1(xs); fp2(xs); } //void nonTpl(ref int[] function(int[] xs) nothrow @nogc @safe fp) @safe //{ // //int[3] xs; // //fp(xs); //} void main() @safe { int[3] xs; f(xs); // good: `xs` binds to parameter inferred `return scope`. static assert(typeof(&f).stringof == "int[] function(int[] xs) nothrow @nogc @safe"); alias F1 = int[] function(int[] xs) nothrow @nogc @safe; alias F2 = typeof(&f); static assert(is(F1 == F2)); // PASSES! F1 fp1 = &f; // This and … F2 fp2 = &f; // … this should behave the same, right? fp1(xs); // error: reference to local variable `xs` assigned to non-scope parameter `xs` fp2(xs); // good (apparently, the parameter is scope here) tplTypeInfer(fp1, fp2); // good/error depending on if nonTpl is commented-in tplTypeInfer(fp2, fp1); // good/error (same) tplTypeInfer!F1(fp1, fp2); // good/error (same) tplTypeInfer!F1(fp2, fp1); // good/error (same) tplTypeInfer!F2(fp1, fp2); // good/error (same) tplTypeInfer!F2(fp2, fp1); // good/error (same) } ``` It seems that if you *use* the function pointer, it remembers somehow that the parameter is inferred scope. Also, there’s some Schrödinger action going on with template type inference.
Comment #1 by dkorpel — 2023-06-20T15:18:50Z
(In reply to Bolpat from comment #0) > Also, there’s some Schrödinger action going on with template type inference. Yes, I'm all too aware of this. It was decided at some point to make inferred `scope` and `return` not part of the type mangle, so that there wouldn't be link errors between phobos compiled with dip1000 and user code without it. However, the compiler uses the mangle internally as the identity of a type. So if two types have the same mangled name, they are considered equal. I tried undoing this, but of course, that breaks everything, so it's going to be hard to untangle the mess.
Comment #2 by dlang-bot — 2023-06-20T16:10:15Z
@dkorpel created dlang/dmd pull request #15333 "Issue 24003 - mangle inferred return/scope attributes in parameters" mentioning this issue: - Issue 24003 - mangle inferred return/scope attributes in parameters https://github.com/dlang/dmd/pull/15333
Comment #3 by Ajieskola — 2024-04-23T12:03:17Z
I think this is same as what I was just about to report: ```d auto nullPtr(int*) => (int*).init; @safe unittest { int local; // compiles (with -preview=dip1000), because the parameter is correctly inferred as scope auto nullP = nullPtr(&local); } // Yet this says AliasSeq!(). // Should say AliasSeq!"scope". pragma(msg, __traits(getParameterStorageClasses, nullPtr, 0)); ``` I was solving https://issues.dlang.org/show_bug.cgi?id=23300, but this bug is blocking me. Since `scope` inference is limited, `std.array.array` needs to manually introspect whether `.front` / `.opApply` / element copy of the source range are `scope`. With this bug, it only works in the rare few cases where `scope` is manually specified. I have tried working around it by testing whether a call passing a `scope` argument compiles, but no joy. DIP1000 checks are only done in safe code, and trying to cast a `@system` function to a `@trusted` one to make the check work, without changing the function type in any other way or losing the `scope` inference, was just too difficult for me - probably impossible.
Comment #4 by robert.schadek — 2024-12-13T19:29:46Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/20302 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB