Bug 14653 – scoped!range in foreach crashes

Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2015-06-05T09:05:00Z
Last change time
2017-07-22T12:35:54Z
Keywords
pull, wrong-code
Assigned to
nobody
Creator
lio+bugzilla

Comments

Comment #0 by lio+bugzilla — 2015-06-05T09:05:42Z
From http://beta.forum.dlang.org/post/[email protected] class SomeRangeType { int a; this(T)(T...) { } ~this() { a = -1; } @property int front() { assert(a>=0); return a; } void popFront() { ++a; } @property bool empty() { return a < 10; } } void main(string[] args) { import std.typecons; foreach(e; scoped!SomeRangeType(args)) {} } $ dmd -g -debug -run ~/testforeach.d --- killed by signal 11
Comment #1 by schuetzm — 2015-06-05T09:13:26Z
I can confirm this for DMD git master.
Comment #2 by schuetzm — 2015-06-05T14:33:29Z
@Lionello: Why ICE?
Comment #3 by lio+bugzilla — 2015-06-05T23:40:33Z
(In reply to Marc Schütz from comment #2) > @Lionello: Why ICE? My bad.
Comment #4 by ketmar — 2015-06-17T13:10:20Z
a simplified sample: =================== import std.stdio : writeln; struct SomeRangeType { int a; alias front = a; void popFront () { ++a; } @property bool empty () { return (a >= 2); } } auto wrapit () { static struct Wrapper { SomeRangeType rng; alias rng this; @disable this (this); ~this () { writeln("wrapper dtor"); } } return Wrapper(SomeRangeType()); } void main () { writeln("before foreach"); foreach (auto e; wrapit()) { writeln("in foreach; e=", e); } writeln("after foreach"); } =================== this prints: --- before foreach wrapper dtor in foreach; e=0 in foreach; e=1 after foreach -- what i expected it to print: --- before foreach in foreach; e=0 in foreach; e=1 wrapper dtor after foreach ---
Comment #5 by ketmar — 2015-06-17T13:20:47Z
p.s. seems that what triggers the bug is `alias this` in wrapper. removing `alias this` and rewriting wrapper to do simple redirections emits the correct output. i.e. changing `Wrapper` struct to the following one makes the bug go away: static struct Wrapper { SomeRangeType rng; //alias rng this; @property int front () { return rng.front; } void popFront () { rng.popFront; } @property bool empty () { return rng.empty; } @disable this (this); ~this () { writeln("wrapper dtor"); } }
Comment #6 by ketmar — 2015-06-17T13:26:38Z
generated initializer for `alias this` variant: init: __r87 = (Wrapper __tmpfordtor86 = wrapit(); , __tmpfordtor86).rng; generated initializer for proxy variant: init: __r86 = wrapit(); clearly, compiler tries to pull `rng` away of wrapper struct with `alias this` redirection, and then destroying created wrapper. this may work for other cases, but completely wrong for `scoped`. seems that `foreach` conversion code shouldn't try to pull off aliased entity.
Comment #7 by ketmar — 2015-06-17T13:58:39Z
that's `inferAggregate()` which pulls out aliased type from wrapper, rewriting it from `wrapit()` to `wrapit().rng`, and semantic then rewrites it to `(Wrapper __tmpfordtor3 = wrapit(); , __tmpfordtor3).rng`. it does this: if (ad->aliasthis) { if (!att && tab->checkAliasThisRec()) att = tab; fes->aggr = new DotIdExp(fes->aggr->loc, fes->aggr, ad->aliasthis->ident); continue; } i.e. literally pulling away aliased struct with `DotIdExp` (and dtoring result of `wrapit()` by the way, as it thinks that it's not required anymore. seems that `inferAggregate()` must postpone dtor calling for such cases.
Comment #8 by k.hara.pg — 2015-07-03T13:59:20Z
Comment #9 by github-bugzilla — 2015-07-06T06:06:28Z
Commits pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/0fea84354ed1f4339a2910897bf9f1cab87b3384 fix Issue 14653 - scoped!range in foreach crashes https://github.com/D-Programming-Language/dmd/commit/e03bfc283f1f2d96bf159c2cba177235a8545d2f Merge pull request #4797 from 9rnsr/fix14653 Issue 14653 - scoped!range in foreach crashes
Comment #10 by github-bugzilla — 2015-10-04T18:19:00Z
Comment #11 by github-bugzilla — 2017-07-22T12:35:54Z
Commits pushed to dmd-cxx at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/0fea84354ed1f4339a2910897bf9f1cab87b3384 fix Issue 14653 - scoped!range in foreach crashes https://github.com/dlang/dmd/commit/e03bfc283f1f2d96bf159c2cba177235a8545d2f Merge pull request #4797 from 9rnsr/fix14653