aboutsummaryrefslogtreecommitdiff
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
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.
-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