I have recently added a note about "init property is sometimes unsafe".
https://github.com/D-Programming-Language/d-programming-language.org/pull/201 To reduce the risk, I have proposed an enhancement for .init property usage. http://d.puremagic.com/issues/show_bug.cgi?id=8752 Kenji Hara 2012/12/16 js.mdnq <[email protected]> > On Saturday, 15 December 2012 at 20:20:10 UTC, H. S. Teoh wrote: > >> On Sat, Dec 15, 2012 at 12:02:16PM -0800, Jonathan M Davis wrote: >> >>> On Saturday, December 15, 2012 11:45:10 H. S. Teoh wrote: >>> > Ironically enough, Andrei in the subsequent paragraph > discourages >>> > the use of such nested structs, whereas Walter's article > promotes >>> > the use of such Voldemort types as a "happy discovery". :) >>> >>> No, the real irony is that it's Andrei who promoted them in the first >>> place. :) >>> >> >> Heh. :) >> >> >> >> We _are_ finding some serious issues with them though (e.g. they don't >>> work with init and apparently can't work with init), and there has >>> been some discussion of ditching them due to such issues, but no >>> consensus has been reached on that. >>> >> [...] >> >> >> Hmm, that's true. They can't possibly work with init: if you do >> something like: >> >> auto func(int x) { >> struct V { >> @property int value() { return x; } >> } >> return V(); >> } >> auto v = func(123); >> auto u = v.init; // <-- what happens here? >> writeln(u.value); // <-- and here? >> >> It seems that we'd have to make .init illegal on these Voldemort >> structs. But that breaks consistency with the rest of the language that >> every type must have an .init value. >> >> Alternatively, .init can implicitly create a context where the value of >> x is set to int.init. But this is unnecessary (it's supposed to be a >> *Voldemort* type!) and very ugly (why are we creating a function's local >> context when it isn't even being called?), not to mention useless >> (u.value will return a nonsensical value). >> >> Or, perhaps a less intrusive workaround, is to have .init set the hidden >> context pointer to null, and you'll get a null deference when accessing >> u.value. Which is not pretty either, since no pointers or references are >> apparent in V.value; it's implicit. >> >> It seems that the only clean way to do this is to use a class instead of >> a struct, since the .init value will conveniently just be null, thereby >> sidestepping the problem. >> >> >> T >> > > > auto func(int x) { > struct V { > int value() { return x; } > > @property V init() { return this; } > > } > > return V(); > } > auto v = func(123); > auto u = v.init; // <-- what happens here? > auto x = u.value; > writeln(x); > > If you add an init property then it is not null. I'm not sure if this is > the correct behavior as I just jumped into this discussion and I'm not sure > if I understand exactly what the problem with these types of structs are. > (as far as I can tell they simply let you pass "sets" of data from a > function rather easily while also keeping the details hidden(impossible to > directly instantiate the struct since it is hidden inside the func) > > In any case, when stepping through the code above, I noticed that init > being called but resulting in u.value throwing a null exception. so I added > an init property to V and then got the expected behavior. Probably too easy > to be the correct solution but who knows ;) >
