From 2745cb37c16600c99083cefdf5eb45a5205dd86d Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 19 Jun 2020 16:29:38 +0200 Subject: 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. --- crates/ra_hir_ty/src/lower.rs | 22 +++++++++++----------- crates/ra_hir_ty/src/tests/regression.rs | 28 ++++++++++++++++++++++++++++ crates/ra_hir_ty/src/utils.rs | 14 ++++++++------ 3 files changed, 47 insertions(+), 17 deletions(-) (limited to 'crates/ra_hir_ty/src') diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 42713928f..7a7fcb0ab 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -337,17 +337,17 @@ impl Ty { TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty); let ty = if remaining_segments.len() == 1 { let segment = remaining_segments.first().unwrap(); - let associated_ty = associated_type_by_name_including_super_traits( - ctx.db.upcast(), - trait_ref.trait_, + let found = associated_type_by_name_including_super_traits( + ctx.db, + trait_ref.clone(), &segment.name, ); - match associated_ty { - Some(associated_ty) => { + match found { + Some((super_trait_ref, associated_ty)) => { // FIXME handle type parameters on the segment Ty::Projection(ProjectionTy { associated_ty, - parameters: trait_ref.substs, + parameters: super_trait_ref.substs, }) } None => { @@ -706,17 +706,17 @@ fn assoc_type_bindings_from_type_bound<'a>( .flat_map(|segment| segment.args_and_bindings.into_iter()) .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) .flat_map(move |binding| { - let associated_ty = associated_type_by_name_including_super_traits( - ctx.db.upcast(), - trait_ref.trait_, + let found = associated_type_by_name_including_super_traits( + ctx.db, + trait_ref.clone(), &binding.name, ); - let associated_ty = match associated_ty { + let (super_trait_ref, associated_ty) = match found { None => return SmallVec::<[GenericPredicate; 1]>::new(), Some(t) => t, }; let projection_ty = - ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; + ProjectionTy { associated_ty, parameters: super_trait_ref.substs.clone() }; let mut preds = SmallVec::with_capacity( binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), ); diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs index ed43df484..8dc5603b7 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs @@ -665,3 +665,31 @@ impl Foo { "### ); } + +#[test] +fn issue_4931() { + assert_snapshot!( + infer(r#" +trait Div { + type Output; +} + +trait CheckedDiv: Div<()> {} + +trait PrimInt: CheckedDiv { + fn pow(self); +} + +fn check(i: T) { + i.pow(); +} +"#), + @r###" + 118..122 'self': Self + 149..150 'i': T + 155..171 '{ ...w(); }': () + 161..162 'i': T + 161..168 'i.pow()': () + "### + ); +} diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index f98350bf9..c45820ff0 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs @@ -143,13 +143,14 @@ pub(super) fn find_super_trait_path( } pub(super) fn associated_type_by_name_including_super_traits( - db: &dyn DefDatabase, - trait_: TraitId, + db: &dyn HirDatabase, + trait_ref: TraitRef, name: &Name, -) -> Option { - all_super_traits(db, trait_) - .into_iter() - .find_map(|t| db.trait_data(t).associated_type_by_name(name)) +) -> Option<(TraitRef, TypeAliasId)> { + all_super_trait_refs(db, trait_ref).into_iter().find_map(|t| { + let assoc_type = db.trait_data(t.trait_).associated_type_by_name(name)?; + Some((t, assoc_type)) + }) } pub(super) fn variant_data(db: &dyn DefDatabase, var: VariantId) -> Arc { @@ -176,6 +177,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { Generics { def, params: db.generic_params(def), parent_generics } } +#[derive(Debug)] pub(crate) struct Generics { def: GenericDefId, pub(crate) params: Arc, -- cgit v1.2.3