clean up skolemiza in traits
This commit is contained in:
parent
3c318049dc
commit
e4df53b93d
|
|
@ -154,7 +154,7 @@ The key point is that, on success, unification can also give back to
|
|||
us a set of subgoals that still remain to be proven (it can also give
|
||||
back region constraints, but those are not relevant here).
|
||||
|
||||
Whenever unification encounters an (unskolemized!) associated type
|
||||
Whenever unification encounters an (un-placeholder!) associated type
|
||||
projection P being equated with some other type T, it always succeeds,
|
||||
but it produces a subgoal `ProjectionEq(P = T)` that is propagated
|
||||
back up. Thus it falls to the ordinary workings of the trait system
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ but *replay* its effects on the type variables.
|
|||
## An example
|
||||
|
||||
The high-level idea of how the cache works is that we first replace
|
||||
all unbound inference variables with skolemized versions. Therefore,
|
||||
all unbound inference variables with placeholder versions. Therefore,
|
||||
if we had a trait reference `usize : Foo<$t>`, where `$t` is an unbound
|
||||
inference variable, we might replace it with `usize : Foo<$0>`, where
|
||||
`$0` is a skolemized type. We would then look this up in the cache.
|
||||
`$0` is a placeholder type. We would then look this up in the cache.
|
||||
|
||||
If we found a hit, the hit would tell us the immediate next step to
|
||||
take in the selection process (e.g. apply impl #22, or apply where
|
||||
|
|
@ -37,7 +37,7 @@ we would [confirm] `ImplCandidate(22)`, which would (as a side-effect) unify
|
|||
[confirm]: ./resolution.html#confirmation
|
||||
|
||||
Now, at some later time, we might come along and see a `usize :
|
||||
Foo<$u>`. When skolemized, this would yield `usize : Foo<$0>`, just as
|
||||
Foo<$u>`. When placeholder, this would yield `usize : Foo<$0>`, just as
|
||||
before, and hence the cache lookup would succeed, yielding
|
||||
`ImplCandidate(22)`. We would confirm `ImplCandidate(22)` which would
|
||||
(as a side-effect) unify `$u` with `isize`.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ bounds*. An example of such a bound is `for<'a> MyTrait<&'a isize>`.
|
|||
Let's walk through how selection on higher-ranked trait references
|
||||
works.
|
||||
|
||||
## Basic matching and skolemization leaks
|
||||
## Basic matching and placeholder leaks
|
||||
|
||||
Suppose we have a trait `Foo`:
|
||||
|
||||
|
|
@ -36,11 +36,11 @@ to the subtyping for higher-ranked types (which is described [here][hrsubtype]
|
|||
and also in a [paper by SPJ]. If you wish to understand higher-ranked
|
||||
subtyping, we recommend you read the paper). There are a few parts:
|
||||
|
||||
**TODO**: We should define _skolemize_.
|
||||
**TODO**: We should define _placeholder_.
|
||||
|
||||
1. _Skolemize_ the obligation.
|
||||
2. Match the impl against the skolemized obligation.
|
||||
3. Check for _skolemization leaks_.
|
||||
2. Match the impl against the placeholder obligation.
|
||||
3. Check for _placeholder leaks_.
|
||||
|
||||
[hrsubtype]: https://github.com/rust-lang/rust/tree/master/src/librustc/infer/higher_ranked/README.md
|
||||
[paper by SPJ]: http://research.microsoft.com/en-us/um/people/simonpj/papers/higher-rank/
|
||||
|
|
@ -48,8 +48,8 @@ subtyping, we recommend you read the paper). There are a few parts:
|
|||
So let's work through our example.
|
||||
|
||||
1. The first thing we would do is to
|
||||
skolemize the obligation, yielding `AnyInt : Foo<&'0 isize>` (here `'0`
|
||||
represents skolemized region #0). Note that we now have no quantifiers;
|
||||
placeholder the obligation, yielding `AnyInt : Foo<&'0 isize>` (here `'0`
|
||||
represents placeholder region #0). Note that we now have no quantifiers;
|
||||
in terms of the compiler type, this changes from a `ty::PolyTraitRef`
|
||||
to a `TraitRef`. We would then create the `TraitRef` from the impl,
|
||||
using fresh variables for it's bound regions (and thus getting
|
||||
|
|
@ -59,10 +59,10 @@ using fresh variables for it's bound regions (and thus getting
|
|||
we relate the two trait refs, yielding a graph with the constraint
|
||||
that `'0 == '$a`.
|
||||
|
||||
3. Finally, we check for skolemization "leaks" – a
|
||||
leak is basically any attempt to relate a skolemized region to another
|
||||
skolemized region, or to any region that pre-existed the impl match.
|
||||
The leak check is done by searching from the skolemized region to find
|
||||
3. Finally, we check for placeholder "leaks" – a
|
||||
leak is basically any attempt to relate a placeholder region to another
|
||||
placeholder region, or to any region that pre-existed the impl match.
|
||||
The leak check is done by searching from the placeholder region to find
|
||||
the set of regions that it is related to in any way. This is called
|
||||
the "taint" set. To pass the check, that set must consist *solely* of
|
||||
itself and region variables from the impl. If the taint set includes
|
||||
|
|
@ -78,7 +78,7 @@ impl Foo<&'static isize> for StaticInt;
|
|||
|
||||
We want the obligation `StaticInt : for<'a> Foo<&'a isize>` to be
|
||||
considered unsatisfied. The check begins just as before. `'a` is
|
||||
skolemized to `'0` and the impl trait reference is instantiated to
|
||||
placeholder to `'0` and the impl trait reference is instantiated to
|
||||
`Foo<&'static isize>`. When we relate those two, we get a constraint
|
||||
like `'static == '0`. This means that the taint set for `'0` is `{'0,
|
||||
'static}`, which fails the leak check.
|
||||
|
|
@ -111,16 +111,16 @@ Now let's say we have a obligation `Baz: for<'a> Foo<&'a isize>` and we match
|
|||
this impl. What obligation is generated as a result? We want to get
|
||||
`Baz: for<'a> Bar<&'a isize>`, but how does that happen?
|
||||
|
||||
After the matching, we are in a position where we have a skolemized
|
||||
After the matching, we are in a position where we have a placeholder
|
||||
substitution like `X => &'0 isize`. If we apply this substitution to the
|
||||
impl obligations, we get `F : Bar<&'0 isize>`. Obviously this is not
|
||||
directly usable because the skolemized region `'0` cannot leak out of
|
||||
directly usable because the placeholder region `'0` cannot leak out of
|
||||
our computation.
|
||||
|
||||
What we do is to create an inverse mapping from the taint set of `'0`
|
||||
back to the original bound region (`'a`, here) that `'0` resulted
|
||||
from. (This is done in `higher_ranked::plug_leaks`). We know that the
|
||||
leak check passed, so this taint set consists solely of the skolemized
|
||||
leak check passed, so this taint set consists solely of the placeholder
|
||||
region itself plus various intermediate region variables. We then walk
|
||||
the trait-reference and convert every region in that taint set back to
|
||||
a late-bound region, so in this case we'd wind up with
|
||||
|
|
|
|||
Loading…
Reference in New Issue