Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-ty/src/lower.rs23
-rw-r--r--crates/hir-ty/src/tests/regression.rs13
2 files changed, 33 insertions, 3 deletions
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index a77dd910ff..223d705b15 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -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() {
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 16ba3dd6e3..a155adcec6 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -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) {}
+}
+ "#,
+ );
+}