Remove TypeVariableTable

This commit is contained in:
Florian Diebold 2021-05-16 20:04:00 +02:00
parent 9716c0b949
commit 99c73537fa
2 changed files with 48 additions and 56 deletions

View file

@ -101,7 +101,7 @@ impl<'a> InferenceContext<'a> {
// here, we would coerce from `!` to `?T`. // here, we would coerce from `!` to `?T`.
match to_ty.kind(&Interner) { match to_ty.kind(&Interner) {
TyKind::InferenceVar(tv, TyVariableKind::General) => { TyKind::InferenceVar(tv, TyVariableKind::General) => {
self.table.type_variable_table.set_diverging(*tv, true); self.table.set_diverging(*tv, true);
} }
_ => {} _ => {}
} }

View file

@ -127,29 +127,6 @@ pub(crate) fn unify(
)) ))
} }
#[derive(Clone, Debug)]
pub(super) struct TypeVariableTable {
inner: Vec<TypeVariableData>,
}
impl TypeVariableTable {
pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) {
self.inner[iv.index() as usize].diverging = diverging;
}
fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
match kind {
_ if self.inner.get(iv.index() as usize).map_or(false, |data| data.diverging) => {
TyKind::Never
}
TyVariableKind::General => TyKind::Error,
TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)),
TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)),
}
.intern(&Interner)
}
}
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub(crate) struct TypeVariableData { pub(crate) struct TypeVariableData {
diverging: bool, diverging: bool,
@ -162,7 +139,7 @@ pub(crate) struct InferenceTable<'a> {
pub db: &'a dyn HirDatabase, pub db: &'a dyn HirDatabase,
pub trait_env: Arc<TraitEnvironment>, pub trait_env: Arc<TraitEnvironment>,
pub(super) var_unification_table: ChalkInferenceTable, pub(super) var_unification_table: ChalkInferenceTable,
pub(super) type_variable_table: TypeVariableTable, pub(super) type_variable_table: Vec<TypeVariableData>,
pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>, pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>,
} }
@ -172,7 +149,7 @@ impl<'a> InferenceTable<'a> {
db, db,
trait_env, trait_env,
var_unification_table: ChalkInferenceTable::new(), var_unification_table: ChalkInferenceTable::new(),
type_variable_table: TypeVariableTable { inner: Vec::new() }, type_variable_table: Vec::new(),
pending_obligations: Vec::new(), pending_obligations: Vec::new(),
} }
} }
@ -184,18 +161,38 @@ impl<'a> InferenceTable<'a> {
/// marked as diverging if necessary, so that resolving them gives the right /// marked as diverging if necessary, so that resolving them gives the right
/// result. /// result.
pub(super) fn propagate_diverging_flag(&mut self) { pub(super) fn propagate_diverging_flag(&mut self) {
for i in 0..self.type_variable_table.inner.len() { for i in 0..self.type_variable_table.len() {
if !self.type_variable_table.inner[i].diverging { if !self.type_variable_table[i].diverging {
continue; continue;
} }
let v = InferenceVar::from(i as u32); let v = InferenceVar::from(i as u32);
let root = self.var_unification_table.inference_var_root(v); let root = self.var_unification_table.inference_var_root(v);
if let Some(data) = self.type_variable_table.inner.get_mut(root.index() as usize) { if let Some(data) = self.type_variable_table.get_mut(root.index() as usize) {
data.diverging = true; data.diverging = true;
} }
} }
} }
pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) {
self.type_variable_table[iv.index() as usize].diverging = diverging;
}
fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
match kind {
_ if self
.type_variable_table
.get(iv.index() as usize)
.map_or(false, |data| data.diverging) =>
{
TyKind::Never
}
TyVariableKind::General => TyKind::Error,
TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)),
TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)),
}
.intern(&Interner)
}
pub(super) fn canonicalize<T: Fold<Interner> + HasInterner<Interner = Interner>>( pub(super) fn canonicalize<T: Fold<Interner> + HasInterner<Interner = Interner>>(
&mut self, &mut self,
t: T, t: T,
@ -239,16 +236,19 @@ impl<'a> InferenceTable<'a> {
var var
} }
fn extend_type_variable_table(&mut self, to_index: usize) {
self.type_variable_table.extend(
(0..1 + to_index - self.type_variable_table.len())
.map(|_| TypeVariableData { diverging: false }),
);
}
fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty { fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty {
let var = self.var_unification_table.new_variable(UniverseIndex::ROOT); let var = self.var_unification_table.new_variable(UniverseIndex::ROOT);
// Chalk might have created some type variables for its own purposes that we don't know about... // Chalk might have created some type variables for its own purposes that we don't know about...
// TODO refactor this? self.extend_type_variable_table(var.index() as usize);
self.type_variable_table.inner.extend( assert_eq!(var.index() as usize, self.type_variable_table.len() - 1);
(0..1 + var.index() as usize - self.type_variable_table.inner.len()) self.type_variable_table[var.index() as usize].diverging = diverging;
.map(|_| TypeVariableData { diverging: false }),
);
assert_eq!(var.index() as usize, self.type_variable_table.inner.len() - 1);
self.type_variable_table.inner[var.index() as usize].diverging = diverging;
var.to_ty_with_kind(&Interner, kind) var.to_ty_with_kind(&Interner, kind)
} }
@ -289,12 +289,7 @@ impl<'a> InferenceTable<'a> {
T: HasInterner<Interner = Interner> + Fold<Interner>, T: HasInterner<Interner = Interner> + Fold<Interner>,
{ {
t.fold_with( t.fold_with(
&mut resolve::Resolver { &mut resolve::Resolver { table: self, var_stack, fallback },
type_variable_table: &self.type_variable_table,
var_unification_table: &mut self.var_unification_table,
var_stack,
fallback,
},
DebruijnIndex::INNERMOST, DebruijnIndex::INNERMOST,
) )
.expect("fold failed unexpectedly") .expect("fold failed unexpectedly")
@ -433,14 +428,12 @@ impl<'a> InferenceTable<'a> {
impl<'a> fmt::Debug for InferenceTable<'a> { impl<'a> fmt::Debug for InferenceTable<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("InferenceTable") f.debug_struct("InferenceTable").field("num_vars", &self.type_variable_table.len()).finish()
.field("num_vars", &self.type_variable_table.inner.len())
.finish()
} }
} }
mod resolve { mod resolve {
use super::{ChalkInferenceTable, TypeVariableTable}; use super::InferenceTable;
use crate::{ use crate::{
ConcreteConst, Const, ConstData, ConstValue, DebruijnIndex, GenericArg, InferenceVar, ConcreteConst, Const, ConstData, ConstValue, DebruijnIndex, GenericArg, InferenceVar,
Interner, Ty, TyVariableKind, VariableKind, Interner, Ty, TyVariableKind, VariableKind,
@ -452,13 +445,12 @@ mod resolve {
}; };
use hir_def::type_ref::ConstScalar; use hir_def::type_ref::ConstScalar;
pub(super) struct Resolver<'a, F> { pub(super) struct Resolver<'a, 'b, F> {
pub type_variable_table: &'a TypeVariableTable, pub table: &'a mut InferenceTable<'b>,
pub var_unification_table: &'a mut ChalkInferenceTable,
pub var_stack: &'a mut Vec<InferenceVar>, pub var_stack: &'a mut Vec<InferenceVar>,
pub fallback: F, pub fallback: F,
} }
impl<'a, 'i, F> Folder<'i, Interner> for Resolver<'a, F> impl<'a, 'b, 'i, F> Folder<'i, Interner> for Resolver<'a, 'b, F>
where where
F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg + 'i, F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg + 'i,
{ {
@ -476,15 +468,15 @@ mod resolve {
kind: TyVariableKind, kind: TyVariableKind,
outer_binder: DebruijnIndex, outer_binder: DebruijnIndex,
) -> Fallible<Ty> { ) -> Fallible<Ty> {
let var = self.var_unification_table.inference_var_root(var); let var = self.table.var_unification_table.inference_var_root(var);
if self.var_stack.contains(&var) { if self.var_stack.contains(&var) {
// recursive type // recursive type
let default = self.type_variable_table.fallback_value(var, kind).cast(&Interner); let default = self.table.fallback_value(var, kind).cast(&Interner);
return Ok((self.fallback)(var, VariableKind::Ty(kind), default, outer_binder) return Ok((self.fallback)(var, VariableKind::Ty(kind), default, outer_binder)
.assert_ty_ref(&Interner) .assert_ty_ref(&Interner)
.clone()); .clone());
} }
let result = if let Some(known_ty) = self.var_unification_table.probe_var(var) { let result = if let Some(known_ty) = self.table.var_unification_table.probe_var(var) {
// known_ty may contain other variables that are known by now // known_ty may contain other variables that are known by now
self.var_stack.push(var); self.var_stack.push(var);
let result = let result =
@ -492,7 +484,7 @@ mod resolve {
self.var_stack.pop(); self.var_stack.pop();
result.assert_ty_ref(&Interner).clone() result.assert_ty_ref(&Interner).clone()
} else { } else {
let default = self.type_variable_table.fallback_value(var, kind).cast(&Interner); let default = self.table.fallback_value(var, kind).cast(&Interner);
(self.fallback)(var, VariableKind::Ty(kind), default, outer_binder) (self.fallback)(var, VariableKind::Ty(kind), default, outer_binder)
.assert_ty_ref(&Interner) .assert_ty_ref(&Interner)
.clone() .clone()
@ -506,7 +498,7 @@ mod resolve {
var: InferenceVar, var: InferenceVar,
outer_binder: DebruijnIndex, outer_binder: DebruijnIndex,
) -> Fallible<Const> { ) -> Fallible<Const> {
let var = self.var_unification_table.inference_var_root(var); let var = self.table.var_unification_table.inference_var_root(var);
let default = ConstData { let default = ConstData {
ty: ty.clone(), ty: ty.clone(),
value: ConstValue::Concrete(ConcreteConst { interned: ConstScalar::Unknown }), value: ConstValue::Concrete(ConcreteConst { interned: ConstScalar::Unknown }),
@ -519,7 +511,7 @@ mod resolve {
.assert_const_ref(&Interner) .assert_const_ref(&Interner)
.clone()); .clone());
} }
let result = if let Some(known_ty) = self.var_unification_table.probe_var(var) { let result = if let Some(known_ty) = self.table.var_unification_table.probe_var(var) {
// known_ty may contain other variables that are known by now // known_ty may contain other variables that are known by now
self.var_stack.push(var); self.var_stack.push(var);
let result = let result =