From d280538174eb51382dc49b934fd5e096f3b36554 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Tue, 6 Apr 2021 20:51:21 +0200 Subject: Clean up Chalk mapping a bit --- crates/hir_ty/src/traits/chalk/mapping.rs | 106 +++++++++++------------------- 1 file changed, 37 insertions(+), 69 deletions(-) diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index cf73cb078..0536b934e 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs @@ -10,10 +10,9 @@ use base_db::salsa::InternKey; use hir_def::{GenericDefId, TypeAliasId}; use crate::{ - chalk_ext::ProjectionTyExt, db::HirDatabase, dummy_usize_const, static_lifetime, AliasTy, - CallableDefId, Canonical, Const, DomainGoal, FnPointer, GenericArg, InEnvironment, Lifetime, - OpaqueTy, ProjectionTy, QuantifiedWhereClause, Substitution, TraitRef, Ty, TypeWalk, - WhereClause, + chalk_ext::ProjectionTyExt, db::HirDatabase, static_lifetime, AliasTy, CallableDefId, + Canonical, DomainGoal, FnPointer, GenericArg, InEnvironment, OpaqueTy, ProjectionTy, + QuantifiedWhereClause, Substitution, TraitRef, Ty, TypeWalk, WhereClause, }; use super::interner::*; @@ -23,16 +22,16 @@ impl ToChalk for Ty { type Chalk = chalk_ir::Ty; fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty { match self.into_inner() { - TyKind::Ref(m, lt, ty) => ref_to_chalk(db, m, lt, ty), - TyKind::Array(ty, size) => array_to_chalk(db, ty, size), - TyKind::Function(FnPointer { sig, substitution: substs, .. }) => { + TyKind::Ref(m, lt, ty) => { + chalk_ir::TyKind::Ref(m, lt, ty.to_chalk(db)).intern(&Interner) + } + TyKind::Array(ty, size) => { + chalk_ir::TyKind::Array(ty.to_chalk(db), size).intern(&Interner) + } + TyKind::Function(FnPointer { sig, substitution: substs, num_binders }) => { let substitution = chalk_ir::FnSubst(substs.0.to_chalk(db)); - chalk_ir::TyKind::Function(chalk_ir::FnPointer { - num_binders: 0, - sig, - substitution, - }) - .intern(&Interner) + chalk_ir::TyKind::Function(chalk_ir::FnPointer { num_binders, sig, substitution }) + .intern(&Interner) } TyKind::AssociatedType(assoc_type_id, substs) => { let substitution = substs.to_chalk(db); @@ -74,22 +73,13 @@ impl ToChalk for Ty { chalk_ir::TyKind::Adt(adt_id, substitution).intern(&Interner) } TyKind::Alias(AliasTy::Projection(proj_ty)) => { - let associated_ty_id = proj_ty.associated_ty_id; - let substitution = proj_ty.substitution.to_chalk(db); - chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { - associated_ty_id, - substitution, - }) - .cast(&Interner) - .intern(&Interner) - } - TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { - let opaque_ty_id = opaque_ty.opaque_ty_id; - let substitution = opaque_ty.substitution.to_chalk(db); - chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { opaque_ty_id, substitution }) + chalk_ir::AliasTy::Projection(proj_ty.to_chalk(db)) .cast(&Interner) .intern(&Interner) } + TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { + chalk_ir::AliasTy::Opaque(opaque_ty.to_chalk(db)).cast(&Interner).intern(&Interner) + } TyKind::Placeholder(idx) => idx.to_ty::(&Interner), TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), @@ -101,7 +91,7 @@ impl ToChalk for Ty { ); let bounded_ty = chalk_ir::DynTy { bounds: chalk_ir::Binders::new(binders, where_clauses), - lifetime: static_lifetime(), + lifetime: dyn_ty.lifetime, }; chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner) } @@ -114,17 +104,10 @@ impl ToChalk for Ty { chalk_ir::TyKind::Array(ty, size) => TyKind::Array(from_chalk(db, ty), size), chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx), chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => { - let associated_ty = proj.associated_ty_id; - let parameters = from_chalk(db, proj.substitution); - TyKind::Alias(AliasTy::Projection(ProjectionTy { - associated_ty_id: associated_ty, - substitution: parameters, - })) + TyKind::Alias(AliasTy::Projection(from_chalk(db, proj))) } chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => { - let opaque_ty_id = opaque_ty.opaque_ty_id; - let parameters = from_chalk(db, opaque_ty.substitution); - TyKind::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id, substitution: parameters })) + TyKind::Alias(AliasTy::Opaque(from_chalk(db, opaque_ty))) } chalk_ir::TyKind::Function(chalk_ir::FnPointer { num_binders, @@ -138,18 +121,19 @@ impl ToChalk for Ty { } chalk_ir::TyKind::BoundVar(idx) => TyKind::BoundVar(idx), chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Error, - chalk_ir::TyKind::Dyn(where_clauses) => { - assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); - let bounds = where_clauses - .bounds - .skip_binders() - .iter(&Interner) - .map(|c| from_chalk(db, c.clone())); + chalk_ir::TyKind::Dyn(dyn_ty) => { + assert_eq!(dyn_ty.bounds.binders.len(&Interner), 1); + let (bounds, binders) = dyn_ty.bounds.into_value_and_skipped_binders(); + let where_clauses = crate::QuantifiedWhereClauses::from_iter( + &Interner, + bounds.interned().iter().cloned().map(|p| from_chalk(db, p)), + ); TyKind::Dyn(crate::DynTy { - bounds: crate::Binders::new( - where_clauses.bounds.binders.clone(), - crate::QuantifiedWhereClauses::from_iter(&Interner, bounds), - ), + bounds: crate::Binders::new(binders, where_clauses), + // HACK: we sometimes get lifetime variables back in solutions + // from Chalk, and don't have the infrastructure to substitute + // them yet. So for now we just turn them into 'static right + // when we get them lifetime: static_lifetime(), }) } @@ -169,8 +153,12 @@ impl ToChalk for Ty { } chalk_ir::TyKind::Raw(mutability, ty) => TyKind::Raw(mutability, from_chalk(db, ty)), chalk_ir::TyKind::Slice(ty) => TyKind::Slice(from_chalk(db, ty)), - chalk_ir::TyKind::Ref(mutability, lifetime, ty) => { - TyKind::Ref(mutability, lifetime, from_chalk(db, ty)) + chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => { + // HACK: we sometimes get lifetime variables back in solutions + // from Chalk, and don't have the infrastructure to substitute + // them yet. So for now we just turn them into 'static right + // when we get them + TyKind::Ref(mutability, static_lifetime(), from_chalk(db, ty)) } chalk_ir::TyKind::Str => TyKind::Str, chalk_ir::TyKind::Never => TyKind::Never, @@ -189,26 +177,6 @@ impl ToChalk for Ty { } } -/// We currently don't model lifetimes, but Chalk does. So, we have to insert a -/// fake lifetime here, because Chalks built-in logic may expect it to be there. -fn ref_to_chalk( - db: &dyn HirDatabase, - mutability: chalk_ir::Mutability, - _lifetime: Lifetime, - ty: Ty, -) -> chalk_ir::Ty { - let arg = ty.to_chalk(db); - let lifetime = static_lifetime(); - chalk_ir::TyKind::Ref(mutability, lifetime, arg).intern(&Interner) -} - -/// We currently don't model constants, but Chalk does. So, we have to insert a -/// fake constant here, because Chalks built-in logic may expect it to be there. -fn array_to_chalk(db: &dyn HirDatabase, ty: Ty, _: Const) -> chalk_ir::Ty { - let arg = ty.to_chalk(db); - chalk_ir::TyKind::Array(arg, dummy_usize_const()).intern(&Interner) -} - impl ToChalk for GenericArg { type Chalk = chalk_ir::GenericArg; -- cgit v1.2.3 From 768ee3e47a140e354575154f431421375b0b5203 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Tue, 6 Apr 2021 21:09:52 +0200 Subject: Align `InferenceVar` to Chalk --- crates/hir_ty/src/infer.rs | 19 ------------------- crates/hir_ty/src/infer/unify.rs | 36 ++++++++++++++++++++++++------------ crates/hir_ty/src/lib.rs | 2 +- crates/hir_ty/src/types.rs | 25 +++++++++++++++++++++++-- 4 files changed, 48 insertions(+), 34 deletions(-) diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index efe9198cc..75d633c96 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs @@ -683,25 +683,6 @@ impl<'a> InferenceContext<'a> { } } -/// The kinds of placeholders we need during type inference. There's separate -/// values for general types, and for integer and float variables. The latter -/// two are used for inference of literal values (e.g. `100` could be one of -/// several integer types). -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] -pub struct InferenceVar { - index: u32, -} - -impl InferenceVar { - fn to_inner(self) -> unify::TypeVarId { - unify::TypeVarId(self.index) - } - - fn from_inner(unify::TypeVarId(index): unify::TypeVarId) -> Self { - InferenceVar { index } - } -} - /// When inferring an expression, we propagate downward whatever type hint we /// are able in the form of an `Expectation`. #[derive(Clone, PartialEq, Eq, Debug)] diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 7d76cda68..d717e3375 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs @@ -51,7 +51,7 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { t.fold_binders( &mut |ty, binders| match ty.kind(&Interner) { &TyKind::InferenceVar(var, kind) => { - let inner = var.to_inner(); + let inner = from_inference_var(var); if self.var_stack.contains(&inner) { // recursive type return self.ctx.table.type_variable_table.fallback_value(var, kind); @@ -65,7 +65,7 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { result } else { let root = self.ctx.table.var_unification_table.find(inner); - let position = self.add(InferenceVar::from_inner(root), kind); + let position = self.add(to_inference_var(root), kind); TyKind::BoundVar(BoundVar::new(binders, position)).intern(&Interner) } } @@ -207,16 +207,16 @@ impl TypeVariableTable { } pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) { - self.inner[iv.to_inner().0 as usize].diverging = diverging; + self.inner[from_inference_var(iv).0 as usize].diverging = diverging; } fn is_diverging(&mut self, iv: InferenceVar) -> bool { - self.inner[iv.to_inner().0 as usize].diverging + self.inner[from_inference_var(iv).0 as usize].diverging } fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { match kind { - _ if self.inner[iv.to_inner().0 as usize].diverging => TyKind::Never, + _ if self.inner[from_inference_var(iv).0 as usize].diverging => TyKind::Never, TyVariableKind::General => TyKind::Error, TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)), TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)), @@ -250,7 +250,7 @@ impl InferenceTable { self.type_variable_table.push(TypeVariableData { diverging }); let key = self.var_unification_table.new_key(TypeVarValue::Unknown); assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1); - TyKind::InferenceVar(InferenceVar::from_inner(key), kind).intern(&Interner) + TyKind::InferenceVar(to_inference_var(key), kind).intern(&Interner) } pub(crate) fn new_type_var(&mut self) -> Ty { @@ -369,8 +369,12 @@ impl InferenceTable { == self.type_variable_table.is_diverging(*tv2) => { // both type vars are unknown since we tried to resolve them - if !self.var_unification_table.unioned(tv1.to_inner(), tv2.to_inner()) { - self.var_unification_table.union(tv1.to_inner(), tv2.to_inner()); + if !self + .var_unification_table + .unioned(from_inference_var(*tv1), from_inference_var(*tv2)) + { + self.var_unification_table + .union(from_inference_var(*tv1), from_inference_var(*tv2)); self.revision += 1; } true @@ -407,7 +411,7 @@ impl InferenceTable { ) => { // the type var is unknown since we tried to resolve it self.var_unification_table.union_value( - tv.to_inner(), + from_inference_var(*tv), TypeVarValue::Known(other.clone().intern(&Interner)), ); self.revision += 1; @@ -462,7 +466,7 @@ impl InferenceTable { } match ty.kind(&Interner) { TyKind::InferenceVar(tv, _) => { - let inner = tv.to_inner(); + let inner = from_inference_var(*tv); match self.var_unification_table.inlined_probe_value(inner).known() { Some(known_ty) => { // The known_ty can't be a type var itself @@ -485,7 +489,7 @@ impl InferenceTable { fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec, ty: Ty) -> Ty { ty.fold(&mut |ty| match ty.kind(&Interner) { &TyKind::InferenceVar(tv, kind) => { - let inner = tv.to_inner(); + let inner = from_inference_var(tv); if tv_stack.contains(&inner) { cov_mark::hit!(type_var_cycles_resolve_as_possible); // recursive type @@ -512,7 +516,7 @@ impl InferenceTable { fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec, ty: Ty) -> Ty { ty.fold(&mut |ty| match ty.kind(&Interner) { &TyKind::InferenceVar(tv, kind) => { - let inner = tv.to_inner(); + let inner = from_inference_var(tv); if tv_stack.contains(&inner) { cov_mark::hit!(type_var_cycles_resolve_completely); // recursive type @@ -555,6 +559,14 @@ impl UnifyKey for TypeVarId { } } +fn from_inference_var(var: InferenceVar) -> TypeVarId { + TypeVarId(var.index()) +} + +fn to_inference_var(TypeVarId(index): TypeVarId) -> InferenceVar { + index.into() +} + /// The value of a type variable: either we already know the type, or we don't /// know it yet. #[derive(Clone, PartialEq, Eq, Debug)] diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index f5b658cba..5c83a508d 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -42,7 +42,7 @@ use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; pub use autoderef::autoderef; pub use builder::TyBuilder; pub use chalk_ext::{ProjectionTyExt, TyExt}; -pub use infer::{could_unify, InferenceResult, InferenceVar}; +pub use infer::{could_unify, InferenceResult}; pub use lower::{ associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, TyDefId, TyLoweringContext, ValueTyDefId, diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs index 89c0ddd1a..eac1b7900 100644 --- a/crates/hir_ty/src/types.rs +++ b/crates/hir_ty/src/types.rs @@ -11,8 +11,7 @@ use smallvec::SmallVec; use crate::{ AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, Const, FnDefId, FnSig, ForeignDefId, - InferenceVar, Interner, Lifetime, OpaqueTyId, PlaceholderIndex, TypeWalk, VariableKind, - VariableKinds, + Interner, Lifetime, OpaqueTyId, PlaceholderIndex, TypeWalk, VariableKind, VariableKinds, }; #[derive(Clone, PartialEq, Eq, Debug, Hash)] @@ -524,3 +523,25 @@ pub enum Guidance { /// There's no useful information to feed back to type inference Unknown, } + +/// The kinds of placeholders we need during type inference. There's separate +/// values for general types, and for integer and float variables. The latter +/// two are used for inference of literal values (e.g. `100` could be one of +/// several integer types). +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct InferenceVar { + index: u32, +} + +impl From for InferenceVar { + fn from(index: u32) -> InferenceVar { + InferenceVar { index } + } +} + +impl InferenceVar { + /// Gets the underlying index value. + pub fn index(self) -> u32 { + self.index + } +} -- cgit v1.2.3