aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/infer/coerce.rs2
-rw-r--r--crates/hir_ty/src/infer/unify.rs102
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)]
131pub(super) struct TypeVariableTable {
132 inner: Vec<TypeVariableData>,
133}
134
135impl 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)]
154pub(crate) struct TypeVariableData { 131pub(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
434impl<'a> fmt::Debug for InferenceTable<'a> { 429impl<'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
442mod resolve { 435mod 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 =