diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 348 |
1 files changed, 231 insertions, 117 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index b54c80318..a3df08827 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -120,12 +120,44 @@ pub struct ProjectionTy { | |||
120 | pub parameters: Substs, | 120 | pub parameters: Substs, |
121 | } | 121 | } |
122 | 122 | ||
123 | impl 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 | } | ||
134 | |||
135 | impl TypeWalk for ProjectionTy { | ||
136 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
137 | self.parameters.walk(f); | ||
138 | } | ||
139 | |||
140 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
141 | self.parameters.walk_mut(f); | ||
142 | } | ||
143 | } | ||
144 | |||
123 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 145 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
124 | pub struct UnselectedProjectionTy { | 146 | pub struct UnselectedProjectionTy { |
125 | pub type_name: Name, | 147 | pub type_name: Name, |
126 | pub parameters: Substs, | 148 | pub parameters: Substs, |
127 | } | 149 | } |
128 | 150 | ||
151 | impl TypeWalk for UnselectedProjectionTy { | ||
152 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
153 | self.parameters.walk(f); | ||
154 | } | ||
155 | |||
156 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
157 | self.parameters.walk_mut(f); | ||
158 | } | ||
159 | } | ||
160 | |||
129 | /// A type. | 161 | /// A type. |
130 | /// | 162 | /// |
131 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents | 163 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents |
@@ -282,20 +314,14 @@ impl TraitRef { | |||
282 | pub fn self_ty(&self) -> &Ty { | 314 | pub fn self_ty(&self) -> &Ty { |
283 | &self.substs[0] | 315 | &self.substs[0] |
284 | } | 316 | } |
317 | } | ||
285 | 318 | ||
286 | pub fn subst(mut self, substs: &Substs) -> TraitRef { | 319 | impl TypeWalk for TraitRef { |
287 | self.substs.walk_mut(&mut |ty_mut| { | 320 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
288 | let ty = mem::replace(ty_mut, Ty::Unknown); | ||
289 | *ty_mut = ty.subst(substs); | ||
290 | }); | ||
291 | self | ||
292 | } | ||
293 | |||
294 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
295 | self.substs.walk(f); | 321 | self.substs.walk(f); |
296 | } | 322 | } |
297 | 323 | ||
298 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 324 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
299 | self.substs.walk_mut(f); | 325 | self.substs.walk_mut(f); |
300 | } | 326 | } |
301 | } | 327 | } |
@@ -306,6 +332,8 @@ impl TraitRef { | |||
306 | pub enum GenericPredicate { | 332 | pub enum GenericPredicate { |
307 | /// The given trait needs to be implemented for its type parameters. | 333 | /// The given trait needs to be implemented for its type parameters. |
308 | Implemented(TraitRef), | 334 | Implemented(TraitRef), |
335 | /// An associated type bindings like in `Iterator<Item = T>`. | ||
336 | Projection(ProjectionPredicate), | ||
309 | /// We couldn't resolve the trait reference. (If some type parameters can't | 337 | /// We couldn't resolve the trait reference. (If some type parameters can't |
310 | /// be resolved, they will just be Unknown). | 338 | /// be resolved, they will just be Unknown). |
311 | Error, | 339 | Error, |
@@ -319,25 +347,35 @@ impl GenericPredicate { | |||
319 | } | 347 | } |
320 | } | 348 | } |
321 | 349 | ||
322 | pub fn subst(self, substs: &Substs) -> GenericPredicate { | 350 | pub fn is_implemented(&self) -> bool { |
323 | match self { | 351 | match self { |
324 | GenericPredicate::Implemented(trait_ref) => { | 352 | GenericPredicate::Implemented(_) => true, |
325 | GenericPredicate::Implemented(trait_ref.subst(substs)) | 353 | _ => false, |
326 | } | ||
327 | GenericPredicate::Error => self, | ||
328 | } | 354 | } |
329 | } | 355 | } |
330 | 356 | ||
331 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | 357 | pub fn trait_ref(&self, db: &impl HirDatabase) -> Option<TraitRef> { |
358 | match self { | ||
359 | GenericPredicate::Implemented(tr) => Some(tr.clone()), | ||
360 | GenericPredicate::Projection(proj) => Some(proj.projection_ty.trait_ref(db)), | ||
361 | GenericPredicate::Error => None, | ||
362 | } | ||
363 | } | ||
364 | } | ||
365 | |||
366 | impl TypeWalk for GenericPredicate { | ||
367 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
332 | match self { | 368 | match self { |
333 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f), | 369 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f), |
370 | GenericPredicate::Projection(projection_pred) => projection_pred.walk(f), | ||
334 | GenericPredicate::Error => {} | 371 | GenericPredicate::Error => {} |
335 | } | 372 | } |
336 | } | 373 | } |
337 | 374 | ||
338 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 375 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
339 | match self { | 376 | match self { |
340 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut(f), | 377 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut(f), |
378 | GenericPredicate::Projection(projection_pred) => projection_pred.walk_mut(f), | ||
341 | GenericPredicate::Error => {} | 379 | GenericPredicate::Error => {} |
342 | } | 380 | } |
343 | } | 381 | } |
@@ -378,16 +416,16 @@ impl FnSig { | |||
378 | pub fn ret(&self) -> &Ty { | 416 | pub fn ret(&self) -> &Ty { |
379 | &self.params_and_return[self.params_and_return.len() - 1] | 417 | &self.params_and_return[self.params_and_return.len() - 1] |
380 | } | 418 | } |
419 | } | ||
381 | 420 | ||
382 | /// Applies the given substitutions to all types in this signature and | 421 | impl TypeWalk for FnSig { |
383 | /// returns the result. | 422 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
384 | pub fn subst(&self, substs: &Substs) -> FnSig { | 423 | for t in self.params_and_return.iter() { |
385 | let result: Vec<_> = | 424 | t.walk(f); |
386 | self.params_and_return.iter().map(|ty| ty.clone().subst(substs)).collect(); | 425 | } |
387 | FnSig { params_and_return: result.into() } | ||
388 | } | 426 | } |
389 | 427 | ||
390 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 428 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
391 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | 429 | // Without an Arc::make_mut_slice, we can't avoid the clone here: |
392 | let mut v: Vec<_> = self.params_and_return.iter().cloned().collect(); | 430 | let mut v: Vec<_> = self.params_and_return.iter().cloned().collect(); |
393 | for t in &mut v { | 431 | for t in &mut v { |
@@ -411,64 +449,6 @@ impl Ty { | |||
411 | Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty()) | 449 | Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty()) |
412 | } | 450 | } |
413 | 451 | ||
414 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
415 | match self { | ||
416 | Ty::Apply(a_ty) => { | ||
417 | for t in a_ty.parameters.iter() { | ||
418 | t.walk(f); | ||
419 | } | ||
420 | } | ||
421 | Ty::Projection(p_ty) => { | ||
422 | for t in p_ty.parameters.iter() { | ||
423 | t.walk(f); | ||
424 | } | ||
425 | } | ||
426 | Ty::UnselectedProjection(p_ty) => { | ||
427 | for t in p_ty.parameters.iter() { | ||
428 | t.walk(f); | ||
429 | } | ||
430 | } | ||
431 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | ||
432 | for p in predicates.iter() { | ||
433 | p.walk(f); | ||
434 | } | ||
435 | } | ||
436 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | ||
437 | } | ||
438 | f(self); | ||
439 | } | ||
440 | |||
441 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
442 | match self { | ||
443 | Ty::Apply(a_ty) => { | ||
444 | a_ty.parameters.walk_mut(f); | ||
445 | } | ||
446 | Ty::Projection(p_ty) => { | ||
447 | p_ty.parameters.walk_mut(f); | ||
448 | } | ||
449 | Ty::UnselectedProjection(p_ty) => { | ||
450 | p_ty.parameters.walk_mut(f); | ||
451 | } | ||
452 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | ||
453 | let mut v: Vec<_> = predicates.iter().cloned().collect(); | ||
454 | for p in &mut v { | ||
455 | p.walk_mut(f); | ||
456 | } | ||
457 | *predicates = v.into(); | ||
458 | } | ||
459 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | ||
460 | } | ||
461 | f(self); | ||
462 | } | ||
463 | |||
464 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Ty { | ||
465 | self.walk_mut(&mut |ty_mut| { | ||
466 | let ty = mem::replace(ty_mut, Ty::Unknown); | ||
467 | *ty_mut = f(ty); | ||
468 | }); | ||
469 | self | ||
470 | } | ||
471 | |||
472 | pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { | 452 | pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { |
473 | match self { | 453 | match self { |
474 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => { | 454 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => { |
@@ -544,10 +524,53 @@ impl Ty { | |||
544 | } | 524 | } |
545 | } | 525 | } |
546 | 526 | ||
527 | /// Returns the type parameters of this type if it has some (i.e. is an ADT | ||
528 | /// or function); so if `self` is `Option<u32>`, this returns the `u32`. | ||
529 | pub fn substs(&self) -> Option<Substs> { | ||
530 | match self { | ||
531 | Ty::Apply(ApplicationTy { parameters, .. }) => Some(parameters.clone()), | ||
532 | _ => None, | ||
533 | } | ||
534 | } | ||
535 | |||
536 | /// If this is an `impl Trait` or `dyn Trait`, returns that trait. | ||
537 | pub fn inherent_trait(&self) -> Option<Trait> { | ||
538 | match self { | ||
539 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | ||
540 | predicates.iter().find_map(|pred| match pred { | ||
541 | GenericPredicate::Implemented(tr) => Some(tr.trait_), | ||
542 | _ => None, | ||
543 | }) | ||
544 | } | ||
545 | _ => None, | ||
546 | } | ||
547 | } | ||
548 | } | ||
549 | |||
550 | /// This allows walking structures that contain types to do something with those | ||
551 | /// types, similar to Chalk's `Fold` trait. | ||
552 | pub trait TypeWalk { | ||
553 | fn walk(&self, f: &mut impl FnMut(&Ty)); | ||
554 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)); | ||
555 | |||
556 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self | ||
557 | where | ||
558 | Self: Sized, | ||
559 | { | ||
560 | self.walk_mut(&mut |ty_mut| { | ||
561 | let ty = mem::replace(ty_mut, Ty::Unknown); | ||
562 | *ty_mut = f(ty); | ||
563 | }); | ||
564 | self | ||
565 | } | ||
566 | |||
547 | /// Replaces type parameters in this type using the given `Substs`. (So e.g. | 567 | /// Replaces type parameters in this type using the given `Substs`. (So e.g. |
548 | /// if `self` is `&[T]`, where type parameter T has index 0, and the | 568 | /// if `self` is `&[T]`, where type parameter T has index 0, and the |
549 | /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.) | 569 | /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.) |
550 | pub fn subst(self, substs: &Substs) -> Ty { | 570 | fn subst(self, substs: &Substs) -> Self |
571 | where | ||
572 | Self: Sized, | ||
573 | { | ||
551 | self.fold(&mut |ty| match ty { | 574 | self.fold(&mut |ty| match ty { |
552 | Ty::Param { idx, name } => { | 575 | Ty::Param { idx, name } => { |
553 | substs.get(idx as usize).cloned().unwrap_or(Ty::Param { idx, name }) | 576 | substs.get(idx as usize).cloned().unwrap_or(Ty::Param { idx, name }) |
@@ -557,24 +580,21 @@ impl Ty { | |||
557 | } | 580 | } |
558 | 581 | ||
559 | /// Substitutes `Ty::Bound` vars (as opposed to type parameters). | 582 | /// Substitutes `Ty::Bound` vars (as opposed to type parameters). |
560 | pub fn subst_bound_vars(self, substs: &Substs) -> Ty { | 583 | fn subst_bound_vars(self, substs: &Substs) -> Self |
584 | where | ||
585 | Self: Sized, | ||
586 | { | ||
561 | self.fold(&mut |ty| match ty { | 587 | self.fold(&mut |ty| match ty { |
562 | Ty::Bound(idx) => substs.get(idx as usize).cloned().unwrap_or_else(|| Ty::Bound(idx)), | 588 | Ty::Bound(idx) => substs.get(idx as usize).cloned().unwrap_or_else(|| Ty::Bound(idx)), |
563 | ty => ty, | 589 | ty => ty, |
564 | }) | 590 | }) |
565 | } | 591 | } |
566 | 592 | ||
567 | /// Returns the type parameters of this type if it has some (i.e. is an ADT | ||
568 | /// or function); so if `self` is `Option<u32>`, this returns the `u32`. | ||
569 | pub fn substs(&self) -> Option<Substs> { | ||
570 | match self { | ||
571 | Ty::Apply(ApplicationTy { parameters, .. }) => Some(parameters.clone()), | ||
572 | _ => None, | ||
573 | } | ||
574 | } | ||
575 | |||
576 | /// Shifts up `Ty::Bound` vars by `n`. | 593 | /// Shifts up `Ty::Bound` vars by `n`. |
577 | pub fn shift_bound_vars(self, n: i32) -> Ty { | 594 | fn shift_bound_vars(self, n: i32) -> Self |
595 | where | ||
596 | Self: Sized, | ||
597 | { | ||
578 | self.fold(&mut |ty| match ty { | 598 | self.fold(&mut |ty| match ty { |
579 | Ty::Bound(idx) => { | 599 | Ty::Bound(idx) => { |
580 | assert!(idx as i32 >= -n); | 600 | assert!(idx as i32 >= -n); |
@@ -583,18 +603,57 @@ impl Ty { | |||
583 | ty => ty, | 603 | ty => ty, |
584 | }) | 604 | }) |
585 | } | 605 | } |
606 | } | ||
586 | 607 | ||
587 | /// If this is an `impl Trait` or `dyn Trait`, returns that trait. | 608 | impl TypeWalk for Ty { |
588 | pub fn inherent_trait(&self) -> Option<Trait> { | 609 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
610 | match self { | ||
611 | Ty::Apply(a_ty) => { | ||
612 | for t in a_ty.parameters.iter() { | ||
613 | t.walk(f); | ||
614 | } | ||
615 | } | ||
616 | Ty::Projection(p_ty) => { | ||
617 | for t in p_ty.parameters.iter() { | ||
618 | t.walk(f); | ||
619 | } | ||
620 | } | ||
621 | Ty::UnselectedProjection(p_ty) => { | ||
622 | for t in p_ty.parameters.iter() { | ||
623 | t.walk(f); | ||
624 | } | ||
625 | } | ||
626 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | ||
627 | for p in predicates.iter() { | ||
628 | p.walk(f); | ||
629 | } | ||
630 | } | ||
631 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | ||
632 | } | ||
633 | f(self); | ||
634 | } | ||
635 | |||
636 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
589 | match self { | 637 | match self { |
638 | Ty::Apply(a_ty) => { | ||
639 | a_ty.parameters.walk_mut(f); | ||
640 | } | ||
641 | Ty::Projection(p_ty) => { | ||
642 | p_ty.parameters.walk_mut(f); | ||
643 | } | ||
644 | Ty::UnselectedProjection(p_ty) => { | ||
645 | p_ty.parameters.walk_mut(f); | ||
646 | } | ||
590 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | 647 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { |
591 | predicates.iter().find_map(|pred| match pred { | 648 | let mut v: Vec<_> = predicates.iter().cloned().collect(); |
592 | GenericPredicate::Implemented(tr) => Some(tr.trait_), | 649 | for p in &mut v { |
593 | _ => None, | 650 | p.walk_mut(f); |
594 | }) | 651 | } |
652 | *predicates = v.into(); | ||
595 | } | 653 | } |
596 | _ => None, | 654 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} |
597 | } | 655 | } |
656 | f(self); | ||
598 | } | 657 | } |
599 | } | 658 | } |
600 | 659 | ||
@@ -742,20 +801,66 @@ impl HirDisplay for Ty { | |||
742 | Ty::Opaque(_) => write!(f, "impl ")?, | 801 | Ty::Opaque(_) => write!(f, "impl ")?, |
743 | _ => unreachable!(), | 802 | _ => unreachable!(), |
744 | }; | 803 | }; |
745 | // looping by hand here just to format the bounds in a slightly nicer way | 804 | // Note: This code is written to produce nice results (i.e. |
805 | // corresponding to surface Rust) for types that can occur in | ||
806 | // actual Rust. It will have weird results if the predicates | ||
807 | // aren't as expected (i.e. self types = $0, projection | ||
808 | // predicates for a certain trait come after the Implemented | ||
809 | // predicate for that trait). | ||
746 | let mut first = true; | 810 | let mut first = true; |
811 | let mut angle_open = false; | ||
747 | for p in predicates.iter() { | 812 | for p in predicates.iter() { |
748 | if !first { | ||
749 | write!(f, " + ")?; | ||
750 | } | ||
751 | first = false; | ||
752 | match p { | 813 | match p { |
753 | // don't show the $0 self type | ||
754 | GenericPredicate::Implemented(trait_ref) => { | 814 | GenericPredicate::Implemented(trait_ref) => { |
755 | trait_ref.hir_fmt_ext(f, false)? | 815 | if angle_open { |
816 | write!(f, ">")?; | ||
817 | } | ||
818 | if !first { | ||
819 | write!(f, " + ")?; | ||
820 | } | ||
821 | // We assume that the self type is $0 (i.e. the | ||
822 | // existential) here, which is the only thing that's | ||
823 | // possible in actual Rust, and hence don't print it | ||
824 | write!( | ||
825 | f, | ||
826 | "{}", | ||
827 | trait_ref.trait_.name(f.db).unwrap_or_else(Name::missing) | ||
828 | )?; | ||
829 | if trait_ref.substs.len() > 1 { | ||
830 | write!(f, "<")?; | ||
831 | f.write_joined(&trait_ref.substs[1..], ", ")?; | ||
832 | // there might be assoc type bindings, so we leave the angle brackets open | ||
833 | angle_open = true; | ||
834 | } | ||
835 | } | ||
836 | GenericPredicate::Projection(projection_pred) => { | ||
837 | // in types in actual Rust, these will always come | ||
838 | // after the corresponding Implemented predicate | ||
839 | if angle_open { | ||
840 | write!(f, ", ")?; | ||
841 | } else { | ||
842 | write!(f, "<")?; | ||
843 | angle_open = true; | ||
844 | } | ||
845 | let name = projection_pred.projection_ty.associated_ty.name(f.db); | ||
846 | write!(f, "{} = ", name)?; | ||
847 | projection_pred.ty.hir_fmt(f)?; | ||
848 | } | ||
849 | GenericPredicate::Error => { | ||
850 | if angle_open { | ||
851 | // impl Trait<X, {error}> | ||
852 | write!(f, ", ")?; | ||
853 | } else if !first { | ||
854 | // impl Trait + {error} | ||
855 | write!(f, " + ")?; | ||
856 | } | ||
857 | p.hir_fmt(f)?; | ||
756 | } | 858 | } |
757 | GenericPredicate::Error => p.hir_fmt(f)?, | ||
758 | } | 859 | } |
860 | first = false; | ||
861 | } | ||
862 | if angle_open { | ||
863 | write!(f, ">")?; | ||
759 | } | 864 | } |
760 | } | 865 | } |
761 | Ty::Unknown => write!(f, "{{unknown}}")?, | 866 | Ty::Unknown => write!(f, "{{unknown}}")?, |
@@ -766,13 +871,12 @@ impl HirDisplay for Ty { | |||
766 | } | 871 | } |
767 | 872 | ||
768 | impl TraitRef { | 873 | impl TraitRef { |
769 | fn hir_fmt_ext( | 874 | fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result { |
770 | &self, | 875 | self.substs[0].hir_fmt(f)?; |
771 | f: &mut HirFormatter<impl HirDatabase>, | 876 | if use_as { |
772 | with_self_ty: bool, | 877 | write!(f, " as ")?; |
773 | ) -> fmt::Result { | 878 | } else { |
774 | if with_self_ty { | 879 | write!(f, ": ")?; |
775 | write!(f, "{}: ", self.substs[0].display(f.db),)?; | ||
776 | } | 880 | } |
777 | write!(f, "{}", self.trait_.name(f.db).unwrap_or_else(Name::missing))?; | 881 | write!(f, "{}", self.trait_.name(f.db).unwrap_or_else(Name::missing))?; |
778 | if self.substs.len() > 1 { | 882 | if self.substs.len() > 1 { |
@@ -786,7 +890,7 @@ impl TraitRef { | |||
786 | 890 | ||
787 | impl HirDisplay for TraitRef { | 891 | impl HirDisplay for TraitRef { |
788 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 892 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
789 | self.hir_fmt_ext(f, true) | 893 | self.hir_fmt_ext(f, false) |
790 | } | 894 | } |
791 | } | 895 | } |
792 | 896 | ||
@@ -800,6 +904,16 @@ impl HirDisplay for GenericPredicate { | |||
800 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 904 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
801 | match self { | 905 | match self { |
802 | GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, | 906 | GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, |
907 | GenericPredicate::Projection(projection_pred) => { | ||
908 | write!(f, "<")?; | ||
909 | projection_pred.projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; | ||
910 | write!( | ||
911 | f, | ||
912 | ">::{} = {}", | ||
913 | projection_pred.projection_ty.associated_ty.name(f.db), | ||
914 | projection_pred.ty.display(f.db) | ||
915 | )?; | ||
916 | } | ||
803 | GenericPredicate::Error => write!(f, "{{error}}")?, | 917 | GenericPredicate::Error => write!(f, "{{error}}")?, |
804 | } | 918 | } |
805 | Ok(()) | 919 | Ok(()) |