1
1
//! Unification and canonicalization logic.
2
2
3
- use std:: { fmt, mem, sync:: Arc } ;
3
+ use std:: { fmt, iter , mem, sync:: Arc } ;
4
4
5
5
use chalk_ir:: {
6
6
cast:: Cast , fold:: TypeFoldable , interner:: HasInterner , zip:: Zip , CanonicalVarKind , FloatTy ,
@@ -128,9 +128,11 @@ pub(crate) fn unify(
128
128
) )
129
129
}
130
130
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
+ }
134
136
}
135
137
136
138
type ChalkInferenceTable = chalk_solve:: infer:: InferenceTable < Interner > ;
@@ -140,14 +142,14 @@ pub(crate) struct InferenceTable<'a> {
140
142
pub ( crate ) db : & ' a dyn HirDatabase ,
141
143
pub ( crate ) trait_env : Arc < TraitEnvironment > ,
142
144
var_unification_table : ChalkInferenceTable ,
143
- type_variable_table : Vec < TypeVariableData > ,
145
+ type_variable_table : Vec < TypeVariableFlags > ,
144
146
pending_obligations : Vec < Canonicalized < InEnvironment < Goal > > > ,
145
147
}
146
148
147
149
pub ( crate ) struct InferenceTableSnapshot {
148
150
var_table_snapshot : chalk_solve:: infer:: InferenceSnapshot < Interner > ,
149
151
pending_obligations : Vec < Canonicalized < InEnvironment < Goal > > > ,
150
- type_variable_table_snapshot : Vec < TypeVariableData > ,
152
+ type_variable_table_snapshot : Vec < TypeVariableFlags > ,
151
153
}
152
154
153
155
impl < ' a > InferenceTable < ' a > {
@@ -169,27 +171,27 @@ impl<'a> InferenceTable<'a> {
169
171
/// result.
170
172
pub ( super ) fn propagate_diverging_flag ( & mut self ) {
171
173
for i in 0 ..self . type_variable_table . len ( ) {
172
- if !self . type_variable_table [ i] . diverging {
174
+ if !self . type_variable_table [ i] . contains ( TypeVariableFlags :: DIVERGING ) {
173
175
continue ;
174
176
}
175
177
let v = InferenceVar :: from ( i as u32 ) ;
176
178
let root = self . var_unification_table . inference_var_root ( v) ;
177
179
if let Some ( data) = self . type_variable_table . get_mut ( root. index ( ) as usize ) {
178
- data. diverging = true ;
180
+ * data |= TypeVariableFlags :: DIVERGING ;
179
181
}
180
182
}
181
183
}
182
184
183
185
pub ( super ) fn set_diverging ( & mut self , iv : InferenceVar , diverging : bool ) {
184
- self . type_variable_table [ iv. index ( ) as usize ] . diverging = diverging;
186
+ self . type_variable_table [ iv. index ( ) as usize ] . set ( TypeVariableFlags :: DIVERGING , diverging) ;
185
187
}
186
188
187
189
fn fallback_value ( & self , iv : InferenceVar , kind : TyVariableKind ) -> Ty {
188
190
match kind {
189
191
_ if self
190
192
. type_variable_table
191
193
. get ( iv. index ( ) as usize )
192
- . map_or ( false , |data| data. diverging ) =>
194
+ . map_or ( false , |data| data. contains ( TypeVariableFlags :: DIVERGING ) ) =>
193
195
{
194
196
TyKind :: Never
195
197
}
@@ -247,18 +249,18 @@ impl<'a> InferenceTable<'a> {
247
249
}
248
250
249
251
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
- ) ;
252
+ let count = to_index - self . type_variable_table . len ( ) + 1 ;
253
+ self . type_variable_table . extend ( iter:: repeat ( TypeVariableFlags :: default ( ) ) . take ( count) ) ;
254
254
}
255
255
256
256
fn new_var ( & mut self , kind : TyVariableKind , diverging : bool ) -> Ty {
257
257
let var = self . var_unification_table . new_variable ( UniverseIndex :: ROOT ) ;
258
258
// Chalk might have created some type variables for its own purposes that we don't know about...
259
259
self . extend_type_variable_table ( var. index ( ) as usize ) ;
260
260
assert_eq ! ( var. index( ) as usize , self . type_variable_table. len( ) - 1 ) ;
261
- self . type_variable_table [ var. index ( ) as usize ] . diverging = diverging;
261
+ if diverging {
262
+ self . type_variable_table [ var. index ( ) as usize ] |= TypeVariableFlags :: DIVERGING ;
263
+ }
262
264
var. to_ty_with_kind ( Interner , kind)
263
265
}
264
266
0 commit comments