On Saturday, 28 February 2015 at 06:37:40 UTC, Zach the Mystic
wrote:
On Friday, 27 February 2015 at 23:18:24 UTC, Marc Schütz wrote:
I think I have an inference algorithm that works. It can infer
the required scope levels for local variables given the
constraints of function parameters, and it can even infer the
annotations for the parameters (in template functions). It can
also cope with local variables that are explicitly declared as
`scope`, though these are mostly unnecessary.
Interestingly, the rvalue/lvalue problem deadalnix found is
only relevant during assignment checking, but not during
inference. That's because we are free to widen the scope of
variables that are to be inferred as needed.
It's based on two principles:
* We start with the minimum possible scope a variable may
have, which is empty for local variables, and its own lifetime
for parameters.
* When a scoped value is stored somewhere, it is then
reachable through the destination. Therefore, assuming the
source's scope is fixed, the destination's scope must be
widened to accommodate the source's scope.
* From the opposite viewpoint, a value that is to be stored
somewhere must have at least the destination's scope.
Therefore, assuming the destination's scope is fixed, the
source's scope needs to be widened accordingly.
I haven't formalized it yet, but I posted a very detailed
step-by-step demonstration on my wiki talk page (nicer to read
because it has syntax highlighting):
http://wiki.dlang.org/User_talk:Schuetzm/scope2
I need to sleep as well right now. But I still don't understand
where the cycles come from. Taken from your example:
*b = c;
// assignment from `c`:
// => SCOPE(c) |= SCOPE(*b)
// => DEFER because SCOPE(*b) = SCOPE(b) is incomplete
`c` is merely being copied, but you indicate here that it will
now inherit b's (or some part of b's) scope. Why would c's
scope inherit b's when it is merely being copied and not
written to?
Should have written that after I slept :-P The second point
(widening the destinations scope) is wrong, it would need to be
narrowed. But it's also unnecessary.
However, the part you quoted is still relevant (though also
wrong): This is only about inference, not about checking. We
start with the smallest possible scope (empty: []), and
successively widen the scope, until all assignments are valid. In
the extreme case, the scope will be widened to [static], because,
no matter how restricted a destination is, it can always contain
a reference to a value with infinite lifetime.
I corrected the examples, and I'm now going to add another one
that shows how `return` inference works.