https://issues.dlang.org/show_bug.cgi?id=15832
--- Comment #4 from [email protected] --- (In reply to Atila Neves from comment #2) > However, even with ref, the explanation isn't quite right: the delegate > created in the constructor doesn't reference garbage - the GC should keep > the memory alive. I think I was a tiny bit off, but not by much. I did some more testing and now I think this is what happens: A closure is allocated, but that closure references the field of the struct on the stack. And that field is part of a local variable, of course. So, the delegate references a local variable through two indirections. That way, stuff like this works: ---- struct S { int field; int delegate() makeFieldGetter() { return {return field;}; } } void main() { S s; s.field = 1; auto getter = s.makeFieldGetter(); assert(getter() == 1); /* passes */ s.field = 2; assert(getter() == 2); /* passes, too */ } ---- If the closure would make a copy the field on the heap, then the second assert wouldn't pass. I don't know if this is the best way to handle the situation, or if it's horribly broken, or something in between. (In reply to Atila Neves from comment #3) > Ok, I've looked into it a bit more and I think it's a bug. I @disabled > this(this) and it still happens. I think "moving" from one location to another is still allowed with a disabled this(this). And "moving" means: make a copy, don't run the postblit, destroy the source. So dmd is probably complying with the spec when it moves a non-copyable struct instead of constructing it at the destination site. I'm not sure, though, and dmd seems to be quite fickle about when it makes a copy and when not: When I change `mock`'s implementation to `auto m = Mock!T(f); return m;`, then dmd seems to not make a copy. So, yeah, this may well be a bug in the implementation, but I'm not sure if the current behavior is against the spec. --
