diff options
-rw-r--r-- | crates/ra_hir_ty/src/infer/path.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/regression.rs | 60 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/utils.rs | 14 |
4 files changed, 80 insertions, 18 deletions
diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 1ad0d8397..80d7ed10e 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs | |||
@@ -81,7 +81,7 @@ impl<'a> InferenceContext<'a> { | |||
81 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); | 81 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); |
82 | let substs = Substs::type_params_for_generics(&generics); | 82 | let substs = Substs::type_params_for_generics(&generics); |
83 | let ty = self.db.impl_self_ty(impl_id).subst(&substs); | 83 | let ty = self.db.impl_self_ty(impl_id).subst(&substs); |
84 | if let Some((AdtId::StructId(struct_id), _)) = ty.as_adt() { | 84 | if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() { |
85 | let ty = self.db.value_ty(struct_id.into()).subst(&substs); | 85 | let ty = self.db.value_ty(struct_id.into()).subst(&substs); |
86 | return Some(ty); | 86 | return Some(ty); |
87 | } else { | 87 | } else { |
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 1f004bd63..8dc5603b7 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs | |||
@@ -633,3 +633,63 @@ where | |||
633 | "### | 633 | "### |
634 | ); | 634 | ); |
635 | } | 635 | } |
636 | |||
637 | #[test] | ||
638 | fn issue_4953() { | ||
639 | assert_snapshot!( | ||
640 | infer(r#" | ||
641 | pub struct Foo(pub i64); | ||
642 | impl Foo { | ||
643 | fn test() -> Self { Self(0i64) } | ||
644 | } | ||
645 | "#), | ||
646 | @r###" | ||
647 | 59..73 '{ Self(0i64) }': Foo | ||
648 | 61..65 'Self': Foo(i64) -> Foo | ||
649 | 61..71 'Self(0i64)': Foo | ||
650 | 66..70 '0i64': i64 | ||
651 | "### | ||
652 | ); | ||
653 | assert_snapshot!( | ||
654 | infer(r#" | ||
655 | pub struct Foo<T>(pub T); | ||
656 | impl Foo<i64> { | ||
657 | fn test() -> Self { Self(0i64) } | ||
658 | } | ||
659 | "#), | ||
660 | @r###" | ||
661 | 65..79 '{ Self(0i64) }': Foo<i64> | ||
662 | 67..71 'Self': Foo<i64>(i64) -> Foo<i64> | ||
663 | 67..77 'Self(0i64)': Foo<i64> | ||
664 | 72..76 '0i64': i64 | ||
665 | "### | ||
666 | ); | ||
667 | } | ||
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 | } | ||
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 | ||
145 | pub(super) fn associated_type_by_name_including_super_traits( | 145 | pub(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 | ||
155 | pub(super) fn variant_data(db: &dyn DefDatabase, var: VariantId) -> Arc<VariantData> { | 156 | 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 { | |||
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)] | ||
179 | pub(crate) struct Generics { | 181 | pub(crate) struct Generics { |
180 | def: GenericDefId, | 182 | def: GenericDefId, |
181 | pub(crate) params: Arc<GenericParams>, | 183 | pub(crate) params: Arc<GenericParams>, |