Difference between revisions of "User talk:Schuetzm/scope2"
Line 7: | Line 7: | ||
<source lang="D"> | <source lang="D"> | ||
void foo(scope int** a) { | void foo(scope int** a) { | ||
− | // no inference for `a` | + | // no inference for `a` => self-owned |
// ("mystery scope" in your terms) | // ("mystery scope" in your terms) | ||
// => SCOPE(a) := [a] (final) | // => SCOPE(a) := [a] (final) | ||
Line 13: | Line 13: | ||
// => SCOPE(b) := [] (incomplete) | // => SCOPE(b) := [] (incomplete) | ||
b = a; | b = a; | ||
− | // | + | // scope of `a` is fixed => do nothing |
− | |||
int d; | int d; | ||
int* c; | int* c; | ||
// => SCOPE(c) := [] (incomplete) | // => SCOPE(c) := [] (incomplete) | ||
c = &d; | c = &d; | ||
− | |||
− | |||
− | |||
− | |||
*b = c; | *b = c; | ||
// assignment from `c`: | // assignment from `c`: | ||
− | // => SCOPE(c) |= SCOPE(*b) | + | // => SCOPE(c) |= SCOPE(*b) = [] | [static] (final) |
− | + | // (dereferencing loses information => static) | |
− | |||
− | // ( | ||
− | |||
− | |||
// --------------------------------------------------- | // --------------------------------------------------- | ||
// we now have: | // we now have: | ||
// SCOPE(a) = [a] | // SCOPE(a) = [a] | ||
− | // SCOPE(b) = [ | + | // SCOPE(b) = [] |
− | // SCOPE(c) = [ | + | // SCOPE(c) = [static] |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
// => all resolved | // => all resolved | ||
// --------------------------------------------------- | // --------------------------------------------------- | ||
// => satisfiable, now let's check the assignments: | // => satisfiable, now let's check the assignments: | ||
− | int** b = a; // [ | + | int** b = a; // [] := [a] => OK |
int d; | int d; | ||
− | int* c = &d; // [ | + | int* c = &d; // [static] := [d] => BAD |
− | *b = c; // [ | + | *b = c; // [static] := [static] => OK |
− | // => invalid | + | // => invalid assignment |
// note how it even traces where the bad value comes from | // note how it even traces where the bad value comes from | ||
} | } | ||
Line 61: | Line 44: | ||
<source lang="D"> | <source lang="D"> | ||
void foo(T)(T** a) { | void foo(T)(T** a) { | ||
− | // | + | // start with empty scope params |
− | // => SCOPE(a) := [ | + | // => SCOPE(a) := [] (incomplete) |
T** b; | T** b; | ||
// start with empty scope for locals | // start with empty scope for locals | ||
Line 70: | Line 53: | ||
// => SCOPE(a) |= SCOPE(b) | // => SCOPE(a) |= SCOPE(b) | ||
// => DEFER because SCOPE(b) is incomplete | // => DEFER because SCOPE(b) is incomplete | ||
− | |||
− | |||
− | |||
T d; | T d; | ||
T* c; | T* c; | ||
// => SCOPE(c) = [] (incomplete) | // => SCOPE(c) = [] (incomplete) | ||
c = &d; | c = &d; | ||
− | |||
− | |||
− | |||
− | |||
*b = c; | *b = c; | ||
// assignment from `c`: | // assignment from `c`: | ||
− | // => SCOPE(c) |= SCOPE(*b) | + | // => SCOPE(c) |= SCOPE(*b) = [] | [static] = [static] |
− | |||
− | |||
− | |||
− | |||
− | |||
// --------------------------------------------------- | // --------------------------------------------------- | ||
// we now have: | // we now have: | ||
− | // SCOPE(a) = [ | + | // SCOPE(a) = [] |
// SCOPE(b) = [] | // SCOPE(b) = [] | ||
− | // SCOPE(c) = [ | + | // SCOPE(c) = [static] |
// unresolved: | // unresolved: | ||
// SCOPE(a) |= SCOPE(b) | // SCOPE(a) |= SCOPE(b) | ||
− | // | + | // resolve: |
− | // SCOPE | + | // SCOPE(a) := [] | [] = [] |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
// => all resolved | // => all resolved | ||
// --------------------------------------------------- | // --------------------------------------------------- | ||
// => satisfiable, now let's check the assignments: | // => satisfiable, now let's check the assignments: | ||
− | int** b = a; // [ | + | int** b = a; // [] := [] => OK |
int d; | int d; | ||
− | int* c = &d; // [ | + | int* c = &d; // [static] := [d] => BAD |
− | *b = c; // [ | + | *b = c; // [static] := [static] => OK |
− | // => invalid | + | // => invalid assignment |
// again, the culprit can be detected | // again, the culprit can be detected | ||
} | } | ||
</source> | </source> |
Revision as of 10:41, 28 February 2015
Example for the inference algorithm
Applied to the function deadalnix used to demonstrate the rvalue/lvalue problem:
(1) foo()
is @safe
, making its param scoped:
void foo(scope int** a) {
// no inference for `a` => self-owned
// ("mystery scope" in your terms)
// => SCOPE(a) := [a] (final)
int** b;
// => SCOPE(b) := [] (incomplete)
b = a;
// scope of `a` is fixed => do nothing
int d;
int* c;
// => SCOPE(c) := [] (incomplete)
c = &d;
*b = c;
// assignment from `c`:
// => SCOPE(c) |= SCOPE(*b) = [] | [static] (final)
// (dereferencing loses information => static)
// ---------------------------------------------------
// we now have:
// SCOPE(a) = [a]
// SCOPE(b) = []
// SCOPE(c) = [static]
// => all resolved
// ---------------------------------------------------
// => satisfiable, now let's check the assignments:
int** b = a; // [] := [a] => OK
int d;
int* c = &d; // [static] := [d] => BAD
*b = c; // [static] := [static] => OK
// => invalid assignment
// note how it even traces where the bad value comes from
}
(2) foo()
is in a template, param scope gets inferred
void foo(T)(T** a) {
// start with empty scope params
// => SCOPE(a) := [] (incomplete)
T** b;
// start with empty scope for locals
// => SCOPE(b) := [] (incomplete)
b = a;
// only access to `a`:
// => SCOPE(a) |= SCOPE(b)
// => DEFER because SCOPE(b) is incomplete
T d;
T* c;
// => SCOPE(c) = [] (incomplete)
c = &d;
*b = c;
// assignment from `c`:
// => SCOPE(c) |= SCOPE(*b) = [] | [static] = [static]
// ---------------------------------------------------
// we now have:
// SCOPE(a) = []
// SCOPE(b) = []
// SCOPE(c) = [static]
// unresolved:
// SCOPE(a) |= SCOPE(b)
// resolve:
// SCOPE(a) := [] | [] = []
// => all resolved
// ---------------------------------------------------
// => satisfiable, now let's check the assignments:
int** b = a; // [] := [] => OK
int d;
int* c = &d; // [static] := [d] => BAD
*b = c; // [static] := [static] => OK
// => invalid assignment
// again, the culprit can be detected
}