From b4c20e3589372ba1536cec1bfe7de6acd2f40a4d Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Wed, 24 Mar 2021 23:07:54 +0100 Subject: Fix chalk_ir assertion Fixes #8150. --- crates/hir_ty/src/lib.rs | 33 ++++++++++++++++++++++++++------- crates/hir_ty/src/lower.rs | 11 +++++++---- crates/hir_ty/src/traits/chalk.rs | 8 +++----- crates/hir_ty/src/utils.rs | 8 ++++++-- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 0f49dd39b..69265286f 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs @@ -538,12 +538,6 @@ impl Binders { assert_eq!(subst.len(), self.num_binders); self.value.subst_bound_vars(subst) } - - /// Substitutes just a prefix of the variables (shifting the rest). - pub fn subst_prefix(self, subst: &Substitution) -> Binders { - assert!(subst.len() < self.num_binders); - Binders::new(self.num_binders - subst.len(), self.value.subst_bound_vars(subst)) - } } impl TypeWalk for Binders { @@ -698,7 +692,15 @@ impl CallableSig { pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { CallableSig { - params_and_return: fn_ptr.substs.interned(&Interner).iter().cloned().collect(), + // FIXME: what to do about lifetime params? + params_and_return: fn_ptr + .substs + .clone() + .shift_bound_vars_out(DebruijnIndex::ONE) + .interned(&Interner) + .iter() + .cloned() + .collect(), is_varargs: fn_ptr.sig.variadic, } } @@ -1131,6 +1133,23 @@ pub trait TypeWalk { DebruijnIndex::INNERMOST, ) } + + /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`. + fn shift_bound_vars_out(self, n: DebruijnIndex) -> Self + where + Self: Sized + std::fmt::Debug, + { + self.fold_binders( + &mut |ty, binders| match ty.interned(&Interner) { + TyKind::BoundVar(bound) if bound.debruijn >= binders => { + TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone())) + .intern(&Interner) + } + _ => ty, + }, + DebruijnIndex::INNERMOST, + ) + } } impl TypeWalk for Ty { diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 3153b5b74..c87789d45 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -828,14 +828,18 @@ pub fn associated_type_shorthand_candidates( let traits_from_env: Vec<_> = match res { TypeNs::SelfType(impl_id) => match db.impl_trait(impl_id) { None => vec![], - Some(trait_ref) => vec![trait_ref.value], + // FIXME: how to correctly handle higher-ranked bounds here? + Some(trait_ref) => vec![trait_ref.value.shift_bound_vars_out(DebruijnIndex::ONE)], }, TypeNs::GenericParam(param_id) => { let predicates = db.generic_predicates_for_param(param_id); let mut traits_: Vec<_> = predicates .iter() .filter_map(|pred| match &pred.value.value { - WhereClause::Implemented(tr) => Some(tr.clone()), + // FIXME: how to correctly handle higher-ranked bounds here? + WhereClause::Implemented(tr) => { + Some(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE)) + } _ => None, }) .collect(); @@ -1156,10 +1160,9 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders { if db.type_alias_data(t).is_extern { Binders::new(0, TyKind::ForeignType(crate::to_foreign_def_id(t)).intern(&Interner)) } else { - let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); let type_ref = &db.type_alias_data(t).type_ref; let inner = ctx.lower_ty(type_ref.as_ref().unwrap_or(&TypeRef::Error)); - Binders::new(substs.len(), inner) + Binders::new(generics.len(), inner) } } diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 4019fdf17..011bef6f6 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs @@ -21,8 +21,8 @@ use crate::{ method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, to_assoc_type_id, to_chalk_trait_id, utils::generics, - AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, ProjectionTy, - Substitution, TraitRef, Ty, TyKind, WhereClause, + AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution, + TraitRef, Ty, TyKind, WhereClause, }; use mapping::{ convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue, @@ -288,9 +288,7 @@ impl<'a> chalk_solve::RustIrDatabase for ChalkContext<'a> { ) -> chalk_ir::Binders> { let sig_ty: Ty = from_chalk(self.db, substs.at(&Interner, 0).assert_ty_ref(&Interner).clone()); - let sig = CallableSig::from_substs( - &sig_ty.substs().expect("first closure param should be fn ptr"), - ); + let sig = &sig_ty.callable_sig(self.db).expect("first closure param should be fn ptr"); let io = rust_ir::FnDefInputsAndOutputDatum { argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(self.db)).collect(), return_type: sig.ret().clone().to_chalk(self.db), diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs index 19874e42b..42d7af146 100644 --- a/crates/hir_ty/src/utils.rs +++ b/crates/hir_ty/src/utils.rs @@ -2,6 +2,7 @@ //! query, but can't be computed directly from `*Data` (ie, which need a `db`). use std::sync::Arc; +use chalk_ir::DebruijnIndex; use hir_def::{ adt::VariantData, db::DefDatabase, @@ -15,7 +16,7 @@ use hir_def::{ }; use hir_expand::name::{name, Name}; -use crate::{db::HirDatabase, TraitRef, WhereClause}; +use crate::{db::HirDatabase, TraitRef, TypeWalk, WhereClause}; fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec { let resolver = trait_.resolver(db); @@ -64,7 +65,10 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec Some(tr.clone()), + // FIXME: how to correctly handle higher-ranked bounds here? + WhereClause::Implemented(tr) => { + Some(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE)) + } _ => None, }) }) -- cgit v1.2.3