From 78dd5482438b1ba13b4aa2eaa9a7c443a3342ce4 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 20 Nov 2020 18:00:34 +0100 Subject: Upgrade Chalk Also make overflow depth and max type size configurable through env variables. This can be helpful at least for debugging. Fixes #6628. --- crates/hir_ty/src/traits/chalk.rs | 49 ++++++++++++++++++++++++++++-- crates/hir_ty/src/traits/chalk/interner.rs | 16 ++++++++++ crates/hir_ty/src/traits/chalk/mapping.rs | 13 ++++++-- 3 files changed, 72 insertions(+), 6 deletions(-) (limited to 'crates/hir_ty/src/traits') diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 55e2c3a3e..69eae6f79 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs @@ -104,7 +104,7 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { }; // Note: Since we're using impls_for_trait, only impls where the trait - // can be resolved should ever reach Chalk. `impl_datum` relies on that + // can be resolved should ever reach Chalk. Symbol’s value as variable is void: impl_datum relies on that // and will panic if the trait can't be resolved. let in_deps = self.db.trait_impls_in_deps(self.krate); let in_self = self.db.trait_impls_in_crate(self.krate); @@ -206,7 +206,7 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { Some((trait_, alias)) }) { - // Making up `AsyncBlock: Future` + // Making up Symbol’s value as variable is void: AsyncBlock: // // |--------------------OpaqueTyDatum-------------------| // |-------------OpaqueTyDatumBound--------------| @@ -242,7 +242,7 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { // The opaque type has 1 parameter. make_binders(bound, 1) } else { - // If failed to find `Future::Output`, return empty bounds as fallback. + // If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback. let bound = OpaqueTyDatumBound { bounds: make_binders(vec![], 0), where_clauses: make_binders(vec![], 0), @@ -343,6 +343,23 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { // FIXME unimplemented!() } + + fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase { + self + } +} + +impl<'a> chalk_ir::UnificationDatabase for ChalkContext<'a> { + fn fn_def_variance( + &self, + fn_def_id: chalk_ir::FnDefId, + ) -> chalk_ir::Variances { + self.db.fn_def_variance(self.krate, fn_def_id) + } + + fn adt_variance(&self, adt_id: chalk_ir::AdtId) -> chalk_ir::Variances { + self.db.adt_variance(self.krate, adt_id) + } } pub(crate) fn program_clauses_for_chalk_env_query( @@ -644,6 +661,32 @@ pub(crate) fn fn_def_datum_query( Arc::new(datum) } +pub(crate) fn fn_def_variance_query( + db: &dyn HirDatabase, + _krate: CrateId, + fn_def_id: FnDefId, +) -> Variances { + let callable_def: CallableDefId = from_chalk(db, fn_def_id); + let generic_params = generics(db.upcast(), callable_def.into()); + Variances::from( + &Interner, + std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()), + ) +} + +pub(crate) fn adt_variance_query( + db: &dyn HirDatabase, + _krate: CrateId, + adt_id: AdtId, +) -> Variances { + let adt: crate::AdtId = from_chalk(db, adt_id); + let generic_params = generics(db.upcast(), adt.into()); + Variances::from( + &Interner, + std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()), + ) +} + impl From for crate::db::InternedCallableDefId { fn from(fn_def_id: FnDefId) -> Self { InternKey::from_intern_id(fn_def_id.0) diff --git a/crates/hir_ty/src/traits/chalk/interner.rs b/crates/hir_ty/src/traits/chalk/interner.rs index 39569e690..6a4aa8333 100644 --- a/crates/hir_ty/src/traits/chalk/interner.rs +++ b/crates/hir_ty/src/traits/chalk/interner.rs @@ -25,6 +25,7 @@ pub(crate) type FnDefId = chalk_ir::FnDefId; pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum; pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId; pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum; +pub(crate) type Variances = chalk_ir::Variances; impl chalk_ir::interner::Interner for Interner { type InternedType = Arc>; @@ -41,6 +42,7 @@ impl chalk_ir::interner::Interner for Interner { type InternedVariableKinds = Vec>; type InternedCanonicalVarKinds = Vec>; type InternedConstraints = Vec>>; + type InternedVariances = Arc<[chalk_ir::Variance]>; type DefId = InternId; type InternedAdtId = hir_def::AdtId; type Identifier = TypeAliasId; @@ -370,6 +372,20 @@ impl chalk_ir::interner::Interner for Interner { ) -> Option { None } + + fn intern_variances( + &self, + data: impl IntoIterator>, + ) -> Result { + data.into_iter().collect() + } + + fn variances_data<'a>( + &self, + variances: &'a Self::InternedVariances, + ) -> &'a [chalk_ir::Variance] { + &variances + } } impl chalk_ir::interner::HasInterner for Interner { diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 86cbc4c7e..8700d664e 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs @@ -31,7 +31,8 @@ impl ToChalk for Ty { TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters), TypeCtor::Array => array_to_chalk(db, apply_ty.parameters), TypeCtor::FnPtr { num_args: _, is_varargs } => { - let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner); + let substitution = + chalk_ir::FnSubst(apply_ty.parameters.to_chalk(db).shifted_in(&Interner)); chalk_ir::TyKind::Function(chalk_ir::FnPointer { num_binders: 0, sig: chalk_ir::FnSig { @@ -183,7 +184,7 @@ impl ToChalk for Ty { assert_eq!(num_binders, 0); let parameters: Substs = from_chalk( db, - substitution.shifted_out(&Interner).expect("fn ptr should have no binders"), + substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"), ); Ty::Apply(ApplicationTy { ctor: TypeCtor::FnPtr { @@ -536,6 +537,7 @@ impl ToChalk for GenericPredicate { // we don't produce any where clauses with binders and can't currently deal with them match where_clause .skip_binders() + .clone() .shifted_out(&Interner) .expect("unexpected bound vars in where clause") { @@ -661,7 +663,12 @@ where chalk_ir::TyVariableKind::Integer => TyKind::Integer, chalk_ir::TyVariableKind::Float => TyKind::Float, }, - chalk_ir::VariableKind::Lifetime => panic!("unexpected lifetime from Chalk"), + // HACK: Chalk can sometimes return new lifetime variables. We + // want to just skip them, but to not mess up the indices of + // other variables, we'll just create a new type variable in + // their place instead. This should not matter (we never see the + // actual *uses* of the lifetime variable). + chalk_ir::VariableKind::Lifetime => TyKind::General, chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"), }) .collect(); -- cgit v1.2.3