11//! Unification and canonicalization logic. 
22
3- use  std:: { fmt,  mem,  sync:: Arc } ; 
3+ use  std:: { fmt,  iter ,   mem,  sync:: Arc } ; 
44
55use  chalk_ir:: { 
66    cast:: Cast ,  fold:: TypeFoldable ,  interner:: HasInterner ,  zip:: Zip ,  CanonicalVarKind ,  FloatTy , 
@@ -128,9 +128,13 @@ pub(crate) fn unify(
128128    ) ) 
129129} 
130130
131- #[ derive( Copy ,  Clone ,  Debug ) ]  
132- pub ( crate )  struct  TypeVariableData  { 
133-     diverging :  bool , 
131+ bitflags:: bitflags! { 
132+     #[ derive( Default ) ] 
133+     pub ( crate )  struct  TypeVariableFlags :  u8  { 
134+         const  DIVERGING  = 1  << 0 ; 
135+         const  INTEGER  = 1  << 1 ; 
136+         const  FLOAT  = 1  << 2 ; 
137+     } 
134138} 
135139
136140type  ChalkInferenceTable  = chalk_solve:: infer:: InferenceTable < Interner > ; 
@@ -140,14 +144,14 @@ pub(crate) struct InferenceTable<'a> {
140144    pub ( crate )  db :  & ' a  dyn  HirDatabase , 
141145    pub ( crate )  trait_env :  Arc < TraitEnvironment > , 
142146    var_unification_table :  ChalkInferenceTable , 
143-     type_variable_table :  Vec < TypeVariableData > , 
147+     type_variable_table :  Vec < TypeVariableFlags > , 
144148    pending_obligations :  Vec < Canonicalized < InEnvironment < Goal > > > , 
145149} 
146150
147151pub ( crate )  struct  InferenceTableSnapshot  { 
148152    var_table_snapshot :  chalk_solve:: infer:: InferenceSnapshot < Interner > , 
149153    pending_obligations :  Vec < Canonicalized < InEnvironment < Goal > > > , 
150-     type_variable_table_snapshot :  Vec < TypeVariableData > , 
154+     type_variable_table_snapshot :  Vec < TypeVariableFlags > , 
151155} 
152156
153157impl < ' a >  InferenceTable < ' a >  { 
@@ -169,27 +173,27 @@ impl<'a> InferenceTable<'a> {
169173     /// result. 
170174     pub ( super )  fn  propagate_diverging_flag ( & mut  self )  { 
171175        for  i in  0 ..self . type_variable_table . len ( )  { 
172-             if  !self . type_variable_table [ i] . diverging  { 
176+             if  !self . type_variable_table [ i] . contains ( TypeVariableFlags :: DIVERGING )  { 
173177                continue ; 
174178            } 
175179            let  v = InferenceVar :: from ( i as  u32 ) ; 
176180            let  root = self . var_unification_table . inference_var_root ( v) ; 
177181            if  let  Some ( data)  = self . type_variable_table . get_mut ( root. index ( )  as  usize )  { 
178-                 data. diverging  =  true ; 
182+                 * data |=  TypeVariableFlags :: DIVERGING ; 
179183            } 
180184        } 
181185    } 
182186
183187    pub ( super )  fn  set_diverging ( & mut  self ,  iv :  InferenceVar ,  diverging :  bool )  { 
184-         self . type_variable_table [ iv. index ( )  as  usize ] . diverging  =  diverging; 
188+         self . type_variable_table [ iv. index ( )  as  usize ] . set ( TypeVariableFlags :: DIVERGING ,   diverging) ; 
185189    } 
186190
187191    fn  fallback_value ( & self ,  iv :  InferenceVar ,  kind :  TyVariableKind )  -> Ty  { 
188192        match  kind { 
189193            _ if  self 
190194                . type_variable_table 
191195                . get ( iv. index ( )  as  usize ) 
192-                 . map_or ( false ,  |data| data. diverging )  =>
196+                 . map_or ( false ,  |data| data. contains ( TypeVariableFlags :: DIVERGING ) )  =>
193197            { 
194198                TyKind :: Never 
195199            } 
@@ -247,18 +251,24 @@ impl<'a> InferenceTable<'a> {
247251    } 
248252
249253    fn  extend_type_variable_table ( & mut  self ,  to_index :  usize )  { 
250-         self . type_variable_table . extend ( 
251-             ( 0 ..1  + to_index - self . type_variable_table . len ( ) ) 
252-                 . map ( |_| TypeVariableData  {  diverging :  false  } ) , 
253-         ) ; 
254+         let  count = to_index - self . type_variable_table . len ( )  + 1 ; 
255+         self . type_variable_table . extend ( iter:: repeat ( TypeVariableFlags :: default ( ) ) . take ( count) ) ; 
254256    } 
255257
256258    fn  new_var ( & mut  self ,  kind :  TyVariableKind ,  diverging :  bool )  -> Ty  { 
257259        let  var = self . var_unification_table . new_variable ( UniverseIndex :: ROOT ) ; 
258260        // Chalk might have created some type variables for its own purposes that we don't know about... 
259261        self . extend_type_variable_table ( var. index ( )  as  usize ) ; 
260262        assert_eq ! ( var. index( )  as  usize ,  self . type_variable_table. len( )  - 1 ) ; 
261-         self . type_variable_table [ var. index ( )  as  usize ] . diverging  = diverging; 
263+         let  flags = self . type_variable_table . get_mut ( var. index ( )  as  usize ) . unwrap ( ) ; 
264+         if  diverging { 
265+             * flags |= TypeVariableFlags :: DIVERGING ; 
266+         } 
267+         if  matches ! ( kind,  TyVariableKind :: Integer )  { 
268+             * flags |= TypeVariableFlags :: INTEGER ; 
269+         }  else  if  matches ! ( kind,  TyVariableKind :: Float )  { 
270+             * flags |= TypeVariableFlags :: FLOAT ; 
271+         } 
262272        var. to_ty_with_kind ( Interner ,  kind) 
263273    } 
264274
@@ -340,6 +350,51 @@ impl<'a> InferenceTable<'a> {
340350        self . resolve_with_fallback ( t,  & |_,  _,  d,  _| d) 
341351    } 
342352
353+     /// Apply a fallback to unresolved scalar types. Integer type variables and float type 
354+      /// variables are replaced with i32 and f64, respectively. 
355+      /// 
356+      /// This method is only intended to be called just before returning inference results (i.e. in 
357+      /// `InferenceContext::resolve_all()`). 
358+      /// 
359+      /// FIXME: This method currently doesn't apply fallback to unconstrained general type variables 
360+      /// whereas rustc replaces them with `()` or `!`. 
361+      pub ( super )  fn  fallback_if_possible ( & mut  self )  { 
362+         let  int_fallback = TyKind :: Scalar ( Scalar :: Int ( IntTy :: I32 ) ) . intern ( Interner ) ; 
363+         let  float_fallback = TyKind :: Scalar ( Scalar :: Float ( FloatTy :: F64 ) ) . intern ( Interner ) ; 
364+ 
365+         let  scalar_vars:  Vec < _ >  = self 
366+             . type_variable_table 
367+             . iter ( ) 
368+             . enumerate ( ) 
369+             . filter_map ( |( index,  flags) | { 
370+                 let  kind = if  flags. contains ( TypeVariableFlags :: INTEGER )  { 
371+                     TyVariableKind :: Integer 
372+                 }  else  if  flags. contains ( TypeVariableFlags :: FLOAT )  { 
373+                     TyVariableKind :: Float 
374+                 }  else  { 
375+                     return  None ; 
376+                 } ; 
377+ 
378+                 // FIXME: This is not really the nicest way to get `InferenceVar`s. Can we get them 
379+                 // without directly constructing them from `index`? 
380+                 let  var = InferenceVar :: from ( index as  u32 ) . to_ty ( Interner ,  kind) ; 
381+                 Some ( var) 
382+             } ) 
383+             . collect ( ) ; 
384+ 
385+         for  var in  scalar_vars { 
386+             let  maybe_resolved = self . resolve_ty_shallow ( & var) ; 
387+             if  let  TyKind :: InferenceVar ( _,  kind)  = maybe_resolved. kind ( Interner )  { 
388+                 let  fallback = match  kind { 
389+                     TyVariableKind :: Integer  => & int_fallback, 
390+                     TyVariableKind :: Float  => & float_fallback, 
391+                     TyVariableKind :: General  => unreachable ! ( ) , 
392+                 } ; 
393+                 self . unify ( & var,  fallback) ; 
394+             } 
395+         } 
396+     } 
397+ 
343398    /// Unify two relatable values (e.g. `Ty`) and register new trait goals that arise from that. 
344399     pub ( crate )  fn  unify < T :  ?Sized  + Zip < Interner > > ( & mut  self ,  ty1 :  & T ,  ty2 :  & T )  -> bool  { 
345400        let  result = match  self . try_unify ( ty1,  ty2)  { 
0 commit comments