On Friday, 27 July 2018 at 11:44:10 UTC, aliak wrote:
A) I'd suggest "@nodestruct" instead, since it sounds like that
what it's supposed to do?
Yes-ish, but it's also supposed to fill the hole in the
typesystem created by T.init, and "you can only assign T.init to
types marked @nodestruct" sounds kind of magic.
B) is this basically for the case of invariants being run
before destructors where T.init are not valid runtime instances
of T?
Yep, that's the reason I'm looking at it.
C) If it is, then this seems to me that this is something that
should just work without a programmer needing to know about how
T.init and invariants are implemented, so an implementation
that doesn't call invariants before a destructor only if an
instance was never constructed at runtime is maybe the way to
go? Though I have no idea how possible that is.
Basically impossible without giving every type a hidden "bool
initialized" field. So, basically impossible.
The advantage of doing it with @manualScoped is twofold. First,
it also covers the case of opAssign methods taking parameters
that don't need to be destroyed at scope end. Second, even a
constructor may return a T.init (and, for instance, increment a
static variable), so if being T.init skipped the destructor we'd
again get a constructor/destructor mismatch. @manualScoped makes
it clear this is a variable that contains a value with a manually
managed lifetime, so users take responsibility to call
moveEmplace/destroy as required to make constructor/destructor
calls match up, which is the goal.
Basically, think of a @manualScoped variable as a "weak value" in
analogy to weak references.
Cheers,
- Ali
maybe your PR where invariants is not called before a
destructor if an instance is a T.init is maybe the way to go?
[0]
The PR itself was just a way to hack around this. The problem
isn't the invariant check on destruction, the problem is the
destruction without the matching construction.