struct Generalizer<'me, 'tcx> {
infcx: &'me InferCtxt<'tcx>,
span: Span,
structurally_relate_aliases: StructurallyRelateAliases,
root_vid: TermVid,
for_universe: UniverseIndex,
root_term: Term<'tcx>,
ambient_variance: Variance,
in_alias: bool,
cache: SsoHashMap<(Ty<'tcx>, Variance, bool), Ty<'tcx>>,
has_unconstrained_ty_var: bool,
}
Expand description
The “generalizer” is used when handling inference variables.
The basic strategy for handling a constraint like ?A <: B
is to
apply a “generalization strategy” to the term B
– this replaces
all the lifetimes in the term B
with fresh inference variables.
(You can read more about the strategy in this blog post.)
As an example, if we had ?A <: &'x u32
, we would generalize &'x u32
to &'0 u32
where '0
is a fresh variable. This becomes the
value of A
. Finally, we relate &'0 u32 <: &'x u32
, which
establishes '0: 'x
as a constraint.
Fields§
§infcx: &'me InferCtxt<'tcx>
§span: Span
§structurally_relate_aliases: StructurallyRelateAliases
Whether aliases should be related structurally. If not, we have to be careful when generalizing aliases.
root_vid: TermVid
The vid of the type variable that is in the process of being instantiated. If we find this within the value we are folding, that means we would have created a cyclic value.
for_universe: UniverseIndex
The universe of the type variable that is in the process of being instantiated. If we find anything that this universe cannot name, we reject the relation.
root_term: Term<'tcx>
The root term (const or type) we’re generalizing. Used for cycle errors.
ambient_variance: Variance
After we generalize this type, we are going to relate it to some other type. What will be the variance at this point?
in_alias: bool
This is set once we’re generalizing the arguments of an alias.
This is necessary to correctly handle
<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0
. This equality can
hold by either normalizing the outer or the inner associated type.
cache: SsoHashMap<(Ty<'tcx>, Variance, bool), Ty<'tcx>>
§has_unconstrained_ty_var: bool
See the field has_unconstrained_ty_var
in Generalization
.
Implementations§
source§impl<'tcx> Generalizer<'_, 'tcx>
impl<'tcx> Generalizer<'_, 'tcx>
sourcefn cyclic_term_error(&self) -> TypeError<'tcx>
fn cyclic_term_error(&self) -> TypeError<'tcx>
Create an error that corresponds to the term kind in root_term
sourcefn next_ty_var_for_alias(&mut self) -> Ty<'tcx>
fn next_ty_var_for_alias(&mut self) -> Ty<'tcx>
Create a new type variable in the universe of the target when
generalizing an alias. This has to set has_unconstrained_ty_var
if we’re currently in a bivariant context.
sourcefn generalize_alias_ty(
&mut self,
alias: AliasTy<'tcx>,
) -> Result<Ty<'tcx>, TypeError<'tcx>>
fn generalize_alias_ty( &mut self, alias: AliasTy<'tcx>, ) -> Result<Ty<'tcx>, TypeError<'tcx>>
An occurs check failure inside of an alias does not mean that the types definitely don’t unify. We may be able to normalize the alias after all.
We handle this by lazily equating the alias and generalizing it to an inference variable. In the new solver, we always generalize to an infer var unless the alias contains escaping bound variables.
Correctly handling aliases with escaping bound variables is difficult and currently incomplete in two opposite ways:
- if we get an occurs check failure in the alias, replace it with a new infer var. This causes us to later emit an alias-relate goal and is incomplete in case the alias normalizes to type containing one of the bound variables.
- if the alias contains an inference variable not nameable by
for_universe
, we continue generalizing the alias. This ends up pulling down the universe of the inference variable and is incomplete in case the alias would normalize to a type which does not mention that inference variable.
Trait Implementations§
source§impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx>
impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx>
fn cx(&self) -> TyCtxt<'tcx>
source§fn relate_item_args(
&mut self,
item_def_id: DefId,
a_arg: GenericArgsRef<'tcx>,
b_arg: GenericArgsRef<'tcx>,
) -> RelateResult<'tcx, GenericArgsRef<'tcx>>
fn relate_item_args( &mut self, item_def_id: DefId, a_arg: GenericArgsRef<'tcx>, b_arg: GenericArgsRef<'tcx>, ) -> RelateResult<'tcx, GenericArgsRef<'tcx>>
source§fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
&mut self,
variance: Variance,
_info: VarianceDiagInfo<TyCtxt<'tcx>>,
a: T,
b: T,
) -> RelateResult<'tcx, T>
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>( &mut self, variance: Variance, _info: VarianceDiagInfo<TyCtxt<'tcx>>, a: T, b: T, ) -> RelateResult<'tcx, T>
a
and b
.fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>>
fn regions( &mut self, r: Region<'tcx>, r2: Region<'tcx>, ) -> RelateResult<'tcx, Region<'tcx>>
fn consts( &mut self, c: Const<'tcx>, c2: Const<'tcx>, ) -> RelateResult<'tcx, Const<'tcx>>
fn binders<T>( &mut self, a: Binder<'tcx, T>, _: Binder<'tcx, T>, ) -> RelateResult<'tcx, Binder<'tcx, T>>
Auto Trait Implementations§
impl<'me, 'tcx> Freeze for Generalizer<'me, 'tcx>
impl<'me, 'tcx> !RefUnwindSafe for Generalizer<'me, 'tcx>
impl<'me, 'tcx> !Send for Generalizer<'me, 'tcx>
impl<'me, 'tcx> !Sync for Generalizer<'me, 'tcx>
impl<'me, 'tcx> Unpin for Generalizer<'me, 'tcx>
impl<'me, 'tcx> !UnwindSafe for Generalizer<'me, 'tcx>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T, R> CollectAndApply<T, R> for T
impl<T, R> CollectAndApply<T, R> for T
source§impl<T> Filterable for T
impl<T> Filterable for T
source§fn filterable(
self,
filter_name: &'static str,
) -> RequestFilterDataProvider<T, fn(_: DataRequest<'_>) -> bool>
fn filterable( self, filter_name: &'static str, ) -> RequestFilterDataProvider<T, fn(_: DataRequest<'_>) -> bool>
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§impl<P> IntoQueryParam<P> for P
impl<P> IntoQueryParam<P> for P
fn into_query_param(self) -> P
source§impl<T> MaybeResult<T> for T
impl<T> MaybeResult<T> for T
source§impl<I, T, U> Upcast<I, U> for Twhere
U: UpcastFrom<I, T>,
impl<I, T, U> Upcast<I, U> for Twhere
U: UpcastFrom<I, T>,
source§impl<I, T> UpcastFrom<I, T> for T
impl<I, T> UpcastFrom<I, T> for T
fn upcast_from(from: T, _tcx: I) -> T
source§impl<Tcx, T> Value<Tcx> for Twhere
Tcx: DepContext,
impl<Tcx, T> Value<Tcx> for Twhere
Tcx: DepContext,
default fn from_cycle_error( tcx: Tcx, cycle_error: &CycleError, _guar: ErrorGuaranteed, ) -> T
source§impl<T> WithSubscriber for T
impl<T> WithSubscriber for T
source§fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
source§fn with_current_subscriber(self) -> WithDispatch<Self>
fn with_current_subscriber(self) -> WithDispatch<Self>
impl<'a, T> Captures<'a> for Twhere
T: ?Sized,
impl<T> ErasedDestructor for Twhere
T: 'static,
impl<T> MaybeSendSync for T
Layout§
Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...)
attributes. Please see the Rust Reference's “Type Layout” chapter for details on type layout guarantees.
Size: 248 bytes