11use std:: mem;
22
3+ use super :: StructurallyRelateAliases ;
34use crate :: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind , TypeVariableValue } ;
45use crate :: infer:: { InferCtxt , ObligationEmittingRelation , RegionVariableOrigin } ;
56use rustc_data_structures:: sso:: SsoHashMap ;
@@ -45,8 +46,14 @@ impl<'tcx> InferCtxt<'tcx> {
4546 // region/type inference variables.
4647 //
4748 // We then relate `generalized_ty <: source_ty`,adding constraints like `'x: '?2` and `?1 <: ?3`.
48- let Generalization { value_may_be_infer : generalized_ty, has_unconstrained_ty_var } =
49- self . generalize ( relation. span ( ) , target_vid, instantiation_variance, source_ty) ?;
49+ let Generalization { value_may_be_infer : generalized_ty, has_unconstrained_ty_var } = self
50+ . generalize (
51+ relation. span ( ) ,
52+ relation. structurally_relate_aliases ( ) ,
53+ target_vid,
54+ instantiation_variance,
55+ source_ty,
56+ ) ?;
5057
5158 // Constrain `b_vid` to the generalized type `generalized_ty`.
5259 if let & ty:: Infer ( ty:: TyVar ( generalized_vid) ) = generalized_ty. kind ( ) {
@@ -178,8 +185,14 @@ impl<'tcx> InferCtxt<'tcx> {
178185 ) -> RelateResult < ' tcx , ( ) > {
179186 // FIXME(generic_const_exprs): Occurs check failures for unevaluated
180187 // constants and generic expressions are not yet handled correctly.
181- let Generalization { value_may_be_infer : generalized_ct, has_unconstrained_ty_var } =
182- self . generalize ( relation. span ( ) , target_vid, ty:: Variance :: Invariant , source_ct) ?;
188+ let Generalization { value_may_be_infer : generalized_ct, has_unconstrained_ty_var } = self
189+ . generalize (
190+ relation. span ( ) ,
191+ relation. structurally_relate_aliases ( ) ,
192+ target_vid,
193+ ty:: Variance :: Invariant ,
194+ source_ct,
195+ ) ?;
183196
184197 debug_assert ! ( !generalized_ct. is_ct_infer( ) ) ;
185198 if has_unconstrained_ty_var {
@@ -217,6 +230,7 @@ impl<'tcx> InferCtxt<'tcx> {
217230 fn generalize < T : Into < Term < ' tcx > > + Relate < ' tcx > > (
218231 & self ,
219232 span : Span ,
233+ structurally_relate_aliases : StructurallyRelateAliases ,
220234 target_vid : impl Into < ty:: TermVid > ,
221235 ambient_variance : ty:: Variance ,
222236 source_term : T ,
@@ -237,6 +251,7 @@ impl<'tcx> InferCtxt<'tcx> {
237251 let mut generalizer = Generalizer {
238252 infcx : self ,
239253 span,
254+ structurally_relate_aliases,
240255 root_vid,
241256 for_universe,
242257 ambient_variance,
@@ -270,6 +285,10 @@ struct Generalizer<'me, 'tcx> {
270285
271286 span : Span ,
272287
288+ /// Whether aliases should be related structurally. If not, we have to
289+ /// be careful when generalizing aliases.
290+ structurally_relate_aliases : StructurallyRelateAliases ,
291+
273292 /// The vid of the type variable that is in the process of being
274293 /// instantiated. If we find this within the value we are folding,
275294 /// that means we would have created a cyclic value.
@@ -314,13 +333,30 @@ impl<'tcx> Generalizer<'_, 'tcx> {
314333 /// to normalize the alias after all.
315334 ///
316335 /// We handle this by lazily equating the alias and generalizing
317- /// it to an inference variable.
336+ /// it to an inference variable. In the new solver, we always
337+ /// generalize to an infer var unless the alias contains escaping
338+ /// bound variables.
318339 ///
319- /// This is incomplete and will hopefully soon get fixed by #119106.
340+ /// Correctly handling aliases with escaping bound variables is
341+ /// difficult and currently incomplete in two opposite ways:
342+ /// - if we get an occurs check failure in the alias, replace it with a new infer var.
343+ /// This causes us to later emit an alias-relate goal and is incomplete in case the
344+ /// alias normalizes to type containing one of the bound variables.
345+ /// - if the alias contains an inference variable not nameable by `for_universe`, we
346+ /// continue generalizing the alias. This ends up pulling down the universe of the
347+ /// inference variable and is incomplete in case the alias would normalize to a type
348+ /// which does not mention that inference variable.
320349 fn generalize_alias_ty (
321350 & mut self ,
322351 alias : ty:: AliasTy < ' tcx > ,
323352 ) -> Result < Ty < ' tcx > , TypeError < ' tcx > > {
353+ if self . infcx . next_trait_solver ( ) && !alias. has_escaping_bound_vars ( ) {
354+ return Ok ( self . infcx . next_ty_var_in_universe (
355+ TypeVariableOrigin { kind : TypeVariableOriginKind :: MiscVariable , span : self . span } ,
356+ self . for_universe ,
357+ ) ) ;
358+ }
359+
324360 let is_nested_alias = mem:: replace ( & mut self . in_alias , true ) ;
325361 let result = match self . relate ( alias, alias) {
326362 Ok ( alias) => Ok ( alias. to_ty ( self . tcx ( ) ) ) ,
@@ -490,7 +526,10 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
490526 }
491527 }
492528
493- ty:: Alias ( _, data) => self . generalize_alias_ty ( data) ,
529+ ty:: Alias ( _, data) => match self . structurally_relate_aliases {
530+ StructurallyRelateAliases :: No => self . generalize_alias_ty ( data) ,
531+ StructurallyRelateAliases :: Yes => relate:: structurally_relate_tys ( self , t, t) ,
532+ } ,
494533
495534 _ => relate:: structurally_relate_tys ( self , t, t) ,
496535 } ?;
0 commit comments