@@ -23,12 +23,9 @@ use crate::{
23
23
} ;
24
24
25
25
impl 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 >
30
27
where
31
- T : HasInterner < Interner = Interner > ,
28
+ T : TypeFoldable < Interner > + HasInterner < Interner = Interner > ,
32
29
{
33
30
self . table . canonicalize ( t)
34
31
}
@@ -128,14 +125,14 @@ impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
128
125
} ) ,
129
126
) ;
130
127
for ( i, v) in solution. value . iter ( Interner ) . enumerate ( ) {
131
- let var = self . free_vars [ i] . clone ( ) ;
128
+ let var = & self . free_vars [ i] ;
132
129
if let Some ( ty) = v. ty ( Interner ) {
133
130
// eagerly replace projections in the type; we may be getting types
134
131
// e.g. from where clauses where this hasn't happened yet
135
132
let ty = ctx. normalize_associated_types_in ( new_vars. apply ( ty. clone ( ) , Interner ) ) ;
136
133
ctx. unify ( var. assert_ty_ref ( Interner ) , & ty) ;
137
134
} 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 ) ) ;
139
136
}
140
137
}
141
138
}
@@ -243,7 +240,7 @@ pub(crate) struct InferenceTable<'a> {
243
240
pub ( crate ) db : & ' a dyn HirDatabase ,
244
241
pub ( crate ) trait_env : Arc < TraitEnvironment > ,
245
242
var_unification_table : ChalkInferenceTable ,
246
- type_variable_table : Vec < TypeVariableFlags > ,
243
+ type_variable_table : SmallVec < [ TypeVariableFlags ; 16 ] > ,
247
244
pending_obligations : Vec < Canonicalized < InEnvironment < Goal > > > ,
248
245
/// Double buffer used in [`Self::resolve_obligations_as_possible`] to cut down on
249
246
/// temporary allocations.
@@ -252,8 +249,8 @@ pub(crate) struct InferenceTable<'a> {
252
249
253
250
pub ( crate ) struct InferenceTableSnapshot {
254
251
var_table_snapshot : chalk_solve:: infer:: InferenceSnapshot < Interner > ,
252
+ type_variable_table : SmallVec < [ TypeVariableFlags ; 16 ] > ,
255
253
pending_obligations : Vec < Canonicalized < InEnvironment < Goal > > > ,
256
- type_variable_table_snapshot : Vec < TypeVariableFlags > ,
257
254
}
258
255
259
256
impl < ' a > InferenceTable < ' a > {
@@ -262,7 +259,7 @@ impl<'a> InferenceTable<'a> {
262
259
db,
263
260
trait_env,
264
261
var_unification_table : ChalkInferenceTable :: new ( ) ,
265
- type_variable_table : Vec :: new ( ) ,
262
+ type_variable_table : SmallVec :: new ( ) ,
266
263
pending_obligations : Vec :: new ( ) ,
267
264
resolve_obligations_buffer : Vec :: new ( ) ,
268
265
}
@@ -292,27 +289,24 @@ impl<'a> InferenceTable<'a> {
292
289
}
293
290
294
291
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
+ }
295
299
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
- }
303
300
TyVariableKind :: General => TyKind :: Error ,
304
301
TyVariableKind :: Integer => TyKind :: Scalar ( Scalar :: Int ( IntTy :: I32 ) ) ,
305
302
TyVariableKind :: Float => TyKind :: Scalar ( Scalar :: Float ( FloatTy :: F64 ) ) ,
306
303
}
307
304
. intern ( Interner )
308
305
}
309
306
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 >
314
308
where
315
- T : HasInterner < Interner = Interner > ,
309
+ T : TypeFoldable < Interner > + HasInterner < Interner = Interner > ,
316
310
{
317
311
// try to resolve obligations before canonicalizing, since this might
318
312
// result in new knowledge about variables
@@ -326,6 +320,16 @@ impl<'a> InferenceTable<'a> {
326
320
Canonicalized { value : result. quantified , free_vars }
327
321
}
328
322
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
+
329
333
/// Recurses through the given type, normalizing associated types mentioned
330
334
/// in it by replacing them by type variables and registering obligations to
331
335
/// resolve later. This should be done once for every type we get from some
@@ -434,6 +438,7 @@ impl<'a> InferenceTable<'a> {
434
438
where
435
439
T : HasInterner < Interner = Interner > + TypeFoldable < Interner > ,
436
440
{
441
+ // TODO check this vec here
437
442
self . resolve_with_fallback_inner ( & mut Vec :: new ( ) , t, & fallback)
438
443
}
439
444
@@ -541,7 +546,7 @@ impl<'a> InferenceTable<'a> {
541
546
Err ( _) => return false ,
542
547
} ;
543
548
result. goals . iter ( ) . all ( |goal| {
544
- let canonicalized = self . canonicalize ( goal. clone ( ) ) ;
549
+ let canonicalized = self . canonicalize_with_free_vars ( goal. clone ( ) ) ;
545
550
self . try_resolve_obligation ( & canonicalized) . is_some ( )
546
551
} )
547
552
}
@@ -575,19 +580,15 @@ impl<'a> InferenceTable<'a> {
575
580
576
581
pub ( crate ) fn snapshot ( & mut self ) -> InferenceTableSnapshot {
577
582
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 ( ) ;
579
584
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 }
585
586
}
586
587
587
588
#[ tracing:: instrument( skip_all) ]
588
589
pub ( crate ) fn rollback_to ( & mut self , snapshot : InferenceTableSnapshot ) {
589
590
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 ;
591
592
self . pending_obligations = snapshot. pending_obligations ;
592
593
}
593
594
@@ -606,7 +607,7 @@ impl<'a> InferenceTable<'a> {
606
607
let in_env = InEnvironment :: new ( & self . trait_env . env , goal) ;
607
608
let canonicalized = self . canonicalize ( in_env) ;
608
609
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)
610
611
}
611
612
612
613
pub ( crate ) fn register_obligation ( & mut self , goal : Goal ) {
@@ -615,7 +616,7 @@ impl<'a> InferenceTable<'a> {
615
616
}
616
617
617
618
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) ;
619
620
let solution = self . try_resolve_obligation ( & canonicalized) ;
620
621
if matches ! ( solution, Some ( Solution :: Ambig ( _) ) ) {
621
622
self . pending_obligations . push ( canonicalized) ;
@@ -798,7 +799,7 @@ impl<'a> InferenceTable<'a> {
798
799
let trait_data = self . db . trait_data ( fn_once_trait) ;
799
800
let output_assoc_type = trait_data. associated_type_by_name ( & name ! [ Output ] ) ?;
800
801
801
- let mut arg_tys = vec ! [ ] ;
802
+ let mut arg_tys = Vec :: with_capacity ( num_args ) ;
802
803
let arg_ty = TyBuilder :: tuple ( num_args)
803
804
. fill ( |it| {
804
805
let arg = match it {
@@ -828,11 +829,7 @@ impl<'a> InferenceTable<'a> {
828
829
environment : trait_env. clone ( ) ,
829
830
} ;
830
831
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 ( ) {
836
833
self . register_obligation ( obligation. goal ) ;
837
834
let return_ty = self . normalize_projection_ty ( projection) ;
838
835
for fn_x in [ FnTrait :: Fn , FnTrait :: FnMut , FnTrait :: FnOnce ] {
@@ -845,7 +842,7 @@ impl<'a> InferenceTable<'a> {
845
842
let canonical = self . canonicalize ( obligation. clone ( ) ) ;
846
843
if self
847
844
. db
848
- . trait_solve ( krate, self . trait_env . block , canonical. value . cast ( Interner ) )
845
+ . trait_solve ( krate, self . trait_env . block , canonical. cast ( Interner ) )
849
846
. is_some ( )
850
847
{
851
848
return Some ( ( fn_x, arg_tys, return_ty) ) ;
0 commit comments