diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 133 |
1 files changed, 123 insertions, 10 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 642dd02cb..b54c80318 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -161,14 +161,28 @@ pub enum Ty { | |||
161 | name: Name, | 161 | name: Name, |
162 | }, | 162 | }, |
163 | 163 | ||
164 | /// A bound type variable. Only used during trait resolution to represent | 164 | /// A bound type variable. Used during trait resolution to represent Chalk |
165 | /// Chalk variables. | 165 | /// variables, and in `Dyn` and `Opaque` bounds to represent the `Self` type. |
166 | Bound(u32), | 166 | Bound(u32), |
167 | 167 | ||
168 | /// A type variable used during type checking. Not to be confused with a | 168 | /// A type variable used during type checking. Not to be confused with a |
169 | /// type parameter. | 169 | /// type parameter. |
170 | Infer(InferTy), | 170 | Infer(InferTy), |
171 | 171 | ||
172 | /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). | ||
173 | /// | ||
174 | /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)` | ||
175 | /// represents the `Self` type inside the bounds. This is currently | ||
176 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it | ||
177 | /// didn't seem worth the overhead yet. | ||
178 | Dyn(Arc<[GenericPredicate]>), | ||
179 | |||
180 | /// An opaque type (`impl Trait`). | ||
181 | /// | ||
182 | /// The predicates are quantified over the `Self` type; see `Ty::Dyn` for | ||
183 | /// more. | ||
184 | Opaque(Arc<[GenericPredicate]>), | ||
185 | |||
172 | /// A placeholder for a type which could not be computed; this is propagated | 186 | /// A placeholder for a type which could not be computed; this is propagated |
173 | /// to avoid useless error messages. Doubles as a placeholder where type | 187 | /// to avoid useless error messages. Doubles as a placeholder where type |
174 | /// variables are inserted before type checking, since we want to try to | 188 | /// variables are inserted before type checking, since we want to try to |
@@ -194,6 +208,12 @@ impl Substs { | |||
194 | Substs(self.0.iter().cloned().take(n).collect::<Vec<_>>().into()) | 208 | Substs(self.0.iter().cloned().take(n).collect::<Vec<_>>().into()) |
195 | } | 209 | } |
196 | 210 | ||
211 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
212 | for t in self.0.iter() { | ||
213 | t.walk(f); | ||
214 | } | ||
215 | } | ||
216 | |||
197 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 217 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
198 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | 218 | // Without an Arc::make_mut_slice, we can't avoid the clone here: |
199 | let mut v: Vec<_> = self.0.iter().cloned().collect(); | 219 | let mut v: Vec<_> = self.0.iter().cloned().collect(); |
@@ -270,6 +290,14 @@ impl TraitRef { | |||
270 | }); | 290 | }); |
271 | self | 291 | self |
272 | } | 292 | } |
293 | |||
294 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
295 | self.substs.walk(f); | ||
296 | } | ||
297 | |||
298 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
299 | self.substs.walk_mut(f); | ||
300 | } | ||
273 | } | 301 | } |
274 | 302 | ||
275 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the | 303 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the |
@@ -299,6 +327,20 @@ impl GenericPredicate { | |||
299 | GenericPredicate::Error => self, | 327 | GenericPredicate::Error => self, |
300 | } | 328 | } |
301 | } | 329 | } |
330 | |||
331 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
332 | match self { | ||
333 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f), | ||
334 | GenericPredicate::Error => {} | ||
335 | } | ||
336 | } | ||
337 | |||
338 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
339 | match self { | ||
340 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut(f), | ||
341 | GenericPredicate::Error => {} | ||
342 | } | ||
343 | } | ||
302 | } | 344 | } |
303 | 345 | ||
304 | /// Basically a claim (currently not validated / checked) that the contained | 346 | /// Basically a claim (currently not validated / checked) that the contained |
@@ -386,6 +428,11 @@ impl Ty { | |||
386 | t.walk(f); | 428 | t.walk(f); |
387 | } | 429 | } |
388 | } | 430 | } |
431 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | ||
432 | for p in predicates.iter() { | ||
433 | p.walk(f); | ||
434 | } | ||
435 | } | ||
389 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | 436 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} |
390 | } | 437 | } |
391 | f(self); | 438 | f(self); |
@@ -402,6 +449,13 @@ impl Ty { | |||
402 | Ty::UnselectedProjection(p_ty) => { | 449 | Ty::UnselectedProjection(p_ty) => { |
403 | p_ty.parameters.walk_mut(f); | 450 | p_ty.parameters.walk_mut(f); |
404 | } | 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 | } | ||
405 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | 459 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} |
406 | } | 460 | } |
407 | f(self); | 461 | f(self); |
@@ -529,6 +583,19 @@ impl Ty { | |||
529 | ty => ty, | 583 | ty => ty, |
530 | }) | 584 | }) |
531 | } | 585 | } |
586 | |||
587 | /// If this is an `impl Trait` or `dyn Trait`, returns that trait. | ||
588 | pub fn inherent_trait(&self) -> Option<Trait> { | ||
589 | match self { | ||
590 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | ||
591 | predicates.iter().find_map(|pred| match pred { | ||
592 | GenericPredicate::Implemented(tr) => Some(tr.trait_), | ||
593 | _ => None, | ||
594 | }) | ||
595 | } | ||
596 | _ => None, | ||
597 | } | ||
598 | } | ||
532 | } | 599 | } |
533 | 600 | ||
534 | impl HirDisplay for &Ty { | 601 | impl HirDisplay for &Ty { |
@@ -669,6 +736,28 @@ impl HirDisplay for Ty { | |||
669 | Ty::UnselectedProjection(p_ty) => p_ty.hir_fmt(f)?, | 736 | Ty::UnselectedProjection(p_ty) => p_ty.hir_fmt(f)?, |
670 | Ty::Param { name, .. } => write!(f, "{}", name)?, | 737 | Ty::Param { name, .. } => write!(f, "{}", name)?, |
671 | Ty::Bound(idx) => write!(f, "?{}", idx)?, | 738 | Ty::Bound(idx) => write!(f, "?{}", idx)?, |
739 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | ||
740 | match self { | ||
741 | Ty::Dyn(_) => write!(f, "dyn ")?, | ||
742 | Ty::Opaque(_) => write!(f, "impl ")?, | ||
743 | _ => unreachable!(), | ||
744 | }; | ||
745 | // looping by hand here just to format the bounds in a slightly nicer way | ||
746 | let mut first = true; | ||
747 | for p in predicates.iter() { | ||
748 | if !first { | ||
749 | write!(f, " + ")?; | ||
750 | } | ||
751 | first = false; | ||
752 | match p { | ||
753 | // don't show the $0 self type | ||
754 | GenericPredicate::Implemented(trait_ref) => { | ||
755 | trait_ref.hir_fmt_ext(f, false)? | ||
756 | } | ||
757 | GenericPredicate::Error => p.hir_fmt(f)?, | ||
758 | } | ||
759 | } | ||
760 | } | ||
672 | Ty::Unknown => write!(f, "{{unknown}}")?, | 761 | Ty::Unknown => write!(f, "{{unknown}}")?, |
673 | Ty::Infer(..) => write!(f, "_")?, | 762 | Ty::Infer(..) => write!(f, "_")?, |
674 | } | 763 | } |
@@ -676,14 +765,16 @@ impl HirDisplay for Ty { | |||
676 | } | 765 | } |
677 | } | 766 | } |
678 | 767 | ||
679 | impl HirDisplay for TraitRef { | 768 | impl TraitRef { |
680 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 769 | fn hir_fmt_ext( |
681 | write!( | 770 | &self, |
682 | f, | 771 | f: &mut HirFormatter<impl HirDatabase>, |
683 | "{}: {}", | 772 | with_self_ty: bool, |
684 | self.substs[0].display(f.db), | 773 | ) -> fmt::Result { |
685 | self.trait_.name(f.db).unwrap_or_else(Name::missing) | 774 | if with_self_ty { |
686 | )?; | 775 | write!(f, "{}: ", self.substs[0].display(f.db),)?; |
776 | } | ||
777 | write!(f, "{}", self.trait_.name(f.db).unwrap_or_else(Name::missing))?; | ||
687 | if self.substs.len() > 1 { | 778 | if self.substs.len() > 1 { |
688 | write!(f, "<")?; | 779 | write!(f, "<")?; |
689 | f.write_joined(&self.substs[1..], ", ")?; | 780 | f.write_joined(&self.substs[1..], ", ")?; |
@@ -693,6 +784,28 @@ impl HirDisplay for TraitRef { | |||
693 | } | 784 | } |
694 | } | 785 | } |
695 | 786 | ||
787 | impl HirDisplay for TraitRef { | ||
788 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | ||
789 | self.hir_fmt_ext(f, true) | ||
790 | } | ||
791 | } | ||
792 | |||
793 | impl HirDisplay for &GenericPredicate { | ||
794 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | ||
795 | HirDisplay::hir_fmt(*self, f) | ||
796 | } | ||
797 | } | ||
798 | |||
799 | impl HirDisplay for GenericPredicate { | ||
800 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | ||
801 | match self { | ||
802 | GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, | ||
803 | GenericPredicate::Error => write!(f, "{{error}}")?, | ||
804 | } | ||
805 | Ok(()) | ||
806 | } | ||
807 | } | ||
808 | |||
696 | impl HirDisplay for Obligation { | 809 | impl HirDisplay for Obligation { |
697 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { | 810 | fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { |
698 | match self { | 811 | match self { |