aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r--crates/ra_hir_ty/src/lower.rs28
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs47
2 files changed, 69 insertions, 6 deletions
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index 6c7bbc448..21e7baf8b 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -8,6 +8,8 @@
8use std::iter; 8use std::iter;
9use std::sync::Arc; 9use std::sync::Arc;
10 10
11use smallvec::SmallVec;
12
11use hir_def::{ 13use hir_def::{
12 adt::StructKind, 14 adt::StructKind,
13 builtin_type::BuiltinType, 15 builtin_type::BuiltinType,
@@ -596,21 +598,35 @@ fn assoc_type_bindings_from_type_bound<'a>(
596 .into_iter() 598 .into_iter()
597 .flat_map(|segment| segment.args_and_bindings.into_iter()) 599 .flat_map(|segment| segment.args_and_bindings.into_iter())
598 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) 600 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
599 .map(move |(name, type_ref)| { 601 .flat_map(move |binding| {
600 let associated_ty = associated_type_by_name_including_super_traits( 602 let associated_ty = associated_type_by_name_including_super_traits(
601 ctx.db.upcast(), 603 ctx.db.upcast(),
602 trait_ref.trait_, 604 trait_ref.trait_,
603 &name, 605 &binding.name,
604 ); 606 );
605 let associated_ty = match associated_ty { 607 let associated_ty = match associated_ty {
606 None => return GenericPredicate::Error, 608 None => return SmallVec::<[GenericPredicate; 1]>::new(),
607 Some(t) => t, 609 Some(t) => t,
608 }; 610 };
609 let projection_ty = 611 let projection_ty =
610 ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; 612 ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() };
611 let ty = Ty::from_hir(ctx, type_ref); 613 let mut preds = SmallVec::with_capacity(
612 let projection_predicate = ProjectionPredicate { projection_ty, ty }; 614 binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
613 GenericPredicate::Projection(projection_predicate) 615 );
616 if let Some(type_ref) = &binding.type_ref {
617 let ty = Ty::from_hir(ctx, type_ref);
618 let projection_predicate =
619 ProjectionPredicate { projection_ty: projection_ty.clone(), ty };
620 preds.push(GenericPredicate::Projection(projection_predicate));
621 }
622 for bound in &binding.bounds {
623 preds.extend(GenericPredicate::from_type_bound(
624 ctx,
625 bound,
626 Ty::Projection(projection_ty.clone()),
627 ));
628 }
629 preds
614 }) 630 })
615} 631}
616 632
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 22ae6ca90..53461bdbb 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -1924,6 +1924,53 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> {
1924} 1924}
1925 1925
1926#[test] 1926#[test]
1927fn inline_assoc_type_bounds_1() {
1928 let t = type_at(
1929 r#"
1930//- /main.rs
1931trait Iterator {
1932 type Item;
1933}
1934trait OtherTrait<T> {
1935 fn foo(&self) -> T;
1936}
1937
1938// workaround for Chalk assoc type normalization problems
1939pub struct S<T>;
1940impl<T: Iterator> Iterator for S<T> {
1941 type Item = <T as Iterator>::Item;
1942}
1943
1944fn test<I: Iterator<Item: OtherTrait<u32>>>() {
1945 let x: <S<I> as Iterator>::Item;
1946 x.foo()<|>;
1947}
1948"#,
1949 );
1950 assert_eq!(t, "u32");
1951}
1952
1953#[test]
1954fn inline_assoc_type_bounds_2() {
1955 let t = type_at(
1956 r#"
1957//- /main.rs
1958trait Iterator {
1959 type Item;
1960}
1961
1962fn test<I: Iterator<Item: Iterator<Item = u32>>>() {
1963 let x: <<I as Iterator>::Item as Iterator>::Item;
1964 x<|>;
1965}
1966"#,
1967 );
1968 // assert_eq!(t, "u32");
1969 // doesn't currently work, Chalk #234
1970 assert_eq!(t, "{unknown}");
1971}
1972
1973#[test]
1927fn unify_impl_trait() { 1974fn unify_impl_trait() {
1928 assert_snapshot!( 1975 assert_snapshot!(
1929 infer_with_mismatches(r#" 1976 infer_with_mismatches(r#"