Home Explore Blog CI



rustc

3rd chunk of `src/type-inference.md`
71e275bf7ca8a1ff84a8fa0a13fc0c16ddec170b0e1df0af0000000100000862
on which path to take. Another is in order to ensure that a series of
smaller changes take place atomically or not at all.

To allow for this, the inference context supports a `snapshot` method.
When you call it, it will start recording changes that occur from the
operations you perform. When you are done, you can either invoke
`rollback_to`, which will undo those changes, or else `confirm`, which
will make them permanent. Snapshots can be nested as long as you follow
a stack-like discipline.

Rather than use snapshots directly, it is often helpful to use the
methods like `commit_if_ok` or `probe` that encapsulate higher-level
patterns.

## Subtyping obligations

One thing worth discussing is subtyping obligations. When you force
two types to be a subtype, like `?T <: i32`, we can often convert those
into equality constraints. This follows from Rust's rather limited notion
of subtyping: so, in the above case, `?T <: i32` is equivalent to `?T = i32`.

However, in some cases we have to be more careful. For example, when
regions are involved. So if you have `?T <: &'a i32`, what we would do
is to first "generalize" `&'a i32` into a type with a region variable:
`&'?b i32`, and then unify `?T` with that (`?T = &'?b i32`). We then
relate this new variable with the original bound:

```text
&'?b i32 <: &'a i32
```

This will result in a region constraint (see below) of `'?b: 'a`.

One final interesting case is relating two unbound type variables,
like `?T <: ?U`.  In that case, we can't make progress, so we enqueue
an obligation `Subtype(?T, ?U)` and return it via the `InferOk`
mechanism. You'll have to try again when more details about `?T` or
`?U` are known.

## Region constraints

Regions are inferenced somewhat differently from types. Rather than
eagerly unifying things, we simply collect constraints as we go, but
make (almost) no attempt to solve regions. These constraints have the
form of an "outlives" constraint:

```text
'a: 'b
```

Actually the code tends to view them as a subregion relation, but it's the same
idea:

```text
'b <= 'a
```

(There are various other kinds of constraints, such as "verifys"; see

Title: Snapshots and Region Constraints in Rust Type Inference
Summary
This section explains the usage of snapshots in Rust's type inference, allowing for the recording and rolling back of changes. It also discusses higher-level methods like `commit_if_ok` and `probe` that encapsulate snapshot patterns. The section further addresses subtyping obligations, emphasizing the conversion of subtyping constraints into equality constraints, especially when regions are involved. It details the process of generalizing region-bound types and the creation of region constraints, like `'?b: 'a`. Finally, it touches on the handling of relating two unbound type variables and the creation of `Subtype(?T, ?U)` obligations. It then introduces region constraints, which are collected as outlives relationships ('a: 'b') without immediate solving.