GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing rustc-dev-guide.rust-lang.org — Type inference - Rust Compiler Development Guide Type inferenceType inference is the process of automatic detection of the type of an expression. It is what allows Rust to work with fewer or no type annotations, making things easier for users:
Here,
the type of The type inference is based on the standard Hindley-Milner (HM) type inference algorithm, but extended in various ways to accommodate subtyping, region inference, and higher-ranked types. A note on terminologyWe use the notation We use the terms “region” and “lifetime” interchangeably.
Both refer to the The term “bound region” refers to a region that is bound in a function signature,
such as the Creating an inference contextYou create an inference context by doing something like the following:
The Inference variablesThe main purpose of the inference context is to house a bunch of inference variables. These represent types or regions whose precise value is not yet known, but will be uncovered as we perform type-checking. If you’re familiar with the basic ideas of unification from H-M type systems, or logic languages like Prolog, this is the same concept. If you’re not, you might want to read a tutorial on how H-M type inference works, or perhaps this blog post on unification in the Chalk project. All told, the inference context stores five kinds of inference variables (as of March 2023):
All the type variables work in much the same way: you can create a new type variable,
and what you get is The region variables work somewhat differently, and are described below in a separate section. Enforcing equality / subtypingThe most basic operations you can perform in the type inferencer is equality,
which forces two types
The first When you equate things, you force them to be precisely equal.
Equating returns an The success case is perhaps more interesting.
The “primary” return type of You can similarly enforce subtyping through “Trying” equalitySometimes you would like to know if it is possible to equate two types without error.
You can test that with Be aware, though, that the success or failure of these methods is always modulo regions.
That is, two types SnapshotsAs described in the previous section on To allow for this, the inference context supports a Rather than use snapshots directly,
it is often helpful to use the methods like Subtyping obligationsOne thing worth discussing is subtyping obligations.
When you force two types to be a subtype, like However, in some cases we have to be more careful.
An example is when regions are involved.
So, if you have
This will result in a region constraint (see below) of One final interesting case is relating two unbound type variables,
like Region constraintsRegions 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:
Actually the code tends to view them as a subregion relation, but it’s the same idea:
(There are various other kinds of constraints,
such as “verifys”; see the There is one case where we do some amount of eager unification. If you have an equality constraint between two regions
we will record that fact in a unification table.
You can then use Solving region constraintsRegion constraints are only solved at the very end of typechecking, once all other constraints are known and all other obligations have been proven. There are two ways to solve region constraints right now: lexical and non-lexical. Eventually there will only be one. An exception here is the leak-check which is used during trait solving
and relies on region constraints containing higher-ranked regions.
Region
constraints in the root universe (i.e. not arising from a To solve lexical region constraints, you invoke The NLL solver (actually, the MIR type-checker) does things slightly differently.
It uses canonical queries for trait solving which use
Lexical region resolutionLexical region resolution is done by initially assigning each region variable to an empty value. We then process each outlives constraint repeatedly, growing region variables until a fixed-point is reached. Region variables can be grown using a least-upper-bound relation on the region lattice in a fairly straightforward fashion. |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |