https://issues.dlang.org/show_bug.cgi?id=19173
Issue ID: 19173 Summary: [scope][dip1000] Using a `lazy` parameter defeats scope and dip1000 Product: D Version: D2 Hardware: x86_64 OS: Linux Status: NEW Severity: major Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: atila.ne...@gmail.com This code correctly does not compile: ------------------------------------- @safe: void main() { auto oops = Oops(10); Oops(10).should == oops[]; } struct Oops { import core.stdc.stdlib; private int* _ints; private int size; this(int size) @trusted { this.size = size; _ints = cast(int*) malloc(size); } ~this() @trusted scope { free(_ints); } bool opEqual(ref const(Oops) other) const { return size == other.size; } scope auto opSlice(this This)() @trusted { return _ints[0 .. size]; } } auto should(E)(lazy E expr) { struct Should { bool opEquals(int[] ints) { assert(expr()[] == ints); return true; } } return Should(); } ------------------------------------- escape_lazy.d(22): Error: variable `escape_lazy.should!(Oops).should.expr` has scoped destruction, cannot build closure escape_lazy.d(22): Error: variable `escape_lazy.should!(Oops).should.expr` has scoped destruction, cannot build closure Nice. However, slicing the rvalue defeats the compiler check and running under asan confirms that the resulting code has a use-after-free bug: `Oops(10)[].should == oops[];` As can be seen in the code above, making opSlice return a scope slice didn't seem to affect anything. --