Skip to content

Commit 2745cb3

Browse files
committed
Use correct substs for super trait assoc types
When referring to an associated type of a super trait, we used the substs of the subtrait. That led to the #4931 crash if the subtrait had less parameters, but it could also lead to other incorrectness if just the order was different. Fixes #4931.
1 parent 6654055 commit 2745cb3

File tree

3 files changed

+47
-17
lines changed

3 files changed

+47
-17
lines changed

crates/ra_hir_ty/src/lower.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -337,17 +337,17 @@ impl Ty {
337337
TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty);
338338
let ty = if remaining_segments.len() == 1 {
339339
let segment = remaining_segments.first().unwrap();
340-
let associated_ty = associated_type_by_name_including_super_traits(
341-
ctx.db.upcast(),
342-
trait_ref.trait_,
340+
let found = associated_type_by_name_including_super_traits(
341+
ctx.db,
342+
trait_ref.clone(),
343343
&segment.name,
344344
);
345-
match associated_ty {
346-
Some(associated_ty) => {
345+
match found {
346+
Some((super_trait_ref, associated_ty)) => {
347347
// FIXME handle type parameters on the segment
348348
Ty::Projection(ProjectionTy {
349349
associated_ty,
350-
parameters: trait_ref.substs,
350+
parameters: super_trait_ref.substs,
351351
})
352352
}
353353
None => {
@@ -706,17 +706,17 @@ fn assoc_type_bindings_from_type_bound<'a>(
706706
.flat_map(|segment| segment.args_and_bindings.into_iter())
707707
.flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
708708
.flat_map(move |binding| {
709-
let associated_ty = associated_type_by_name_including_super_traits(
710-
ctx.db.upcast(),
711-
trait_ref.trait_,
709+
let found = associated_type_by_name_including_super_traits(
710+
ctx.db,
711+
trait_ref.clone(),
712712
&binding.name,
713713
);
714-
let associated_ty = match associated_ty {
714+
let (super_trait_ref, associated_ty) = match found {
715715
None => return SmallVec::<[GenericPredicate; 1]>::new(),
716716
Some(t) => t,
717717
};
718718
let projection_ty =
719-
ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() };
719+
ProjectionTy { associated_ty, parameters: super_trait_ref.substs.clone() };
720720
let mut preds = SmallVec::with_capacity(
721721
binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
722722
);

crates/ra_hir_ty/src/tests/regression.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,3 +665,31 @@ impl Foo<i64> {
665665
"###
666666
);
667667
}
668+
669+
#[test]
670+
fn issue_4931() {
671+
assert_snapshot!(
672+
infer(r#"
673+
trait Div<T> {
674+
type Output;
675+
}
676+
677+
trait CheckedDiv: Div<()> {}
678+
679+
trait PrimInt: CheckedDiv<Output = ()> {
680+
fn pow(self);
681+
}
682+
683+
fn check<T: PrimInt>(i: T) {
684+
i.pow();
685+
}
686+
"#),
687+
@r###"
688+
118..122 'self': Self
689+
149..150 'i': T
690+
155..171 '{ ...w(); }': ()
691+
161..162 'i': T
692+
161..168 'i.pow()': ()
693+
"###
694+
);
695+
}

crates/ra_hir_ty/src/utils.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,13 +143,14 @@ pub(super) fn find_super_trait_path(
143143
}
144144

145145
pub(super) fn associated_type_by_name_including_super_traits(
146-
db: &dyn DefDatabase,
147-
trait_: TraitId,
146+
db: &dyn HirDatabase,
147+
trait_ref: TraitRef,
148148
name: &Name,
149-
) -> Option<TypeAliasId> {
150-
all_super_traits(db, trait_)
151-
.into_iter()
152-
.find_map(|t| db.trait_data(t).associated_type_by_name(name))
149+
) -> Option<(TraitRef, TypeAliasId)> {
150+
all_super_trait_refs(db, trait_ref).into_iter().find_map(|t| {
151+
let assoc_type = db.trait_data(t.trait_).associated_type_by_name(name)?;
152+
Some((t, assoc_type))
153+
})
153154
}
154155

155156
pub(super) fn variant_data(db: &dyn DefDatabase, var: VariantId) -> Arc<VariantData> {
@@ -176,6 +177,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
176177
Generics { def, params: db.generic_params(def), parent_generics }
177178
}
178179

180+
#[derive(Debug)]
179181
pub(crate) struct Generics {
180182
def: GenericDefId,
181183
pub(crate) params: Arc<GenericParams>,

0 commit comments

Comments
 (0)