aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-08-25 12:57:03 +0100
committerFlorian Diebold <[email protected]>2019-09-03 13:00:35 +0100
commitc4fcfa2b0d516b9790fa8abdf96bb2308657d60a (patch)
tree94ae979da298244b9a057b6eacf58875101535b0 /crates/ra_hir/src
parent741e350d4b7c3561f242207541ac9d7cab6ce45f (diff)
Properly format `impl Trait<Type = Foo>` types
It's a bit complicated because we basically have to 'undo' the desugaring, and the result is very dependent on the specifics of the desugaring and will probably produce weird results otherwise.
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/ty.rs112
-rw-r--r--crates/ra_hir/src/ty/tests.rs8
2 files changed, 97 insertions, 23 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 035491bff..c0c609d78 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -121,6 +121,16 @@ pub struct ProjectionTy {
121} 121}
122 122
123impl ProjectionTy { 123impl ProjectionTy {
124 pub fn trait_ref(&self, db: &impl HirDatabase) -> TraitRef {
125 TraitRef {
126 trait_: self
127 .associated_ty
128 .parent_trait(db)
129 .expect("projection ty without parent trait"),
130 substs: self.parameters.clone(),
131 }
132 }
133
124 pub fn walk(&self, f: &mut impl FnMut(&Ty)) { 134 pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
125 self.parameters.walk(f); 135 self.parameters.walk(f);
126 } 136 }
@@ -341,6 +351,21 @@ impl GenericPredicate {
341 } 351 }
342 } 352 }
343 353
354 pub fn is_implemented(&self) -> bool {
355 match self {
356 GenericPredicate::Implemented(_) => true,
357 _ => false,
358 }
359 }
360
361 pub fn trait_ref(&self, db: &impl HirDatabase) -> Option<TraitRef> {
362 match self {
363 GenericPredicate::Implemented(tr) => Some(tr.clone()),
364 GenericPredicate::Projection(proj) => Some(proj.projection_ty.trait_ref(db)),
365 GenericPredicate::Error => None,
366 }
367 }
368
344 pub fn subst(self, substs: &Substs) -> GenericPredicate { 369 pub fn subst(self, substs: &Substs) -> GenericPredicate {
345 match self { 370 match self {
346 GenericPredicate::Implemented(trait_ref) => { 371 GenericPredicate::Implemented(trait_ref) => {
@@ -769,23 +794,66 @@ impl HirDisplay for Ty {
769 Ty::Opaque(_) => write!(f, "impl ")?, 794 Ty::Opaque(_) => write!(f, "impl ")?,
770 _ => unreachable!(), 795 _ => unreachable!(),
771 }; 796 };
772 // looping by hand here just to format the bounds in a slightly nicer way 797 // Note: This code is written to produce nice results (i.e.
798 // corresponding to surface Rust) for types that can occur in
799 // actual Rust. It will have weird results if the predicates
800 // aren't as expected (i.e. self types = $0, projection
801 // predicates for a certain trait come after the Implemented
802 // predicate for that trait).
773 let mut first = true; 803 let mut first = true;
804 let mut angle_open = false;
774 for p in predicates.iter() { 805 for p in predicates.iter() {
775 if !first {
776 write!(f, " + ")?;
777 }
778 first = false;
779 match p { 806 match p {
780 // don't show the $0 self type
781 GenericPredicate::Implemented(trait_ref) => { 807 GenericPredicate::Implemented(trait_ref) => {
782 trait_ref.hir_fmt_ext(f, false)? 808 if angle_open {
809 write!(f, ">")?;
810 }
811 if !first {
812 write!(f, " + ")?;
813 }
814 // We assume that the self type is $0 (i.e. the
815 // existential) here, which is the only thing that's
816 // possible in actual Rust, and hence don't print it
817 write!(
818 f,
819 "{}",
820 trait_ref.trait_.name(f.db).unwrap_or_else(Name::missing)
821 )?;
822 if trait_ref.substs.len() > 1 {
823 write!(f, "<")?;
824 f.write_joined(&trait_ref.substs[1..], ", ")?;
825 // there might be assoc type bindings, so we leave the angle brackets open
826 angle_open = true;
827 }
783 } 828 }
784 GenericPredicate::Projection(_projection_pred) => { 829 GenericPredicate::Projection(projection_pred) => {
785 // TODO show something 830 // in types in actual Rust, these will always come
831 // after the corresponding Implemented predicate
832 if angle_open {
833 write!(f, ", ")?;
834 } else {
835 write!(f, "<")?;
836 angle_open = true;
837 }
838 let name = projection_pred.projection_ty.associated_ty.name(f.db);
839 write!(f, "{} = ", name)?;
840 projection_pred.ty.hir_fmt(f)?;
841 }
842 GenericPredicate::Error => {
843 if angle_open {
844 // impl Trait<X, {error}>
845 write!(f, ", ")?;
846 } else if !first {
847 // impl Trait + {error}
848 write!(f, " + ")?;
849 }
850 p.hir_fmt(f)?;
786 } 851 }
787 GenericPredicate::Error => p.hir_fmt(f)?,
788 } 852 }
853 first = false;
854 }
855 if angle_open {
856 write!(f, ">")?;
789 } 857 }
790 } 858 }
791 Ty::Unknown => write!(f, "{{unknown}}")?, 859 Ty::Unknown => write!(f, "{{unknown}}")?,
@@ -796,13 +864,12 @@ impl HirDisplay for Ty {
796} 864}
797 865
798impl TraitRef { 866impl TraitRef {
799 fn hir_fmt_ext( 867 fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result {
800 &self, 868 self.substs[0].hir_fmt(f)?;
801 f: &mut HirFormatter<impl HirDatabase>, 869 if use_as {
802 with_self_ty: bool, 870 write!(f, " as ")?;
803 ) -> fmt::Result { 871 } else {
804 if with_self_ty { 872 write!(f, ": ")?;
805 write!(f, "{}: ", self.substs[0].display(f.db),)?;
806 } 873 }
807 write!(f, "{}", self.trait_.name(f.db).unwrap_or_else(Name::missing))?; 874 write!(f, "{}", self.trait_.name(f.db).unwrap_or_else(Name::missing))?;
808 if self.substs.len() > 1 { 875 if self.substs.len() > 1 {
@@ -816,7 +883,7 @@ impl TraitRef {
816 883
817impl HirDisplay for TraitRef { 884impl HirDisplay for TraitRef {
818 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 885 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
819 self.hir_fmt_ext(f, true) 886 self.hir_fmt_ext(f, false)
820 } 887 }
821} 888}
822 889
@@ -831,7 +898,14 @@ impl HirDisplay for GenericPredicate {
831 match self { 898 match self {
832 GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, 899 GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
833 GenericPredicate::Projection(projection_pred) => { 900 GenericPredicate::Projection(projection_pred) => {
834 // TODO print something 901 write!(f, "<")?;
902 projection_pred.projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?;
903 write!(
904 f,
905 ">::{} = {}",
906 projection_pred.projection_ty.associated_ty.name(f.db),
907 projection_pred.ty.display(f.db)
908 )?;
835 } 909 }
836 GenericPredicate::Error => write!(f, "{{error}}")?, 910 GenericPredicate::Error => write!(f, "{{error}}")?,
837 } 911 }
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 3e743ef58..d92d4659b 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -3586,7 +3586,7 @@ fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
3586 [166; 169) '{t}': T 3586 [166; 169) '{t}': T
3587 [167; 168) 't': T 3587 [167; 168) 't': T
3588 [257; 258) 'x': T 3588 [257; 258) 'x': T
3589 [263; 264) 'y': impl Trait + 3589 [263; 264) 'y': impl Trait<Type = i64>
3590 [290; 398) '{ ...r>); }': () 3590 [290; 398) '{ ...r>); }': ()
3591 [296; 299) 'get': fn get<T>(T) -> <T as Trait>::Type 3591 [296; 299) 'get': fn get<T>(T) -> <T as Trait>::Type
3592 [296; 302) 'get(x)': {unknown} 3592 [296; 302) 'get(x)': {unknown}
@@ -3594,12 +3594,12 @@ fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
3594 [308; 312) 'get2': fn get2<{unknown}, S<{unknown}>>(T) -> U 3594 [308; 312) 'get2': fn get2<{unknown}, S<{unknown}>>(T) -> U
3595 [308; 315) 'get2(x)': {unknown} 3595 [308; 315) 'get2(x)': {unknown}
3596 [313; 314) 'x': T 3596 [313; 314) 'x': T
3597 [321; 324) 'get': fn get<impl Trait + >(T) -> <T as Trait>::Type 3597 [321; 324) 'get': fn get<impl Trait<Type = i64>>(T) -> <T as Trait>::Type
3598 [321; 327) 'get(y)': {unknown} 3598 [321; 327) 'get(y)': {unknown}
3599 [325; 326) 'y': impl Trait + 3599 [325; 326) 'y': impl Trait<Type = i64>
3600 [333; 337) 'get2': fn get2<{unknown}, S<{unknown}>>(T) -> U 3600 [333; 337) 'get2': fn get2<{unknown}, S<{unknown}>>(T) -> U
3601 [333; 340) 'get2(y)': {unknown} 3601 [333; 340) 'get2(y)': {unknown}
3602 [338; 339) 'y': impl Trait + 3602 [338; 339) 'y': impl Trait<Type = i64>
3603 [346; 349) 'get': fn get<S<u64>>(T) -> <T as Trait>::Type 3603 [346; 349) 'get': fn get<S<u64>>(T) -> <T as Trait>::Type
3604 [346; 357) 'get(set(S))': u64 3604 [346; 357) 'get(set(S))': u64
3605 [350; 353) 'set': fn set<S<u64>>(T) -> T 3605 [350; 353) 'set': fn set<S<u64>>(T) -> T