aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-06-19 15:29:38 +0100
committerFlorian Diebold <[email protected]>2020-06-19 20:46:47 +0100
commit2745cb37c16600c99083cefdf5eb45a5205dd86d (patch)
tree518fe5b3895e021e1d35e90d6e7d71abfc36692a /crates/ra_hir_ty
parent6654055308515cb330f23942f347de5605f69be1 (diff)
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.
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r--crates/ra_hir_ty/src/lower.rs22
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs28
-rw-r--r--crates/ra_hir_ty/src/utils.rs14
3 files changed, 47 insertions, 17 deletions
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 {
337 TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty); 337 TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty);
338 let ty = if remaining_segments.len() == 1 { 338 let ty = if remaining_segments.len() == 1 {
339 let segment = remaining_segments.first().unwrap(); 339 let segment = remaining_segments.first().unwrap();
340 let associated_ty = associated_type_by_name_including_super_traits( 340 let found = associated_type_by_name_including_super_traits(
341 ctx.db.upcast(), 341 ctx.db,
342 trait_ref.trait_, 342 trait_ref.clone(),
343 &segment.name, 343 &segment.name,
344 ); 344 );
345 match associated_ty { 345 match found {
346 Some(associated_ty) => { 346 Some((super_trait_ref, associated_ty)) => {
347 // FIXME handle type parameters on the segment 347 // FIXME handle type parameters on the segment
348 Ty::Projection(ProjectionTy { 348 Ty::Projection(ProjectionTy {
349 associated_ty, 349 associated_ty,
350 parameters: trait_ref.substs, 350 parameters: super_trait_ref.substs,
351 }) 351 })
352 } 352 }
353 None => { 353 None => {
@@ -706,17 +706,17 @@ fn assoc_type_bindings_from_type_bound<'a>(
706 .flat_map(|segment| segment.args_and_bindings.into_iter()) 706 .flat_map(|segment| segment.args_and_bindings.into_iter())
707 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) 707 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
708 .flat_map(move |binding| { 708 .flat_map(move |binding| {
709 let associated_ty = associated_type_by_name_including_super_traits( 709 let found = associated_type_by_name_including_super_traits(
710 ctx.db.upcast(), 710 ctx.db,
711 trait_ref.trait_, 711 trait_ref.clone(),
712 &binding.name, 712 &binding.name,
713 ); 713 );
714 let associated_ty = match associated_ty { 714 let (super_trait_ref, associated_ty) = match found {
715 None => return SmallVec::<[GenericPredicate; 1]>::new(), 715 None => return SmallVec::<[GenericPredicate; 1]>::new(),
716 Some(t) => t, 716 Some(t) => t,
717 }; 717 };
718 let projection_ty = 718 let projection_ty =
719 ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; 719 ProjectionTy { associated_ty, parameters: super_trait_ref.substs.clone() };
720 let mut preds = SmallVec::with_capacity( 720 let mut preds = SmallVec::with_capacity(
721 binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), 721 binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
722 ); 722 );
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<i64> {
665 "### 665 "###
666 ); 666 );
667} 667}
668
669#[test]
670fn issue_4931() {
671 assert_snapshot!(
672 infer(r#"
673trait Div<T> {
674 type Output;
675}
676
677trait CheckedDiv: Div<()> {}
678
679trait PrimInt: CheckedDiv<Output = ()> {
680 fn pow(self);
681}
682
683fn 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}
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(
143} 143}
144 144
145pub(super) fn associated_type_by_name_including_super_traits( 145pub(super) fn associated_type_by_name_including_super_traits(
146 db: &dyn DefDatabase, 146 db: &dyn HirDatabase,
147 trait_: TraitId, 147 trait_ref: TraitRef,
148 name: &Name, 148 name: &Name,
149) -> Option<TypeAliasId> { 149) -> Option<(TraitRef, TypeAliasId)> {
150 all_super_traits(db, trait_) 150 all_super_trait_refs(db, trait_ref).into_iter().find_map(|t| {
151 .into_iter() 151 let assoc_type = db.trait_data(t.trait_).associated_type_by_name(name)?;
152 .find_map(|t| db.trait_data(t).associated_type_by_name(name)) 152 Some((t, assoc_type))
153 })
153} 154}
154 155
155pub(super) fn variant_data(db: &dyn DefDatabase, var: VariantId) -> Arc<VariantData> { 156pub(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 {
176 Generics { def, params: db.generic_params(def), parent_generics } 177 Generics { def, params: db.generic_params(def), parent_generics }
177} 178}
178 179
180#[derive(Debug)]
179pub(crate) struct Generics { 181pub(crate) struct Generics {
180 def: GenericDefId, 182 def: GenericDefId,
181 pub(crate) params: Arc<GenericParams>, 183 pub(crate) params: Arc<GenericParams>,