diff --git a/Cargo.lock b/Cargo.lock index e45cde68388..e612495df57 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -171,9 +171,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chalk-derive" -version = "0.84.0" +version = "0.86.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf29c109d57f8d57b0e7675391be37a9285d86dd93278bd5f14a0ad3c447a6c2" +checksum = "5499d415d855b5094366a824815341893ad3de0ecb6048c430118bdae6d27402" dependencies = [ "proc-macro2", "quote", @@ -183,9 +183,9 @@ dependencies = [ [[package]] name = "chalk-ir" -version = "0.84.0" +version = "0.86.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d391763027b5e50a5e15caf6d2857ec585fd68160367bbeac9e1804209620918" +checksum = "3800118c76a48507b0eece3a01f3a429b5c478d203c493096e6040c67ab960e1" dependencies = [ "bitflags", "chalk-derive", @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "chalk-recursive" -version = "0.84.0" +version = "0.86.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afafd92dcdc7fe0ea940ee94bdd8cc5bd18f4a4a84c593d6d7025fe16c150478" +checksum = "1baf60628fd73104d1f8562586a52d48f37f1e84435aab2e62674b1fd935b8c8" dependencies = [ "chalk-derive", "chalk-ir", @@ -207,9 +207,9 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.84.0" +version = "0.86.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af1d111f11c91c48ace02e93e470c5bae6d2631bd112e4545317da53660d7fc" +checksum = "0e9c3c068f9358786348e58a1b94ef0a5cf90a9810fc1f10fda896f0b5d80185" dependencies = [ "chalk-derive", "chalk-ir", @@ -546,6 +546,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", + "chalk-derive", "chalk-ir", "chalk-recursive", "chalk-solve", diff --git a/Cargo.toml b/Cargo.toml index 6b68ca82389..286ef1e7dcb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ debug = 0 # chalk-solve = { path = "../chalk/chalk-solve" } # chalk-ir = { path = "../chalk/chalk-ir" } # chalk-recursive = { path = "../chalk/chalk-recursive" } +# chalk-derive = { path = "../chalk/chalk-derive" } # ungrammar = { path = "../ungrammar" } diff --git a/crates/hir-ty/Cargo.toml b/crates/hir-ty/Cargo.toml index 7f143f396c7..df68a37bf45 100644 --- a/crates/hir-ty/Cargo.toml +++ b/crates/hir-ty/Cargo.toml @@ -18,9 +18,10 @@ ena = "0.14.0" tracing = "0.1.35" rustc-hash = "1.1.0" scoped-tls = "1.0.0" -chalk-solve = { version = "0.84.0", default-features = false } -chalk-ir = "0.84.0" -chalk-recursive = { version = "0.84.0", default-features = false } +chalk-solve = { version = "0.86.0", default-features = false } +chalk-ir = "0.86.0" +chalk-recursive = { version = "0.86.0", default-features = false } +chalk-derive = "0.86.0" la-arena = { version = "0.3.0", path = "../../lib/la-arena" } once_cell = "1.12.0" typed-arena = "2.0.1" diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs index 3f3f8f7d0f2..43c3451cab3 100644 --- a/crates/hir-ty/src/chalk_db.rs +++ b/crates/hir-ty/src/chalk_db.rs @@ -823,10 +823,10 @@ pub(super) fn generic_predicate_to_inline_bound( Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound))) } WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { - if projection_ty.self_type_parameter(Interner) != self_ty_shifted_in { + let trait_ = projection_ty.trait_(db); + if projection_ty.self_type_parameter(db) != self_ty_shifted_in { return None; } - let trait_ = projection_ty.trait_(db); let args_no_self = projection_ty.substitution.as_slice(Interner)[1..] .iter() .map(|ty| ty.clone().cast(Interner)) diff --git a/crates/hir-ty/src/chalk_ext.rs b/crates/hir-ty/src/chalk_ext.rs index 4f0e9dbf1e4..e2099d7e509 100644 --- a/crates/hir-ty/src/chalk_ext.rs +++ b/crates/hir-ty/src/chalk_ext.rs @@ -262,7 +262,7 @@ impl TyExt for Ty { WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), ty: _, - }) => &proj.self_type_parameter(Interner) == self, + }) => &proj.self_type_parameter(db) == self, _ => false, }) .collect::>(); @@ -333,6 +333,7 @@ impl TyExt for Ty { pub trait ProjectionTyExt { fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef; fn trait_(&self, db: &dyn HirDatabase) -> TraitId; + fn self_type_parameter(&self, db: &dyn HirDatabase) -> Ty; } impl ProjectionTyExt for ProjectionTy { @@ -349,6 +350,10 @@ impl ProjectionTyExt for ProjectionTy { _ => panic!("projection ty without parent trait"), } } + + fn self_type_parameter(&self, db: &dyn HirDatabase) -> Ty { + self.trait_ref(db).self_type_parameter(Interner) + } } pub trait TraitRefExt { diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index a6602747ef7..0221f922feb 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -291,7 +291,7 @@ impl HirDisplay for ProjectionTy { let trait_ = f.db.trait_data(self.trait_(f.db)); write!(f, "<")?; - self.self_type_parameter(Interner).hir_fmt(f)?; + self.self_type_parameter(f.db).hir_fmt(f)?; write!(f, " as {}", trait_.name)?; if self.substitution.len(Interner) > 1 { write!(f, "<")?; @@ -731,7 +731,7 @@ impl HirDisplay for Ty { WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), ty: _, - }) => &proj.self_type_parameter(Interner) == self, + }) => &proj.self_type_parameter(f.db) == self, _ => false, }) .collect::>(); diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index 6ccd0b215c6..b00e3216b2d 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -4,7 +4,7 @@ use std::{fmt, mem, sync::Arc}; use chalk_ir::{ cast::Cast, fold::TypeFoldable, interner::HasInterner, zip::Zip, CanonicalVarKind, FloatTy, - IntTy, NoSolution, TyVariableKind, UniverseIndex, + IntTy, TyVariableKind, UniverseIndex, }; use chalk_solve::infer::ParameterEnaVariableExt; use ena::unify::UnifyKey; @@ -331,7 +331,6 @@ impl<'a> InferenceTable<'a> { &mut resolve::Resolver { table: self, var_stack, fallback }, DebruijnIndex::INNERMOST, ) - .expect("fold failed unexpectedly") } pub(crate) fn resolve_completely(&mut self, t: T) -> T @@ -452,13 +451,14 @@ impl<'a> InferenceTable<'a> { f: impl FnOnce(&mut Self) -> T, ) -> T { use chalk_ir::fold::TypeFolder; + + #[derive(chalk_derive::FallibleTypeFolder)] + #[has_interner(Interner)] struct VarFudger<'a, 'b> { table: &'a mut InferenceTable<'b>, highest_known_var: InferenceVar, } impl<'a, 'b> TypeFolder for VarFudger<'a, 'b> { - type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } @@ -472,24 +472,24 @@ impl<'a> InferenceTable<'a> { var: chalk_ir::InferenceVar, kind: TyVariableKind, _outer_binder: chalk_ir::DebruijnIndex, - ) -> chalk_ir::Fallible> { - Ok(if var < self.highest_known_var { + ) -> chalk_ir::Ty { + if var < self.highest_known_var { var.to_ty(Interner, kind) } else { self.table.new_type_var() - }) + } } fn fold_inference_lifetime( &mut self, var: chalk_ir::InferenceVar, _outer_binder: chalk_ir::DebruijnIndex, - ) -> chalk_ir::Fallible> { - Ok(if var < self.highest_known_var { + ) -> chalk_ir::Lifetime { + if var < self.highest_known_var { var.to_lifetime(Interner) } else { self.table.new_lifetime_var() - }) + } } fn fold_inference_const( @@ -497,12 +497,12 @@ impl<'a> InferenceTable<'a> { ty: chalk_ir::Ty, var: chalk_ir::InferenceVar, _outer_binder: chalk_ir::DebruijnIndex, - ) -> chalk_ir::Fallible> { - Ok(if var < self.highest_known_var { + ) -> chalk_ir::Const { + if var < self.highest_known_var { var.to_const(Interner, ty) } else { self.table.new_const_var(ty) - }) + } } } @@ -512,7 +512,6 @@ impl<'a> InferenceTable<'a> { self.rollback_to(snapshot); result .fold_with(&mut VarFudger { table: self, highest_known_var }, DebruijnIndex::INNERMOST) - .expect("fold_with with VarFudger") } /// This checks whether any of the free variables in the `canonicalized` @@ -639,21 +638,24 @@ mod resolve { use chalk_ir::{ cast::Cast, fold::{TypeFoldable, TypeFolder}, - Fallible, NoSolution, }; use hir_def::type_ref::ConstScalar; - pub(super) struct Resolver<'a, 'b, F> { + #[derive(chalk_derive::FallibleTypeFolder)] + #[has_interner(Interner)] + pub(super) struct Resolver< + 'a, + 'b, + F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg, + > { pub(super) table: &'a mut InferenceTable<'b>, pub(super) var_stack: &'a mut Vec, pub(super) fallback: F, } - impl<'a, 'b, 'i, F> TypeFolder for Resolver<'a, 'b, F> + impl<'a, 'b, F> TypeFolder for Resolver<'a, 'b, F> where - F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg + 'i, + F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg, { - type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } @@ -667,20 +669,19 @@ mod resolve { var: InferenceVar, kind: TyVariableKind, outer_binder: DebruijnIndex, - ) -> Fallible { + ) -> Ty { let var = self.table.var_unification_table.inference_var_root(var); if self.var_stack.contains(&var) { // recursive type let default = self.table.fallback_value(var, kind).cast(Interner); - return Ok((self.fallback)(var, VariableKind::Ty(kind), default, outer_binder) + return (self.fallback)(var, VariableKind::Ty(kind), default, outer_binder) .assert_ty_ref(Interner) - .clone()); + .clone(); } 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 self.var_stack.push(var); - let result = - known_ty.fold_with(self, outer_binder).expect("fold failed unexpectedly"); + let result = known_ty.fold_with(self, outer_binder); self.var_stack.pop(); result.assert_ty_ref(Interner).clone() } else { @@ -689,7 +690,7 @@ mod resolve { .assert_ty_ref(Interner) .clone() }; - Ok(result) + result } fn fold_inference_const( @@ -697,7 +698,7 @@ mod resolve { ty: Ty, var: InferenceVar, outer_binder: DebruijnIndex, - ) -> Fallible { + ) -> Const { let var = self.table.var_unification_table.inference_var_root(var); let default = ConstData { ty: ty.clone(), @@ -707,35 +708,33 @@ mod resolve { .cast(Interner); if self.var_stack.contains(&var) { // recursive - return Ok((self.fallback)(var, VariableKind::Const(ty), default, outer_binder) + return (self.fallback)(var, VariableKind::Const(ty), default, outer_binder) .assert_const_ref(Interner) - .clone()); + .clone(); } - let result = if let Some(known_ty) = self.table.var_unification_table.probe_var(var) { + if let Some(known_ty) = self.table.var_unification_table.probe_var(var) { // known_ty may contain other variables that are known by now self.var_stack.push(var); - let result = - known_ty.fold_with(self, outer_binder).expect("fold failed unexpectedly"); + let result = known_ty.fold_with(self, outer_binder); self.var_stack.pop(); result.assert_const_ref(Interner).clone() } else { (self.fallback)(var, VariableKind::Const(ty), default, outer_binder) .assert_const_ref(Interner) .clone() - }; - Ok(result) + } } fn fold_inference_lifetime( &mut self, _var: InferenceVar, _outer_binder: DebruijnIndex, - ) -> Fallible { + ) -> Lifetime { // fall back all lifetimes to 'static -- currently we don't deal // with any lifetimes, but we can sometimes get some lifetime // variables through Chalk's unification, and this at least makes // sure we don't leak them outside of inference - Ok(crate::static_lifetime()) + crate::static_lifetime() } } } diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs index de4a5446e57..c4b700cbce6 100644 --- a/crates/hir-ty/src/lib.rs +++ b/crates/hir-ty/src/lib.rs @@ -254,13 +254,13 @@ impl CallableSig { } impl TypeFoldable for CallableSig { - fn fold_with( + fn try_fold_with( self, - folder: &mut dyn chalk_ir::fold::TypeFolder, + folder: &mut dyn chalk_ir::fold::FallibleTypeFolder, outer_binder: DebruijnIndex, ) -> Result { let vec = self.params_and_return.to_vec(); - let folded = vec.fold_with(folder, outer_binder)?; + let folded = vec.try_fold_with(folder, outer_binder)?; Ok(CallableSig { params_and_return: folded.into(), is_varargs: self.is_varargs }) } } @@ -292,16 +292,19 @@ pub(crate) fn fold_free_vars + TypeFoldable< for_ty: impl FnMut(BoundVar, DebruijnIndex) -> Ty, for_const: impl FnMut(Ty, BoundVar, DebruijnIndex) -> Const, ) -> T { - use chalk_ir::{fold::TypeFolder, Fallible}; - struct FreeVarFolder(F1, F2); + use chalk_ir::fold::TypeFolder; + + #[derive(chalk_derive::FallibleTypeFolder)] + #[has_interner(Interner)] + struct FreeVarFolder< + F1: FnMut(BoundVar, DebruijnIndex) -> Ty, + F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const, + >(F1, F2); impl< - 'i, - F1: FnMut(BoundVar, DebruijnIndex) -> Ty + 'i, - F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const + 'i, + F1: FnMut(BoundVar, DebruijnIndex) -> Ty, + F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const, > TypeFolder for FreeVarFolder { - type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } @@ -310,12 +313,8 @@ pub(crate) fn fold_free_vars + TypeFoldable< Interner } - fn fold_free_var_ty( - &mut self, - bound_var: BoundVar, - outer_binder: DebruijnIndex, - ) -> Fallible { - Ok(self.0(bound_var, outer_binder)) + fn fold_free_var_ty(&mut self, bound_var: BoundVar, outer_binder: DebruijnIndex) -> Ty { + self.0(bound_var, outer_binder) } fn fold_free_var_const( @@ -323,12 +322,11 @@ pub(crate) fn fold_free_vars + TypeFoldable< ty: Ty, bound_var: BoundVar, outer_binder: DebruijnIndex, - ) -> Fallible { - Ok(self.1(ty, bound_var, outer_binder)) + ) -> Const { + self.1(ty, bound_var, outer_binder) } } t.fold_with(&mut FreeVarFolder(for_ty, for_const), DebruijnIndex::INNERMOST) - .expect("fold failed unexpectedly") } pub(crate) fn fold_tys + TypeFoldable>( @@ -351,16 +349,13 @@ pub(crate) fn fold_tys_and_consts + TypeFold f: impl FnMut(Either, DebruijnIndex) -> Either, binders: DebruijnIndex, ) -> T { - use chalk_ir::{ - fold::{TypeFolder, TypeSuperFoldable}, - Fallible, - }; - struct TyFolder(F); - impl<'i, F: FnMut(Either, DebruijnIndex) -> Either + 'i> - TypeFolder for TyFolder + use chalk_ir::fold::{TypeFolder, TypeSuperFoldable}; + #[derive(chalk_derive::FallibleTypeFolder)] + #[has_interner(Interner)] + struct TyFolder, DebruijnIndex) -> Either>(F); + impl, DebruijnIndex) -> Either> TypeFolder + for TyFolder { - type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { self } @@ -369,16 +364,16 @@ pub(crate) fn fold_tys_and_consts + TypeFold Interner } - fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible { - let ty = ty.super_fold_with(self.as_dyn(), outer_binder)?; - Ok(self.0(Either::Left(ty), outer_binder).left().unwrap()) + fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Ty { + let ty = ty.super_fold_with(self.as_dyn(), outer_binder); + self.0(Either::Left(ty), outer_binder).left().unwrap() } - fn fold_const(&mut self, c: Const, outer_binder: DebruijnIndex) -> Fallible { - Ok(self.0(Either::Right(c), outer_binder).right().unwrap()) + fn fold_const(&mut self, c: Const, outer_binder: DebruijnIndex) -> Const { + self.0(Either::Right(c), outer_binder).right().unwrap() } } - t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly") + t.fold_with(&mut TyFolder(f), binders) } /// 'Canonicalizes' the `t` by replacing any errors with new variables. Also @@ -390,16 +385,16 @@ where T: HasInterner, { use chalk_ir::{ - fold::{TypeFolder, TypeSuperFoldable}, + fold::{FallibleTypeFolder, TypeSuperFoldable}, Fallible, }; struct ErrorReplacer { vars: usize, } - impl TypeFolder for ErrorReplacer { + impl FallibleTypeFolder for ErrorReplacer { type Error = NoSolution; - fn as_dyn(&mut self) -> &mut dyn TypeFolder { + fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder { self } @@ -407,18 +402,17 @@ where Interner } - fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible { + fn try_fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible { if let TyKind::Error = ty.kind(Interner) { let index = self.vars; self.vars += 1; Ok(TyKind::BoundVar(BoundVar::new(outer_binder, index)).intern(Interner)) } else { - let ty = ty.super_fold_with(self.as_dyn(), outer_binder)?; - Ok(ty) + ty.try_super_fold_with(self.as_dyn(), outer_binder) } } - fn fold_inference_ty( + fn try_fold_inference_ty( &mut self, _var: InferenceVar, _kind: TyVariableKind, @@ -433,7 +427,7 @@ where } } - fn fold_free_var_ty( + fn try_fold_free_var_ty( &mut self, _bound_var: BoundVar, _outer_binder: DebruijnIndex, @@ -447,7 +441,7 @@ where } } - fn fold_inference_const( + fn try_fold_inference_const( &mut self, ty: Ty, _var: InferenceVar, @@ -460,7 +454,7 @@ where } } - fn fold_free_var_const( + fn try_fold_free_var_const( &mut self, ty: Ty, _bound_var: BoundVar, @@ -473,7 +467,7 @@ where } } - fn fold_inference_lifetime( + fn try_fold_inference_lifetime( &mut self, _var: InferenceVar, _outer_binder: DebruijnIndex, @@ -485,7 +479,7 @@ where } } - fn fold_free_var_lifetime( + fn try_fold_free_var_lifetime( &mut self, _bound_var: BoundVar, _outer_binder: DebruijnIndex, @@ -498,7 +492,7 @@ where } } let mut error_replacer = ErrorReplacer { vars: 0 }; - let value = match t.clone().fold_with(&mut error_replacer, DebruijnIndex::INNERMOST) { + let value = match t.clone().try_fold_with(&mut error_replacer, DebruijnIndex::INNERMOST) { Ok(t) => t, Err(_) => panic!("Encountered unbound or inference vars in {:?}", t), }; diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs index 372c3a3cca6..c425f35acfe 100644 --- a/crates/hir-ty/src/traits.rs +++ b/crates/hir-ty/src/traits.rs @@ -13,8 +13,8 @@ use syntax::SmolStr; use crate::{ db::HirDatabase, infer::unify::InferenceTable, AliasEq, AliasTy, Canonical, DomainGoal, Goal, - Guidance, InEnvironment, Interner, ProjectionTy, Solution, TraitRefExt, Ty, TyKind, - WhereClause, + Guidance, InEnvironment, Interner, ProjectionTy, ProjectionTyExt, Solution, TraitRefExt, Ty, + TyKind, WhereClause, }; /// This controls how much 'time' we give the Chalk solver before giving up. @@ -95,7 +95,7 @@ pub(crate) fn trait_solve_query( .. }))) = &goal.value.goal.data(Interner) { - if let TyKind::BoundVar(_) = projection_ty.self_type_parameter(Interner).kind(Interner) { + if let TyKind::BoundVar(_) = projection_ty.self_type_parameter(db).kind(Interner) { // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible return Some(Solution::Ambig(Guidance::Unknown)); }