Bug 21197 – Wrong lifetime inference with DIP1000 in dmd 2.093.0

Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2020-08-25T14:26:37Z
Last change time
2022-08-31T09:35:31Z
Keywords
pull, safe
Assigned to
No Owner
Creator
Atila Neves

Comments

Comment #0 by atila.neves — 2020-08-25T14:26:37Z
This is a regression compared to 2.092.1. I don't know how this got past CI since it broke unit-threaded. This test compiled with 2.092.1 but fails to do so with 2.092.1: https://github.com/atilaneves/unit-threaded/blob/42d517a9bbdfc216fcedf65440c1ec71b437a175/tests/unit_threaded/ut/property.d#L7 The reason is the @safe inference done on this template function: https://github.com/atilaneves/unit-threaded/blob/42d517a9bbdfc216fcedf65440c1ec71b437a175/subpackages/property/source/unit_threaded/property.d#L21 After investigating and adding @safe to it, the compiler fails to compile it with this: subpackages/property/source/unit_threaded/property.d(48,21): Error: address of struct temporary returned by createGenerator() assigned to longer lived variable gen This is obviously false. Applying this diff makes the problem go away, which is a valid workaround but that shouldn't be needed: // See https://github.com/atilaneves/unit-threaded/issues/187 for why - auto createGenerator() { + auto createGenerator(ref Random random) { return RndValueGen!(Parameters!F)(&random); } // It might be that some projects don't use dip1000 and so // createGenerator isn't safe static if(isSafe!createGenerator) - scope gen = createGenerator; + scope gen = createGenerator(random); else - scope gen = () @trusted { return createGenerator; }(); + scope gen = () @trusted { return createGenerator(random); }(); auto input(Flag!"shrink" shrink = Yes.shrink) {
Comment #1 by moonlightsentinel — 2020-08-25T17:33:12Z
Reduced example: ========================================== @safe void check() { int random; auto createGenerator() { return RndValueGen(&random); } scope gen = createGenerator; } struct RndValueGen { int* rnd; } ==========================================
Comment #2 by moonlightsentinel — 2020-08-25T21:41:55Z
digger: 788398ac6293f57ae78fca23de96b1653f729265 is the first bad commit commit 788398ac6293f57ae78fca23de96b1653f729265 Author: Atila Neves <[email protected]> Date: Wed Jun 10 10:44:17 2020 +0100 dmd: Merge pull request #10945 from WalterBright/fix20183 https://github.com/dlang/dmd/pull/10945 fix Issue 20183 - Assigning statement scope of struct literal or temp…
Comment #3 by bugzilla — 2022-07-28T08:20:56Z
If we replace the struct with an equivalent pointer: @safe void check() { int random; auto createGenerator() { int* p = &random; return p; } scope gen = createGenerator; } it does compile successfully. Both should compile successfully, as the struct is just a wrapper around a pointer.
Comment #4 by bugzilla — 2022-08-11T02:16:17Z
A better test case, with and without the error message: @safe void check2() { int random; S create1() { return S(); } scope S gen1 = create1; // no error S create2() { return S(&random); } // address of struct temporary returned by `create()` assigned to longer lived variable `gen` scope S gen2 = create2; } struct S { int* r; }
Comment #5 by dlang-bot — 2022-08-11T17:04:14Z
@WalterBright updated dlang/dmd pull request #14360 "fix Issue 21197 - Wrong lifetime inference with DIP1000 in dmd 2.093.0" fixing this issue: - fix Issue 21197 - Wrong lifetime inference with DIP1000 in dmd 2.093.0 https://github.com/dlang/dmd/pull/14360
Comment #6 by razvan.nitu1305 — 2022-08-31T09:35:31Z
This has been fixed.