[−][src]Trait rustc_trait_selection::opaque_types::InferCtxtExt
Required methods
pub fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
&self,
parent_def_id: LocalDefId,
body_id: HirId,
param_env: ParamEnv<'tcx>,
value: T,
value_span: Span
) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)>[src]
&self,
parent_def_id: LocalDefId,
body_id: HirId,
param_env: ParamEnv<'tcx>,
value: T,
value_span: Span
) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)>
pub fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(
&self,
opaque_types: &OpaqueTypeMap<'tcx>,
free_region_relations: &FRR
)[src]
&self,
opaque_types: &OpaqueTypeMap<'tcx>,
free_region_relations: &FRR
)
pub fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
&self,
def_id: DefId,
opaque_defn: &OpaqueTypeDecl<'tcx>,
mode: GenerateMemberConstraints,
free_region_relations: &FRR
)[src]
&self,
def_id: DefId,
opaque_defn: &OpaqueTypeDecl<'tcx>,
mode: GenerateMemberConstraints,
free_region_relations: &FRR
)
pub fn generate_member_constraint(
&self,
concrete_ty: Ty<'tcx>,
opaque_defn: &OpaqueTypeDecl<'tcx>,
opaque_type_def_id: DefId,
first_own_region_index: usize
)[src]
&self,
concrete_ty: Ty<'tcx>,
opaque_defn: &OpaqueTypeDecl<'tcx>,
opaque_type_def_id: DefId,
first_own_region_index: usize
)
pub fn member_constraint_feature_gate(
&self,
opaque_defn: &OpaqueTypeDecl<'tcx>,
opaque_type_def_id: DefId,
conflict1: Region<'tcx>,
conflict2: Region<'tcx>
) -> bool[src]
&self,
opaque_defn: &OpaqueTypeDecl<'tcx>,
opaque_type_def_id: DefId,
conflict1: Region<'tcx>,
conflict2: Region<'tcx>
) -> bool
pub fn infer_opaque_definition_from_instantiation(
&self,
def_id: DefId,
substs: SubstsRef<'tcx>,
instantiated_ty: Ty<'tcx>,
span: Span
) -> Ty<'tcx>[src]
&self,
def_id: DefId,
substs: SubstsRef<'tcx>,
instantiated_ty: Ty<'tcx>,
span: Span
) -> Ty<'tcx>
Implementors
impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx>[src]
pub fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
&self,
parent_def_id: LocalDefId,
body_id: HirId,
param_env: ParamEnv<'tcx>,
value: T,
value_span: Span
) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)>[src]
&self,
parent_def_id: LocalDefId,
body_id: HirId,
param_env: ParamEnv<'tcx>,
value: T,
value_span: Span
) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)>
Replaces all opaque types in value with fresh inference variables
and creates appropriate obligations. For example, given the input:
impl Iterator<Item = impl Debug>
this method would create two type variables, ?0 and ?1. It would
return the type ?0 but also the obligations:
?0: Iterator<Item = ?1> ?1: Debug
Moreover, it returns a OpaqueTypeMap that would map ?0 to
info about the impl Iterator<..> type and ?1 to info about
the impl Debug type.
Parameters
parent_def_id-- theDefIdof the function in which the opaque type is definedbody_id-- the body-id with which the resulting obligations should be associatedparam_env-- the in-scope parameter environment to be used for obligationsvalue-- the value within which we are instantiating opaque typesvalue_span-- the span where the value came from, used in error reporting
pub fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(
&self,
opaque_types: &OpaqueTypeMap<'tcx>,
free_region_relations: &FRR
)[src]
&self,
opaque_types: &OpaqueTypeMap<'tcx>,
free_region_relations: &FRR
)
Given the map opaque_types containing the opaque
impl Trait types whose underlying, hidden types are being
inferred, this method adds constraints to the regions
appearing in those underlying hidden types to ensure that they
at least do not refer to random scopes within the current
function. These constraints are not (quite) sufficient to
guarantee that the regions are actually legal values; that
final condition is imposed after region inference is done.
The Problem
Let's work through an example to explain how it works. Assume the current function is as follows:
fn foo<'a, 'b>(..) -> (impl Bar<'a>, impl Bar<'b>)
Here, we have two impl Trait types whose values are being
inferred (the impl Bar<'a> and the impl Bar<'b>). Conceptually, this is sugar for a setup where we
define underlying opaque types (Foo1, Foo2) and then, in
the return type of foo, we reference those definitions:
type Foo1<'x> = impl Bar<'x>;
type Foo2<'x> = impl Bar<'x>;
fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
// ^^^^ ^^
// | |
// | substs
// def_id
As indicating in the comments above, each of those references
is (in the compiler) basically a substitution (substs)
applied to the type of a suitable def_id (which identifies
Foo1 or Foo2).
Now, at this point in compilation, what we have done is to
replace each of the references (Foo1<'a>, Foo2<'b>) with
fresh inference variables C1 and C2. We wish to use the values
of these variables to infer the underlying types of Foo1 and
Foo2. That is, this gives rise to higher-order (pattern) unification
constraints like:
for<'a> (Foo1<'a> = C1)
for<'b> (Foo1<'b> = C2)
For these equation to be satisfiable, the types C1 and C2
can only refer to a limited set of regions. For example, C1
can only refer to 'static and 'a, and C2 can only refer
to 'static and 'b. The job of this function is to impose that
constraint.
Up to this point, C1 and C2 are basically just random type
inference variables, and hence they may contain arbitrary
regions. In fact, it is fairly likely that they do! Consider
this possible definition of foo:
fn foo<'a, 'b>(x: &'a i32, y: &'b i32) -> (impl Bar<'a>, impl Bar<'b>) {
(&*x, &*y)
}
Here, the values for the concrete types of the two impl traits will include inference variables:
&'0 i32
&'1 i32
Ordinarily, the subtyping rules would ensure that these are
sufficiently large. But since impl Bar<'a> isn't a specific
type per se, we don't get such constraints by default. This
is where this function comes into play. It adds extra
constraints to ensure that all the regions which appear in the
inferred type are regions that could validly appear.
This is actually a bit of a tricky constraint in general. We
want to say that each variable (e.g., '0) can only take on
values that were supplied as arguments to the opaque type
(e.g., 'a for Foo1<'a>) or 'static, which is always in
scope. We don't have a constraint quite of this kind in the current
region checker.
The Solution
We generally prefer to make <= constraints, since they
integrate best into the region solver. To do that, we find the
"minimum" of all the arguments that appear in the substs: that
is, some region which is less than all the others. In the case
of Foo1<'a>, that would be 'a (it's the only choice, after
all). Then we apply that as a least bound to the variables
(e.g., 'a <= '0).
In some cases, there is no minimum. Consider this example:
fn baz<'a, 'b>() -> impl Trait<'a, 'b> { ... }
Here we would report a more complex "in constraint", like 'r in ['a, 'b, 'static] (where 'r is some region appearing in
the hidden type).
Constrain regions, not the hidden concrete type
Note that generating constraints on each region Rc is not
the same as generating an outlives constraint on Tc iself.
For example, if we had a function like this:
fn foo<'a, T>(x: &'a u32, y: T) -> impl Foo<'a> { (x, y) } // Equivalent to: type FooReturn<'a, T> = impl Foo<'a>; fn foo<'a, T>(..) -> FooReturn<'a, T> { .. }
then the hidden type Tc would be (&'0 u32, T) (where '0
is an inference variable). If we generated a constraint that
Tc: 'a, then this would incorrectly require that T: 'a --
but this is not necessary, because the opaque type we
create will be allowed to reference T. So we only generate a
constraint that '0: 'a.
The free_region_relations parameter
The free_region_relations argument is used to find the
"minimum" of the regions supplied to a given opaque type.
It must be a relation that can answer whether 'a <= 'b,
where 'a and 'b are regions that appear in the "substs"
for the opaque type references (the <'a> in Foo1<'a>).
Note that we do not impose the constraints based on the
generic regions from the Foo1 definition (e.g., 'x). This
is because the constraints we are imposing here is basically
the concern of the one generating the constraining type C1,
which is the current function. It also means that we can
take "implied bounds" into account in some cases:
trait SomeTrait<'a, 'b> { }
fn foo<'a, 'b>(_: &'a &'b u32) -> impl SomeTrait<'a, 'b> { .. }
Here, the fact that 'b: 'a is known only because of the
implied bounds from the &'a &'b u32 parameter, and is not
"inherent" to the opaque type definition.
Parameters
opaque_types-- the map produced byinstantiate_opaque_typesfree_region_relations-- something that can be used to relate the free regions ('a) that appear in the impl trait.
pub fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
&self,
def_id: DefId,
opaque_defn: &OpaqueTypeDecl<'tcx>,
mode: GenerateMemberConstraints,
free_region_relations: &FRR
)[src]
&self,
def_id: DefId,
opaque_defn: &OpaqueTypeDecl<'tcx>,
mode: GenerateMemberConstraints,
free_region_relations: &FRR
)
See constrain_opaque_types for documentation.
pub fn generate_member_constraint(
&self,
concrete_ty: Ty<'tcx>,
opaque_defn: &OpaqueTypeDecl<'tcx>,
opaque_type_def_id: DefId,
first_own_region: usize
)[src]
&self,
concrete_ty: Ty<'tcx>,
opaque_defn: &OpaqueTypeDecl<'tcx>,
opaque_type_def_id: DefId,
first_own_region: usize
)
As a fallback, we sometimes generate an "in constraint". For
a case like impl Foo<'a, 'b>, where 'a and 'b cannot be
related, we would generate a constraint 'r in ['a, 'b, 'static] for each region 'r that appears in the hidden type
(i.e., it must be equal to 'a, 'b, or 'static).
conflict1 and conflict2 are the two region bounds that we
detected which were unrelated. They are used for diagnostics.
pub fn member_constraint_feature_gate(
&self,
opaque_defn: &OpaqueTypeDecl<'tcx>,
opaque_type_def_id: DefId,
conflict1: Region<'tcx>,
conflict2: Region<'tcx>
) -> bool[src]
&self,
opaque_defn: &OpaqueTypeDecl<'tcx>,
opaque_type_def_id: DefId,
conflict1: Region<'tcx>,
conflict2: Region<'tcx>
) -> bool
Member constraints are presently feature-gated except for async-await. We expect to lift this once we've had a bit more time.
pub fn infer_opaque_definition_from_instantiation(
&self,
def_id: DefId,
substs: SubstsRef<'tcx>,
instantiated_ty: Ty<'tcx>,
span: Span
) -> Ty<'tcx>[src]
&self,
def_id: DefId,
substs: SubstsRef<'tcx>,
instantiated_ty: Ty<'tcx>,
span: Span
) -> Ty<'tcx>
Given the fully resolved, instantiated type for an opaque
type, i.e., the value of an inference variable like C1 or C2
(*), computes the "definition type" for an opaque type
definition -- that is, the inferred value of Foo1<'x> or
Foo2<'x> that we would conceptually use in its definition:
type Foo1<'x> = impl Bar<'x> = AAA; <-- this type AAA type Foo2<'x> = impl Bar<'x> = BBB; <-- or this type BBB fn foo<'a, 'b>(..) -> (Foo1<'a>, Foo2<'b>) { .. }
Note that these values are defined in terms of a distinct set of
generic parameters ('x instead of 'a) from C1 or C2. The main
purpose of this function is to do that translation.
(*) C1 and C2 were introduced in the comments on
constrain_opaque_types. Read that comment for more context.
Parameters
def_id, theimpl Traittypesubsts, the substs used to instantiate this opaque typeinstantiated_ty, the inferred type C1 -- fully resolved, lifted version ofopaque_defn.concrete_ty