fix: use BoundVars from current generic scope

This commit is contained in:
Ryo Yoshida 2022-10-05 00:20:01 +09:00
parent e0a161b2e3
commit ded3326a64
No known key found for this signature in database
GPG key ID: E25698A930586171
2 changed files with 33 additions and 3 deletions

View file

@ -1158,11 +1158,28 @@ fn named_associated_type_shorthand_candidates<R>(
};
match res {
TypeNs::SelfType(impl_id) => search(
TypeNs::SelfType(impl_id) => {
// we're _in_ the impl -- the binders get added back later. Correct,
// but it would be nice to make this more explicit
db.impl_trait(impl_id)?.into_value_and_skipped_binders().0,
),
let trait_ref = db.impl_trait(impl_id)?.into_value_and_skipped_binders().0;
let impl_id_as_generic_def: GenericDefId = impl_id.into();
if impl_id_as_generic_def != def {
// `trait_ref` contains `BoundVar`s bound by impl's `Binders`, but here we need
// `BoundVar`s from `def`'s point of view.
// FIXME: A `HirDatabase` query may be handy if this process is needed in more
// places. It'd be almost identical as `impl_trait_query` where `resolver` would be
// of `def` instead of `impl_id`.
let starting_idx = generics(db.upcast(), def).len_self();
let subst = TyBuilder::subst_for_def(db, impl_id, None)
.fill_with_bound_vars(DebruijnIndex::INNERMOST, starting_idx)
.build();
let trait_ref = subst.apply(trait_ref, Interner);
search(trait_ref)
} else {
search(trait_ref)
}
}
TypeNs::GenericParam(param_id) => {
let predicates = db.generic_predicates_for_param(def, param_id.into(), assoc_name);
let res = predicates.iter().find_map(|pred| match pred.skip_binders().skip_binders() {

View file

@ -1694,3 +1694,16 @@ fn foo(a: &dyn DoesNotExist) {
"#,
);
}
#[test]
fn self_assoc_with_const_generics_crash() {
check_no_mismatches(
r#"
trait Trait { type Item; }
impl<T, const N: usize> Trait for [T; N] {
type Item = ();
fn f<U>(_: Self::Item) {}
}
"#,
);
}