Skip to content

Commit 93958df

Browse files
committed
Clarifications and edits to hrtb chapter
1 parent 2f04df3 commit 93958df

File tree

2 files changed

+25
-17
lines changed

2 files changed

+25
-17
lines changed

src/trait-caching.md

-1
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,3 @@ and draw finer-grained distinctions, but that led to a serious of
5151
annoying and weird bugs like #22019 and #18290. This simple rule seems
5252
to be pretty clearly safe and also still retains a very high hit rate
5353
(~95% when compiling rustc).
54-

src/trait-hrtb.md

+25-16
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
# Higher-ranked trait bounds
22

3-
One of the more subtle concepts at work are *higher-ranked trait
3+
One of the more subtle concepts in trait resolution is *higher-ranked trait
44
bounds*. An example of such a bound is `for<'a> MyTrait<&'a isize>`.
55
Let's walk through how selection on higher-ranked trait references
66
works.
77

88
## Basic matching and skolemization leaks
99

10-
Let's walk through the test `compile-fail/hrtb-just-for-static.rs` to see
11-
how it works. The test starts with the trait `Foo`:
10+
Suppose we have a trait `Foo`:
1211

1312
```rust
1413
trait Foo<X> {
@@ -33,25 +32,34 @@ impl<'a> Foo<&'a isize> for AnyInt { }
3332

3433
And the question is, does `AnyInt : for<'a> Foo<&'a isize>`? We want the
3534
answer to be yes. The algorithm for figuring it out is closely related
36-
to the subtyping for higher-ranked types (which is described in
37-
`middle::infer::higher_ranked::doc`, but also in a [paper by SPJ] that
38-
I recommend you read).
35+
to the subtyping for higher-ranked types (which is described in [here][hrsubtype]
36+
and also in a [paper by SPJ]. If you wish to understand higher-ranked
37+
subtyping, we recommend you read the paper). There are a few parts:
3938

40-
1. Skolemize the obligation.
39+
**TODO**: We should define _skolemize_.
40+
41+
1. _Skolemize_ the obligation.
4142
2. Match the impl against the skolemized obligation.
42-
3. Check for skolemization leaks.
43+
3. Check for _skolemization leaks_.
4344

45+
[hrsubtype]: https://github.com/rust-lang/rust/tree/master/src/librustc/infer/higher_ranked/README.md
4446
[paper by SPJ]: http://research.microsoft.com/en-us/um/people/simonpj/papers/higher-rank/
4547

46-
So let's work through our example. The first thing we would do is to
48+
So let's work through our example.
49+
50+
1. The first thing we would do is to
4751
skolemize the obligation, yielding `AnyInt : Foo<&'0 isize>` (here `'0`
48-
represents skolemized region #0). Note that now have no quantifiers;
52+
represents skolemized region #0). Note that we now have no quantifiers;
4953
in terms of the compiler type, this changes from a `ty::PolyTraitRef`
5054
to a `TraitRef`. We would then create the `TraitRef` from the impl,
5155
using fresh variables for it's bound regions (and thus getting
52-
`Foo<&'$a isize>`, where `'$a` is the inference variable for `'a`). Next
56+
`Foo<&'$a isize>`, where `'$a` is the inference variable for `'a`).
57+
58+
2. Next
5359
we relate the two trait refs, yielding a graph with the constraint
54-
that `'0 == '$a`. Finally, we check for skolemization "leaks" – a
60+
that `'0 == '$a`.
61+
62+
3. Finally, we check for skolemization "leaks" – a
5563
leak is basically any attempt to relate a skolemized region to another
5664
skolemized region, or to any region that pre-existed the impl match.
5765
The leak check is done by searching from the skolemized region to find
@@ -75,6 +83,8 @@ skolemized to `'0` and the impl trait reference is instantiated to
7583
like `'static == '0`. This means that the taint set for `'0` is `{'0,
7684
'static}`, which fails the leak check.
7785

86+
**TODO**: This is because `'static` is not a region variable but is in the taint set, right?
87+
7888
## Higher-ranked trait obligations
7989

8090
Once the basic matching is done, we get to another interesting topic:
@@ -96,9 +106,9 @@ impl<X,F> Foo<X> for F
96106
}
97107
```
98108

99-
Now let's say we have a obligation `for<'a> Foo<&'a isize>` and we match
109+
Now let's say we have a obligation `Baz: for<'a> Foo<&'a isize>` and we match
100110
this impl. What obligation is generated as a result? We want to get
101-
`for<'a> Bar<&'a isize>`, but how does that happen?
111+
`Baz: for<'a> Bar<&'a isize>`, but how does that happen?
102112

103113
After the matching, we are in a position where we have a skolemized
104114
substitution like `X => &'0 isize`. If we apply this substitution to the
@@ -112,5 +122,4 @@ from. (This is done in `higher_ranked::plug_leaks`). We know that the
112122
leak check passed, so this taint set consists solely of the skolemized
113123
region itself plus various intermediate region variables. We then walk
114124
the trait-reference and convert every region in that taint set back to
115-
a late-bound region, so in this case we'd wind up with `for<'a> F :
116-
Bar<&'a isize>`.
125+
a late-bound region, so in this case we'd wind up with `Baz: for<'a> Bar<&'a isize>`.

0 commit comments

Comments
 (0)