A nice interface for working with the infcx. The basic idea is to
do infcx.at(cause, param_env), which sets the “cause” of the
operation as well as the surrounding parameter environment. Then
you can do something like .sub(a, b) or .eq(a, b) to create a
subtype or equality relationship respectively. The first argument
is always the “expected” output from the POV of diagnostics.
Canonicalization is the key to constructing a query in the
middle of type inference. Ordinarily, it is not possible to store
types from type inference in query keys, because they contain
references to inference variables whose lifetimes are too short
and so forth. Canonicalizing a value T1 using canonicalize_query
produces two things:
This module contains the definitions of most TypeRelations in the type system
(except for some relations used for diagnostics and heuristics in the compiler).
As well as the implementation of Relate for interned things (Ty/Const/etc).
This type contains all the things within InferCtxt that sit within a
RefCell and are involved with taking/rolling back snapshots. Snapshot
operations are hot enough that we want only one call to borrow_mut per
call to start_snapshot and rollback_to.
InferOk<'tcx, ()> is used a lot. It may seem like a useless wrapper
around PredicateObligations<'tcx>, but it has one important property:
because InferOk is marked with #[must_use], if you have a method
InferCtxt::f that returns InferResult<'tcx, ()> and you call it with
infcx.f()?; you’ll get a warning about the obligations being discarded
without use, which is probably unintentional and has been a source of bugs
in the past.