clean up skolemiza in borrow_ck
This commit is contained in:
parent
f177b07847
commit
3c318049dc
|
|
@ -78,19 +78,19 @@ The kinds of region elements are as follows:
|
||||||
etc) control-flow graph.
|
etc) control-flow graph.
|
||||||
- Similarly, there is an element denoted `end('static)` corresponding
|
- Similarly, there is an element denoted `end('static)` corresponding
|
||||||
to the remainder of program execution after this function returns.
|
to the remainder of program execution after this function returns.
|
||||||
- There is an element `!1` for each skolemized region `!1`. This
|
- There is an element `!1` for each placeholder region `!1`. This
|
||||||
corresponds (intuitively) to some unknown set of other elements –
|
corresponds (intuitively) to some unknown set of other elements –
|
||||||
for details on skolemization, see the section
|
for details on placeholder, see the section
|
||||||
[skolemization and universes](#skol).
|
[placeholder and universes](#placeholder).
|
||||||
|
|
||||||
## Causal tracking
|
## Causal tracking
|
||||||
|
|
||||||
*to be written* – describe how we can extend the values of a variable
|
*to be written* – describe how we can extend the values of a variable
|
||||||
with causal tracking etc
|
with causal tracking etc
|
||||||
|
|
||||||
<a name="skol"></a>
|
<a name="placeholder"></a>
|
||||||
|
|
||||||
## Skolemization and universes
|
## Placeholders and universes
|
||||||
|
|
||||||
(This section describes ongoing work that hasn't landed yet.)
|
(This section describes ongoing work that hasn't landed yet.)
|
||||||
|
|
||||||
|
|
@ -117,7 +117,7 @@ for its argument, and `bar` wants to be given a function that that
|
||||||
accepts **any** reference (so it can call it with something on its
|
accepts **any** reference (so it can call it with something on its
|
||||||
stack, for example). But *how* do we reject it and *why*?
|
stack, for example). But *how* do we reject it and *why*?
|
||||||
|
|
||||||
### Subtyping and skolemization
|
### Subtyping and Placeholder
|
||||||
|
|
||||||
When we type-check `main`, and in particular the call `bar(foo)`, we
|
When we type-check `main`, and in particular the call `bar(foo)`, we
|
||||||
are going to wind up with a subtyping relationship like this one:
|
are going to wind up with a subtyping relationship like this one:
|
||||||
|
|
@ -129,10 +129,10 @@ the type of `foo` the type `bar` expects
|
||||||
```
|
```
|
||||||
|
|
||||||
We handle this sort of subtyping by taking the variables that are
|
We handle this sort of subtyping by taking the variables that are
|
||||||
bound in the supertype and **skolemizing** them: this means that we
|
bound in the supertype and **placeholder** them: this means that we
|
||||||
replace them with
|
replace them with
|
||||||
[universally quantified](../appendix/background.html#quantified)
|
[universally quantified](../appendix/background.html#quantified)
|
||||||
representatives, written like `!1`. We call these regions "skolemized
|
representatives, written like `!1`. We call these regions "placeholder
|
||||||
regions" – they represent, basically, "some unknown region".
|
regions" – they represent, basically, "some unknown region".
|
||||||
|
|
||||||
Once we've done that replacement, we have the following relation:
|
Once we've done that replacement, we have the following relation:
|
||||||
|
|
@ -163,7 +163,7 @@ should yield up an error (eventually).
|
||||||
|
|
||||||
### What is a universe
|
### What is a universe
|
||||||
|
|
||||||
In the previous section, we introduced the idea of a skolemized
|
In the previous section, we introduced the idea of a placeholder
|
||||||
region, and we denoted it `!1`. We call this number `1` the **universe
|
region, and we denoted it `!1`. We call this number `1` the **universe
|
||||||
index**. The idea of a "universe" is that it is a set of names that
|
index**. The idea of a "universe" is that it is a set of names that
|
||||||
are in scope within some type or at some point. Universes are formed
|
are in scope within some type or at some point. Universes are formed
|
||||||
|
|
@ -198,7 +198,7 @@ fn bar<'a, T>(t: &'a T) {
|
||||||
```
|
```
|
||||||
|
|
||||||
Here, the name `'b` is not part of the root universe. Instead, when we
|
Here, the name `'b` is not part of the root universe. Instead, when we
|
||||||
"enter" into this `for<'b>` (e.g., by skolemizing it), we will create
|
"enter" into this `for<'b>` (e.g., by placeholder it), we will create
|
||||||
a child universe of the root, let's call it U1:
|
a child universe of the root, let's call it U1:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
|
|
@ -274,25 +274,25 @@ Here, the only way for the two foralls to interact would be through X,
|
||||||
but neither Y nor Z are in scope when X is declared, so its value
|
but neither Y nor Z are in scope when X is declared, so its value
|
||||||
cannot reference either of them.
|
cannot reference either of them.
|
||||||
|
|
||||||
### Universes and skolemized region elements
|
### Universes and placeholder region elements
|
||||||
|
|
||||||
But where does that error come from? The way it happens is like this.
|
But where does that error come from? The way it happens is like this.
|
||||||
When we are constructing the region inference context, we can tell
|
When we are constructing the region inference context, we can tell
|
||||||
from the type inference context how many skolemized variables exist
|
from the type inference context how many placeholder variables exist
|
||||||
(the `InferCtxt` has an internal counter). For each of those, we
|
(the `InferCtxt` has an internal counter). For each of those, we
|
||||||
create a corresponding universal region variable `!n` and a "region
|
create a corresponding universal region variable `!n` and a "region
|
||||||
element" `skol(n)`. This corresponds to "some unknown set of other
|
element" `placeholder(n)`. This corresponds to "some unknown set of other
|
||||||
elements". The value of `!n` is `{skol(n)}`.
|
elements". The value of `!n` is `{placeholder(n)}`.
|
||||||
|
|
||||||
At the same time, we also give each existential variable a
|
At the same time, we also give each existential variable a
|
||||||
**universe** (also taken from the `InferCtxt`). This universe
|
**universe** (also taken from the `InferCtxt`). This universe
|
||||||
determines which skolemized elements may appear in its value: For
|
determines which placeholder elements may appear in its value: For
|
||||||
example, a variable in universe U3 may name `skol(1)`, `skol(2)`, and
|
example, a variable in universe U3 may name `placeholder(1)`, `placeholder(2)`, and
|
||||||
`skol(3)`, but not `skol(4)`. Note that the universe of an inference
|
`placeholder(3)`, but not `placeholder(4)`. Note that the universe of an inference
|
||||||
variable controls what region elements **can** appear in its value; it
|
variable controls what region elements **can** appear in its value; it
|
||||||
does not say region elements **will** appear.
|
does not say region elements **will** appear.
|
||||||
|
|
||||||
### Skolemization and outlives constraints
|
### Placeholders and outlives constraints
|
||||||
|
|
||||||
In the region inference engine, outlives constraints have the form:
|
In the region inference engine, outlives constraints have the form:
|
||||||
|
|
||||||
|
|
@ -313,23 +313,23 @@ are present in `value(V2)` and we add those nodes to `value(V1)`. If
|
||||||
we reach a return point, we add in any `end(X)` elements. That part
|
we reach a return point, we add in any `end(X)` elements. That part
|
||||||
remains unchanged.
|
remains unchanged.
|
||||||
|
|
||||||
But then *after that* we want to iterate over the skolemized `skol(x)`
|
But then *after that* we want to iterate over the placeholder `placeholder(x)`
|
||||||
elements in V2 (each of those must be visible to `U(V2)`, but we
|
elements in V2 (each of those must be visible to `U(V2)`, but we
|
||||||
should be able to just assume that is true, we don't have to check
|
should be able to just assume that is true, we don't have to check
|
||||||
it). We have to ensure that `value(V1)` outlives each of those
|
it). We have to ensure that `value(V1)` outlives each of those
|
||||||
skolemized elements.
|
placeholder elements.
|
||||||
|
|
||||||
Now there are two ways that could happen. First, if `U(V1)` can see
|
Now there are two ways that could happen. First, if `U(V1)` can see
|
||||||
the universe `x` (i.e., `x <= U(V1)`), then we can just add `skol(x)`
|
the universe `x` (i.e., `x <= U(V1)`), then we can just add `placeholder(x)`
|
||||||
to `value(V1)` and be done. But if not, then we have to approximate:
|
to `value(V1)` and be done. But if not, then we have to approximate:
|
||||||
we may not know what set of elements `skol(x)` represents, but we
|
we may not know what set of elements `placeholder(x)` represents, but we
|
||||||
should be able to compute some sort of **upper bound** B for it –
|
should be able to compute some sort of **upper bound** B for it –
|
||||||
some region B that outlives `skol(x)`. For now, we'll just use
|
some region B that outlives `placeholder(x)`. For now, we'll just use
|
||||||
`'static` for that (since it outlives everything) – in the future, we
|
`'static` for that (since it outlives everything) – in the future, we
|
||||||
can sometimes be smarter here (and in fact we have code for doing this
|
can sometimes be smarter here (and in fact we have code for doing this
|
||||||
already in other contexts). Moreover, since `'static` is in the root
|
already in other contexts). Moreover, since `'static` is in the root
|
||||||
universe U0, we know that all variables can see it – so basically if
|
universe U0, we know that all variables can see it – so basically if
|
||||||
we find that `value(V2)` contains `skol(x)` for some universe `x`
|
we find that `value(V2)` contains `placeholder(x)` for some universe `x`
|
||||||
that `V1` can't see, then we force `V1` to `'static`.
|
that `V1` can't see, then we force `V1` to `'static`.
|
||||||
|
|
||||||
### Extending the "universal regions" check
|
### Extending the "universal regions" check
|
||||||
|
|
@ -337,20 +337,20 @@ that `V1` can't see, then we force `V1` to `'static`.
|
||||||
After all constraints have been propagated, the NLL region inference
|
After all constraints have been propagated, the NLL region inference
|
||||||
has one final check, where it goes over the values that wound up being
|
has one final check, where it goes over the values that wound up being
|
||||||
computed for each universal region and checks that they did not get
|
computed for each universal region and checks that they did not get
|
||||||
'too large'. In our case, we will go through each skolemized region
|
'too large'. In our case, we will go through each placeholder region
|
||||||
and check that it contains *only* the `skol(u)` element it is known to
|
and check that it contains *only* the `placeholder(u)` element it is known to
|
||||||
outlive. (Later, we might be able to know that there are relationships
|
outlive. (Later, we might be able to know that there are relationships
|
||||||
between two skolemized regions and take those into account, as we do
|
between two placeholder regions and take those into account, as we do
|
||||||
for universal regions from the fn signature.)
|
for universal regions from the fn signature.)
|
||||||
|
|
||||||
Put another way, the "universal regions" check can be considered to be
|
Put another way, the "universal regions" check can be considered to be
|
||||||
checking constraints like:
|
checking constraints like:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
{skol(1)}: V1
|
{placeholder(1)}: V1
|
||||||
```
|
```
|
||||||
|
|
||||||
where `{skol(1)}` is like a constant set, and V1 is the variable we
|
where `{placeholder(1)}` is like a constant set, and V1 is the variable we
|
||||||
made to represent the `!1` region.
|
made to represent the `!1` region.
|
||||||
|
|
||||||
## Back to our example
|
## Back to our example
|
||||||
|
|
@ -365,7 +365,7 @@ fn(&'static u32) <: fn(&'!1 u32) @ P // this point P is not imp't here
|
||||||
The region inference engine will create a region element domain like this:
|
The region inference engine will create a region element domain like this:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
{ CFG; end('static); skol(1) }
|
{ CFG; end('static); placeholder(1) }
|
||||||
--- ------------ ------- from the universe `!1`
|
--- ------------ ------- from the universe `!1`
|
||||||
| 'static is always in scope
|
| 'static is always in scope
|
||||||
all points in the CFG; not especially relevant here
|
all points in the CFG; not especially relevant here
|
||||||
|
|
@ -377,7 +377,7 @@ will have initial values like so:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Vs = { CFG; end('static) } // it is in U0, so can't name anything else
|
Vs = { CFG; end('static) } // it is in U0, so can't name anything else
|
||||||
V1 = { skol(1) }
|
V1 = { placeholder(1) }
|
||||||
```
|
```
|
||||||
|
|
||||||
From the subtyping constraint above, we would have an outlives constraint like
|
From the subtyping constraint above, we would have an outlives constraint like
|
||||||
|
|
@ -390,7 +390,7 @@ To process this, we would grow the value of V1 to include all of Vs:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Vs = { CFG; end('static) }
|
Vs = { CFG; end('static) }
|
||||||
V1 = { CFG; end('static), skol(1) }
|
V1 = { CFG; end('static), placeholder(1) }
|
||||||
```
|
```
|
||||||
|
|
||||||
At that point, constraint propagation is complete, because all the
|
At that point, constraint propagation is complete, because all the
|
||||||
|
|
@ -411,7 +411,7 @@ for<'a> fn(&'a u32, &'a u32)
|
||||||
for<'b, 'c> fn(&'b u32, &'c u32)
|
for<'b, 'c> fn(&'b u32, &'c u32)
|
||||||
```
|
```
|
||||||
|
|
||||||
Here we would skolemize the supertype, as before, yielding:
|
Here we would placeholer the supertype, as before, yielding:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
for<'a> fn(&'a u32, &'a u32)
|
for<'a> fn(&'a u32, &'a u32)
|
||||||
|
|
@ -476,7 +476,7 @@ an error. That's good: the problem is that we've gone from a fn that promises
|
||||||
to return one of its two arguments, to a fn that is promising to return the
|
to return one of its two arguments, to a fn that is promising to return the
|
||||||
first one. That is unsound. Let's see how it plays out.
|
first one. That is unsound. Let's see how it plays out.
|
||||||
|
|
||||||
First, we skolemize the supertype:
|
First, we placeholder the supertype:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
for<'a> fn(&'a u32, &'a u32) -> &'a u32
|
for<'a> fn(&'a u32, &'a u32) -> &'a u32
|
||||||
|
|
@ -512,26 +512,26 @@ V3: V1
|
||||||
Those variables will have these initial values:
|
Those variables will have these initial values:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
V1 in U1 = {skol(1)}
|
V1 in U1 = {placeholder(1)}
|
||||||
V2 in U2 = {skol(2)}
|
V2 in U2 = {placeholder(2)}
|
||||||
V3 in U2 = {}
|
V3 in U2 = {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Now because of the `V3: V1` constraint, we have to add `skol(1)` into `V3` (and
|
Now because of the `V3: V1` constraint, we have to add `placeholder(1)` into `V3` (and
|
||||||
indeed it is visible from `V3`), so we get:
|
indeed it is visible from `V3`), so we get:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
V3 in U2 = {skol(1)}
|
V3 in U2 = {placeholder(1)}
|
||||||
```
|
```
|
||||||
|
|
||||||
then we have this constraint `V2: V3`, so we wind up having to enlarge
|
then we have this constraint `V2: V3`, so we wind up having to enlarge
|
||||||
`V2` to include `skol(1)` (which it can also see):
|
`V2` to include `placeholder(1)` (which it can also see):
|
||||||
|
|
||||||
```text
|
```text
|
||||||
V2 in U2 = {skol(1), skol(2)}
|
V2 in U2 = {placeholder(1), placeholder(2)}
|
||||||
```
|
```
|
||||||
|
|
||||||
Now constraint propagation is done, but when we check the outlives
|
Now constraint propagation is done, but when we check the outlives
|
||||||
relationships, we find that `V2` includes this new element `skol(1)`,
|
relationships, we find that `V2` includes this new element `placeholder(1)`,
|
||||||
so we report an error.
|
so we report an error.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue