diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 82589e504..642dd02cb 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -94,6 +94,12 @@ pub enum TypeCtor { | |||
94 | 94 | ||
95 | /// A tuple type. For example, `(i32, bool)`. | 95 | /// A tuple type. For example, `(i32, bool)`. |
96 | Tuple { cardinality: u16 }, | 96 | Tuple { cardinality: u16 }, |
97 | |||
98 | /// Represents an associated item like `Iterator::Item`. This is used | ||
99 | /// when we have tried to normalize a projection like `T::Item` but | ||
100 | /// couldn't find a better representation. In that case, we generate | ||
101 | /// an **application type** like `(Iterator::Item)<T>`. | ||
102 | AssociatedType(TypeAlias), | ||
97 | } | 103 | } |
98 | 104 | ||
99 | /// A nominal type with (maybe 0) type parameters. This might be a primitive | 105 | /// A nominal type with (maybe 0) type parameters. This might be a primitive |
@@ -114,6 +120,12 @@ pub struct ProjectionTy { | |||
114 | pub parameters: Substs, | 120 | pub parameters: Substs, |
115 | } | 121 | } |
116 | 122 | ||
123 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
124 | pub struct UnselectedProjectionTy { | ||
125 | pub type_name: Name, | ||
126 | pub parameters: Substs, | ||
127 | } | ||
128 | |||
117 | /// A type. | 129 | /// A type. |
118 | /// | 130 | /// |
119 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents | 131 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents |
@@ -127,6 +139,18 @@ pub enum Ty { | |||
127 | /// several other things. | 139 | /// several other things. |
128 | Apply(ApplicationTy), | 140 | Apply(ApplicationTy), |
129 | 141 | ||
142 | /// A "projection" type corresponds to an (unnormalized) | ||
143 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | ||
144 | /// trait and all its parameters are fully known. | ||
145 | Projection(ProjectionTy), | ||
146 | |||
147 | /// This is a variant of a projection in which the trait is | ||
148 | /// **not** known. It corresponds to a case where people write | ||
149 | /// `T::Item` without specifying the trait. We would then try to | ||
150 | /// figure out the trait by looking at all the traits that are in | ||
151 | /// scope. | ||
152 | UnselectedProjection(UnselectedProjectionTy), | ||
153 | |||
130 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} | 154 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} |
131 | Param { | 155 | Param { |
132 | /// The index of the parameter (starting with parameters from the | 156 | /// The index of the parameter (starting with parameters from the |
@@ -352,6 +376,16 @@ impl Ty { | |||
352 | t.walk(f); | 376 | t.walk(f); |
353 | } | 377 | } |
354 | } | 378 | } |
379 | Ty::Projection(p_ty) => { | ||
380 | for t in p_ty.parameters.iter() { | ||
381 | t.walk(f); | ||
382 | } | ||
383 | } | ||
384 | Ty::UnselectedProjection(p_ty) => { | ||
385 | for t in p_ty.parameters.iter() { | ||
386 | t.walk(f); | ||
387 | } | ||
388 | } | ||
355 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | 389 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} |
356 | } | 390 | } |
357 | f(self); | 391 | f(self); |
@@ -362,6 +396,12 @@ impl Ty { | |||
362 | Ty::Apply(a_ty) => { | 396 | Ty::Apply(a_ty) => { |
363 | a_ty.parameters.walk_mut(f); | 397 | a_ty.parameters.walk_mut(f); |
364 | } | 398 | } |
399 | Ty::Projection(p_ty) => { | ||
400 | p_ty.parameters.walk_mut(f); | ||
401 | } | ||
402 | Ty::UnselectedProjection(p_ty) => { | ||
403 | p_ty.parameters.walk_mut(f); | ||
404 | } | ||
365 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | 405 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} |
366 | } | 406 | } |
367 | f(self); | 407 | f(self); |
@@ -572,15 +612,61 @@ impl HirDisplay for ApplicationTy { | |||
572 | write!(f, ">")?; | 612 | write!(f, ">")?; |
573 | } | 613 | } |
574 | } | 614 | } |
615 | TypeCtor::AssociatedType(type_alias) => { | ||
616 | let trait_name = type_alias | ||
617 | .parent_trait(f.db) | ||
618 | .and_then(|t| t.name(f.db)) | ||
619 | .unwrap_or_else(Name::missing); | ||
620 | let name = type_alias.name(f.db); | ||
621 | write!(f, "{}::{}", trait_name, name)?; | ||
622 | if self.parameters.len() > 0 { | ||
623 | write!(f, "<")?; | ||
624 | f.write_joined(&*self.parameters.0, ", ")?; | ||
625 | write!(f, ">")?; | ||
626 | } | ||
627 | } | ||
575 | } | 628 | } |
576 | Ok(()) | 629 | Ok(()) |
577 | } | 630 | } |
578 | } | 631 | } |
579 | 632 | ||
633 | impl HirDisplay for ProjectionTy { | ||
634 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | ||
635 | let trait_name = self | ||
636 | .associated_ty | ||
637 | .parent_trait(f.db) | ||
638 | .and_then(|t| t.name(f.db)) | ||
639 | .unwrap_or_else(Name::missing); | ||
640 | write!(f, "<{} as {}", self.parameters[0].display(f.db), trait_name,)?; | ||
641 | if self.parameters.len() > 1 { | ||
642 | write!(f, "<")?; | ||
643 | f.write_joined(&self.parameters[1..], ", ")?; | ||
644 | write!(f, ">")?; | ||
645 | } | ||
646 | write!(f, ">::{}", self.associated_ty.name(f.db))?; | ||
647 | Ok(()) | ||
648 | } | ||
649 | } | ||
650 | |||
651 | impl HirDisplay for UnselectedProjectionTy { | ||
652 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | ||
653 | write!(f, "{}", self.parameters[0].display(f.db))?; | ||
654 | if self.parameters.len() > 1 { | ||
655 | write!(f, "<")?; | ||
656 | f.write_joined(&self.parameters[1..], ", ")?; | ||
657 | write!(f, ">")?; | ||
658 | } | ||
659 | write!(f, "::{}", self.type_name)?; | ||
660 | Ok(()) | ||
661 | } | ||
662 | } | ||
663 | |||
580 | impl HirDisplay for Ty { | 664 | impl HirDisplay for Ty { |
581 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 665 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
582 | match self { | 666 | match self { |
583 | Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, | 667 | Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, |
668 | Ty::Projection(p_ty) => p_ty.hir_fmt(f)?, | ||
669 | Ty::UnselectedProjection(p_ty) => p_ty.hir_fmt(f)?, | ||
584 | Ty::Param { name, .. } => write!(f, "{}", name)?, | 670 | Ty::Param { name, .. } => write!(f, "{}", name)?, |
585 | Ty::Bound(idx) => write!(f, "?{}", idx)?, | 671 | Ty::Bound(idx) => write!(f, "?{}", idx)?, |
586 | Ty::Unknown => write!(f, "{{unknown}}")?, | 672 | Ty::Unknown => write!(f, "{{unknown}}")?, |
@@ -606,3 +692,17 @@ impl HirDisplay for TraitRef { | |||
606 | Ok(()) | 692 | Ok(()) |
607 | } | 693 | } |
608 | } | 694 | } |
695 | |||
696 | impl HirDisplay for Obligation { | ||
697 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | ||
698 | match self { | ||
699 | Obligation::Trait(tr) => write!(f, "Implements({})", tr.display(f.db)), | ||
700 | Obligation::Projection(proj) => write!( | ||
701 | f, | ||
702 | "Normalize({} => {})", | ||
703 | proj.projection_ty.display(f.db), | ||
704 | proj.ty.display(f.db) | ||
705 | ), | ||
706 | } | ||
707 | } | ||
708 | } | ||