@@ -23,12 +23,9 @@ use crate::{
2323} ;
2424
2525impl InferenceContext < ' _ > {
26- pub ( super ) fn canonicalize < T : TypeFoldable < Interner > + HasInterner < Interner = Interner > > (
27- & mut self ,
28- t : T ,
29- ) -> Canonicalized < T >
26+ pub ( super ) fn canonicalize < T > ( & mut self , t : T ) -> Canonical < T >
3027 where
31- T : HasInterner < Interner = Interner > ,
28+ T : TypeFoldable < Interner > + HasInterner < Interner = Interner > ,
3229 {
3330 self . table . canonicalize ( t)
3431 }
@@ -128,14 +125,14 @@ impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
128125 } ) ,
129126 ) ;
130127 for ( i, v) in solution. value . iter ( Interner ) . enumerate ( ) {
131- let var = self . free_vars [ i] . clone ( ) ;
128+ let var = & self . free_vars [ i] ;
132129 if let Some ( ty) = v. ty ( Interner ) {
133130 // eagerly replace projections in the type; we may be getting types
134131 // e.g. from where clauses where this hasn't happened yet
135132 let ty = ctx. normalize_associated_types_in ( new_vars. apply ( ty. clone ( ) , Interner ) ) ;
136133 ctx. unify ( var. assert_ty_ref ( Interner ) , & ty) ;
137134 } else {
138- let _ = ctx. try_unify ( & var, & new_vars. apply ( v. clone ( ) , Interner ) ) ;
135+ let _ = ctx. try_unify ( var, & new_vars. apply ( v. clone ( ) , Interner ) ) ;
139136 }
140137 }
141138 }
@@ -243,7 +240,7 @@ pub(crate) struct InferenceTable<'a> {
243240 pub ( crate ) db : & ' a dyn HirDatabase ,
244241 pub ( crate ) trait_env : Arc < TraitEnvironment > ,
245242 var_unification_table : ChalkInferenceTable ,
246- type_variable_table : Vec < TypeVariableFlags > ,
243+ type_variable_table : SmallVec < [ TypeVariableFlags ; 16 ] > ,
247244 pending_obligations : Vec < Canonicalized < InEnvironment < Goal > > > ,
248245 /// Double buffer used in [`Self::resolve_obligations_as_possible`] to cut down on
249246 /// temporary allocations.
@@ -252,8 +249,8 @@ pub(crate) struct InferenceTable<'a> {
252249
253250pub ( crate ) struct InferenceTableSnapshot {
254251 var_table_snapshot : chalk_solve:: infer:: InferenceSnapshot < Interner > ,
252+ type_variable_table : SmallVec < [ TypeVariableFlags ; 16 ] > ,
255253 pending_obligations : Vec < Canonicalized < InEnvironment < Goal > > > ,
256- type_variable_table_snapshot : Vec < TypeVariableFlags > ,
257254}
258255
259256impl < ' a > InferenceTable < ' a > {
@@ -262,7 +259,7 @@ impl<'a> InferenceTable<'a> {
262259 db,
263260 trait_env,
264261 var_unification_table : ChalkInferenceTable :: new ( ) ,
265- type_variable_table : Vec :: new ( ) ,
262+ type_variable_table : SmallVec :: new ( ) ,
266263 pending_obligations : Vec :: new ( ) ,
267264 resolve_obligations_buffer : Vec :: new ( ) ,
268265 }
@@ -292,27 +289,24 @@ impl<'a> InferenceTable<'a> {
292289 }
293290
294291 fn fallback_value ( & self , iv : InferenceVar , kind : TyVariableKind ) -> Ty {
292+ let is_diverging = self
293+ . type_variable_table
294+ . get ( iv. index ( ) as usize )
295+ . map_or ( false , |data| data. contains ( TypeVariableFlags :: DIVERGING ) ) ;
296+ if is_diverging {
297+ return TyKind :: Never . intern ( Interner ) ;
298+ }
295299 match kind {
296- _ if self
297- . type_variable_table
298- . get ( iv. index ( ) as usize )
299- . map_or ( false , |data| data. contains ( TypeVariableFlags :: DIVERGING ) ) =>
300- {
301- TyKind :: Never
302- }
303300 TyVariableKind :: General => TyKind :: Error ,
304301 TyVariableKind :: Integer => TyKind :: Scalar ( Scalar :: Int ( IntTy :: I32 ) ) ,
305302 TyVariableKind :: Float => TyKind :: Scalar ( Scalar :: Float ( FloatTy :: F64 ) ) ,
306303 }
307304 . intern ( Interner )
308305 }
309306
310- pub ( crate ) fn canonicalize < T : TypeFoldable < Interner > + HasInterner < Interner = Interner > > (
311- & mut self ,
312- t : T ,
313- ) -> Canonicalized < T >
307+ pub ( crate ) fn canonicalize_with_free_vars < T > ( & mut self , t : T ) -> Canonicalized < T >
314308 where
315- T : HasInterner < Interner = Interner > ,
309+ T : TypeFoldable < Interner > + HasInterner < Interner = Interner > ,
316310 {
317311 // try to resolve obligations before canonicalizing, since this might
318312 // result in new knowledge about variables
@@ -326,6 +320,16 @@ impl<'a> InferenceTable<'a> {
326320 Canonicalized { value : result. quantified , free_vars }
327321 }
328322
323+ pub ( crate ) fn canonicalize < T > ( & mut self , t : T ) -> Canonical < T >
324+ where
325+ T : TypeFoldable < Interner > + HasInterner < Interner = Interner > ,
326+ {
327+ // try to resolve obligations before canonicalizing, since this might
328+ // result in new knowledge about variables
329+ self . resolve_obligations_as_possible ( ) ;
330+ self . var_unification_table . canonicalize ( Interner , t) . quantified
331+ }
332+
329333 /// Recurses through the given type, normalizing associated types mentioned
330334 /// in it by replacing them by type variables and registering obligations to
331335 /// resolve later. This should be done once for every type we get from some
@@ -434,6 +438,7 @@ impl<'a> InferenceTable<'a> {
434438 where
435439 T : HasInterner < Interner = Interner > + TypeFoldable < Interner > ,
436440 {
441+ // TODO check this vec here
437442 self . resolve_with_fallback_inner ( & mut Vec :: new ( ) , t, & fallback)
438443 }
439444
@@ -541,7 +546,7 @@ impl<'a> InferenceTable<'a> {
541546 Err ( _) => return false ,
542547 } ;
543548 result. goals . iter ( ) . all ( |goal| {
544- let canonicalized = self . canonicalize ( goal. clone ( ) ) ;
549+ let canonicalized = self . canonicalize_with_free_vars ( goal. clone ( ) ) ;
545550 self . try_resolve_obligation ( & canonicalized) . is_some ( )
546551 } )
547552 }
@@ -575,19 +580,15 @@ impl<'a> InferenceTable<'a> {
575580
576581 pub ( crate ) fn snapshot ( & mut self ) -> InferenceTableSnapshot {
577582 let var_table_snapshot = self . var_unification_table . snapshot ( ) ;
578- let type_variable_table_snapshot = self . type_variable_table . clone ( ) ;
583+ let type_variable_table = self . type_variable_table . clone ( ) ;
579584 let pending_obligations = self . pending_obligations . clone ( ) ;
580- InferenceTableSnapshot {
581- var_table_snapshot,
582- pending_obligations,
583- type_variable_table_snapshot,
584- }
585+ InferenceTableSnapshot { var_table_snapshot, pending_obligations, type_variable_table }
585586 }
586587
587588 #[ tracing:: instrument( skip_all) ]
588589 pub ( crate ) fn rollback_to ( & mut self , snapshot : InferenceTableSnapshot ) {
589590 self . var_unification_table . rollback_to ( snapshot. var_table_snapshot ) ;
590- self . type_variable_table = snapshot. type_variable_table_snapshot ;
591+ self . type_variable_table = snapshot. type_variable_table ;
591592 self . pending_obligations = snapshot. pending_obligations ;
592593 }
593594
@@ -606,7 +607,7 @@ impl<'a> InferenceTable<'a> {
606607 let in_env = InEnvironment :: new ( & self . trait_env . env , goal) ;
607608 let canonicalized = self . canonicalize ( in_env) ;
608609
609- self . db . trait_solve ( self . trait_env . krate , self . trait_env . block , canonicalized. value )
610+ self . db . trait_solve ( self . trait_env . krate , self . trait_env . block , canonicalized)
610611 }
611612
612613 pub ( crate ) fn register_obligation ( & mut self , goal : Goal ) {
@@ -615,7 +616,7 @@ impl<'a> InferenceTable<'a> {
615616 }
616617
617618 fn register_obligation_in_env ( & mut self , goal : InEnvironment < Goal > ) {
618- let canonicalized = self . canonicalize ( goal) ;
619+ let canonicalized = self . canonicalize_with_free_vars ( goal) ;
619620 let solution = self . try_resolve_obligation ( & canonicalized) ;
620621 if matches ! ( solution, Some ( Solution :: Ambig ( _) ) ) {
621622 self . pending_obligations . push ( canonicalized) ;
@@ -798,7 +799,7 @@ impl<'a> InferenceTable<'a> {
798799 let trait_data = self . db . trait_data ( fn_once_trait) ;
799800 let output_assoc_type = trait_data. associated_type_by_name ( & name ! [ Output ] ) ?;
800801
801- let mut arg_tys = vec ! [ ] ;
802+ let mut arg_tys = Vec :: with_capacity ( num_args ) ;
802803 let arg_ty = TyBuilder :: tuple ( num_args)
803804 . fill ( |it| {
804805 let arg = match it {
@@ -828,11 +829,7 @@ impl<'a> InferenceTable<'a> {
828829 environment : trait_env. clone ( ) ,
829830 } ;
830831 let canonical = self . canonicalize ( obligation. clone ( ) ) ;
831- if self
832- . db
833- . trait_solve ( krate, self . trait_env . block , canonical. value . cast ( Interner ) )
834- . is_some ( )
835- {
832+ if self . db . trait_solve ( krate, self . trait_env . block , canonical. cast ( Interner ) ) . is_some ( ) {
836833 self . register_obligation ( obligation. goal ) ;
837834 let return_ty = self . normalize_projection_ty ( projection) ;
838835 for fn_x in [ FnTrait :: Fn , FnTrait :: FnMut , FnTrait :: FnOnce ] {
@@ -845,7 +842,7 @@ impl<'a> InferenceTable<'a> {
845842 let canonical = self . canonicalize ( obligation. clone ( ) ) ;
846843 if self
847844 . db
848- . trait_solve ( krate, self . trait_env . block , canonical. value . cast ( Interner ) )
845+ . trait_solve ( krate, self . trait_env . block , canonical. cast ( Interner ) )
849846 . is_some ( )
850847 {
851848 return Some ( ( fn_x, arg_tys, return_ty) ) ;
0 commit comments