diff options
-rw-r--r-- | crates/hir_ty/src/infer/coerce.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 102 |
2 files changed, 48 insertions, 56 deletions
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index 60186bc5f..20c512517 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -101,7 +101,7 @@ impl<'a> InferenceContext<'a> { | |||
101 | // here, we would coerce from `!` to `?T`. | 101 | // here, we would coerce from `!` to `?T`. |
102 | match to_ty.kind(&Interner) { | 102 | match to_ty.kind(&Interner) { |
103 | TyKind::InferenceVar(tv, TyVariableKind::General) => { | 103 | TyKind::InferenceVar(tv, TyVariableKind::General) => { |
104 | self.table.type_variable_table.set_diverging(*tv, true); | 104 | self.table.set_diverging(*tv, true); |
105 | } | 105 | } |
106 | _ => {} | 106 | _ => {} |
107 | } | 107 | } |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index d872cdd58..8674c1b0c 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -127,29 +127,6 @@ pub(crate) fn unify( | |||
127 | )) | 127 | )) |
128 | } | 128 | } |
129 | 129 | ||
130 | #[derive(Clone, Debug)] | ||
131 | pub(super) struct TypeVariableTable { | ||
132 | inner: Vec<TypeVariableData>, | ||
133 | } | ||
134 | |||
135 | impl TypeVariableTable { | ||
136 | pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) { | ||
137 | self.inner[iv.index() as usize].diverging = diverging; | ||
138 | } | ||
139 | |||
140 | fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { | ||
141 | match kind { | ||
142 | _ if self.inner.get(iv.index() as usize).map_or(false, |data| data.diverging) => { | ||
143 | TyKind::Never | ||
144 | } | ||
145 | TyVariableKind::General => TyKind::Error, | ||
146 | TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)), | ||
147 | TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)), | ||
148 | } | ||
149 | .intern(&Interner) | ||
150 | } | ||
151 | } | ||
152 | |||
153 | #[derive(Copy, Clone, Debug)] | 130 | #[derive(Copy, Clone, Debug)] |
154 | pub(crate) struct TypeVariableData { | 131 | pub(crate) struct TypeVariableData { |
155 | diverging: bool, | 132 | diverging: bool, |
@@ -162,7 +139,7 @@ pub(crate) struct InferenceTable<'a> { | |||
162 | pub db: &'a dyn HirDatabase, | 139 | pub db: &'a dyn HirDatabase, |
163 | pub trait_env: Arc<TraitEnvironment>, | 140 | pub trait_env: Arc<TraitEnvironment>, |
164 | pub(super) var_unification_table: ChalkInferenceTable, | 141 | pub(super) var_unification_table: ChalkInferenceTable, |
165 | pub(super) type_variable_table: TypeVariableTable, | 142 | pub(super) type_variable_table: Vec<TypeVariableData>, |
166 | pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>, | 143 | pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>, |
167 | } | 144 | } |
168 | 145 | ||
@@ -172,7 +149,7 @@ impl<'a> InferenceTable<'a> { | |||
172 | db, | 149 | db, |
173 | trait_env, | 150 | trait_env, |
174 | var_unification_table: ChalkInferenceTable::new(), | 151 | var_unification_table: ChalkInferenceTable::new(), |
175 | type_variable_table: TypeVariableTable { inner: Vec::new() }, | 152 | type_variable_table: Vec::new(), |
176 | pending_obligations: Vec::new(), | 153 | pending_obligations: Vec::new(), |
177 | } | 154 | } |
178 | } | 155 | } |
@@ -184,18 +161,38 @@ impl<'a> InferenceTable<'a> { | |||
184 | /// marked as diverging if necessary, so that resolving them gives the right | 161 | /// marked as diverging if necessary, so that resolving them gives the right |
185 | /// result. | 162 | /// result. |
186 | pub(super) fn propagate_diverging_flag(&mut self) { | 163 | pub(super) fn propagate_diverging_flag(&mut self) { |
187 | for i in 0..self.type_variable_table.inner.len() { | 164 | for i in 0..self.type_variable_table.len() { |
188 | if !self.type_variable_table.inner[i].diverging { | 165 | if !self.type_variable_table[i].diverging { |
189 | continue; | 166 | continue; |
190 | } | 167 | } |
191 | let v = InferenceVar::from(i as u32); | 168 | let v = InferenceVar::from(i as u32); |
192 | let root = self.var_unification_table.inference_var_root(v); | 169 | let root = self.var_unification_table.inference_var_root(v); |
193 | if let Some(data) = self.type_variable_table.inner.get_mut(root.index() as usize) { | 170 | if let Some(data) = self.type_variable_table.get_mut(root.index() as usize) { |
194 | data.diverging = true; | 171 | data.diverging = true; |
195 | } | 172 | } |
196 | } | 173 | } |
197 | } | 174 | } |
198 | 175 | ||
176 | pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) { | ||
177 | self.type_variable_table[iv.index() as usize].diverging = diverging; | ||
178 | } | ||
179 | |||
180 | fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { | ||
181 | match kind { | ||
182 | _ if self | ||
183 | .type_variable_table | ||
184 | .get(iv.index() as usize) | ||
185 | .map_or(false, |data| data.diverging) => | ||
186 | { | ||
187 | TyKind::Never | ||
188 | } | ||
189 | TyVariableKind::General => TyKind::Error, | ||
190 | TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)), | ||
191 | TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)), | ||
192 | } | ||
193 | .intern(&Interner) | ||
194 | } | ||
195 | |||
199 | pub(super) fn canonicalize<T: Fold<Interner> + HasInterner<Interner = Interner>>( | 196 | pub(super) fn canonicalize<T: Fold<Interner> + HasInterner<Interner = Interner>>( |
200 | &mut self, | 197 | &mut self, |
201 | t: T, | 198 | t: T, |
@@ -239,16 +236,19 @@ impl<'a> InferenceTable<'a> { | |||
239 | var | 236 | var |
240 | } | 237 | } |
241 | 238 | ||
239 | fn extend_type_variable_table(&mut self, to_index: usize) { | ||
240 | self.type_variable_table.extend( | ||
241 | (0..1 + to_index - self.type_variable_table.len()) | ||
242 | .map(|_| TypeVariableData { diverging: false }), | ||
243 | ); | ||
244 | } | ||
245 | |||
242 | fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty { | 246 | fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty { |
243 | let var = self.var_unification_table.new_variable(UniverseIndex::ROOT); | 247 | let var = self.var_unification_table.new_variable(UniverseIndex::ROOT); |
244 | // Chalk might have created some type variables for its own purposes that we don't know about... | 248 | // Chalk might have created some type variables for its own purposes that we don't know about... |
245 | // TODO refactor this? | 249 | self.extend_type_variable_table(var.index() as usize); |
246 | self.type_variable_table.inner.extend( | 250 | assert_eq!(var.index() as usize, self.type_variable_table.len() - 1); |
247 | (0..1 + var.index() as usize - self.type_variable_table.inner.len()) | 251 | self.type_variable_table[var.index() as usize].diverging = diverging; |
248 | .map(|_| TypeVariableData { diverging: false }), | ||
249 | ); | ||
250 | assert_eq!(var.index() as usize, self.type_variable_table.inner.len() - 1); | ||
251 | self.type_variable_table.inner[var.index() as usize].diverging = diverging; | ||
252 | var.to_ty_with_kind(&Interner, kind) | 252 | var.to_ty_with_kind(&Interner, kind) |
253 | } | 253 | } |
254 | 254 | ||
@@ -289,12 +289,7 @@ impl<'a> InferenceTable<'a> { | |||
289 | T: HasInterner<Interner = Interner> + Fold<Interner>, | 289 | T: HasInterner<Interner = Interner> + Fold<Interner>, |
290 | { | 290 | { |
291 | t.fold_with( | 291 | t.fold_with( |
292 | &mut resolve::Resolver { | 292 | &mut resolve::Resolver { table: self, var_stack, fallback }, |
293 | type_variable_table: &self.type_variable_table, | ||
294 | var_unification_table: &mut self.var_unification_table, | ||
295 | var_stack, | ||
296 | fallback, | ||
297 | }, | ||
298 | DebruijnIndex::INNERMOST, | 293 | DebruijnIndex::INNERMOST, |
299 | ) | 294 | ) |
300 | .expect("fold failed unexpectedly") | 295 | .expect("fold failed unexpectedly") |
@@ -433,14 +428,12 @@ impl<'a> InferenceTable<'a> { | |||
433 | 428 | ||
434 | impl<'a> fmt::Debug for InferenceTable<'a> { | 429 | impl<'a> fmt::Debug for InferenceTable<'a> { |
435 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 430 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
436 | f.debug_struct("InferenceTable") | 431 | f.debug_struct("InferenceTable").field("num_vars", &self.type_variable_table.len()).finish() |
437 | .field("num_vars", &self.type_variable_table.inner.len()) | ||
438 | .finish() | ||
439 | } | 432 | } |
440 | } | 433 | } |
441 | 434 | ||
442 | mod resolve { | 435 | mod resolve { |
443 | use super::{ChalkInferenceTable, TypeVariableTable}; | 436 | use super::InferenceTable; |
444 | use crate::{ | 437 | use crate::{ |
445 | ConcreteConst, Const, ConstData, ConstValue, DebruijnIndex, GenericArg, InferenceVar, | 438 | ConcreteConst, Const, ConstData, ConstValue, DebruijnIndex, GenericArg, InferenceVar, |
446 | Interner, Ty, TyVariableKind, VariableKind, | 439 | Interner, Ty, TyVariableKind, VariableKind, |
@@ -452,13 +445,12 @@ mod resolve { | |||
452 | }; | 445 | }; |
453 | use hir_def::type_ref::ConstScalar; | 446 | use hir_def::type_ref::ConstScalar; |
454 | 447 | ||
455 | pub(super) struct Resolver<'a, F> { | 448 | pub(super) struct Resolver<'a, 'b, F> { |
456 | pub type_variable_table: &'a TypeVariableTable, | 449 | pub table: &'a mut InferenceTable<'b>, |
457 | pub var_unification_table: &'a mut ChalkInferenceTable, | ||
458 | pub var_stack: &'a mut Vec<InferenceVar>, | 450 | pub var_stack: &'a mut Vec<InferenceVar>, |
459 | pub fallback: F, | 451 | pub fallback: F, |
460 | } | 452 | } |
461 | impl<'a, 'i, F> Folder<'i, Interner> for Resolver<'a, F> | 453 | impl<'a, 'b, 'i, F> Folder<'i, Interner> for Resolver<'a, 'b, F> |
462 | where | 454 | where |
463 | F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg + 'i, | 455 | F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg + 'i, |
464 | { | 456 | { |
@@ -476,15 +468,15 @@ mod resolve { | |||
476 | kind: TyVariableKind, | 468 | kind: TyVariableKind, |
477 | outer_binder: DebruijnIndex, | 469 | outer_binder: DebruijnIndex, |
478 | ) -> Fallible<Ty> { | 470 | ) -> Fallible<Ty> { |
479 | let var = self.var_unification_table.inference_var_root(var); | 471 | let var = self.table.var_unification_table.inference_var_root(var); |
480 | if self.var_stack.contains(&var) { | 472 | if self.var_stack.contains(&var) { |
481 | // recursive type | 473 | // recursive type |
482 | let default = self.type_variable_table.fallback_value(var, kind).cast(&Interner); | 474 | let default = self.table.fallback_value(var, kind).cast(&Interner); |
483 | return Ok((self.fallback)(var, VariableKind::Ty(kind), default, outer_binder) | 475 | return Ok((self.fallback)(var, VariableKind::Ty(kind), default, outer_binder) |
484 | .assert_ty_ref(&Interner) | 476 | .assert_ty_ref(&Interner) |
485 | .clone()); | 477 | .clone()); |
486 | } | 478 | } |
487 | let result = if let Some(known_ty) = self.var_unification_table.probe_var(var) { | 479 | let result = if let Some(known_ty) = self.table.var_unification_table.probe_var(var) { |
488 | // known_ty may contain other variables that are known by now | 480 | // known_ty may contain other variables that are known by now |
489 | self.var_stack.push(var); | 481 | self.var_stack.push(var); |
490 | let result = | 482 | let result = |
@@ -492,7 +484,7 @@ mod resolve { | |||
492 | self.var_stack.pop(); | 484 | self.var_stack.pop(); |
493 | result.assert_ty_ref(&Interner).clone() | 485 | result.assert_ty_ref(&Interner).clone() |
494 | } else { | 486 | } else { |
495 | let default = self.type_variable_table.fallback_value(var, kind).cast(&Interner); | 487 | let default = self.table.fallback_value(var, kind).cast(&Interner); |
496 | (self.fallback)(var, VariableKind::Ty(kind), default, outer_binder) | 488 | (self.fallback)(var, VariableKind::Ty(kind), default, outer_binder) |
497 | .assert_ty_ref(&Interner) | 489 | .assert_ty_ref(&Interner) |
498 | .clone() | 490 | .clone() |
@@ -506,7 +498,7 @@ mod resolve { | |||
506 | var: InferenceVar, | 498 | var: InferenceVar, |
507 | outer_binder: DebruijnIndex, | 499 | outer_binder: DebruijnIndex, |
508 | ) -> Fallible<Const> { | 500 | ) -> Fallible<Const> { |
509 | let var = self.var_unification_table.inference_var_root(var); | 501 | let var = self.table.var_unification_table.inference_var_root(var); |
510 | let default = ConstData { | 502 | let default = ConstData { |
511 | ty: ty.clone(), | 503 | ty: ty.clone(), |
512 | value: ConstValue::Concrete(ConcreteConst { interned: ConstScalar::Unknown }), | 504 | value: ConstValue::Concrete(ConcreteConst { interned: ConstScalar::Unknown }), |
@@ -519,7 +511,7 @@ mod resolve { | |||
519 | .assert_const_ref(&Interner) | 511 | .assert_const_ref(&Interner) |
520 | .clone()); | 512 | .clone()); |
521 | } | 513 | } |
522 | let result = if let Some(known_ty) = self.var_unification_table.probe_var(var) { | 514 | let result = if let Some(known_ty) = self.table.var_unification_table.probe_var(var) { |
523 | // known_ty may contain other variables that are known by now | 515 | // known_ty may contain other variables that are known by now |
524 | self.var_stack.push(var); | 516 | self.var_stack.push(var); |
525 | let result = | 517 | let result = |