aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-08-13 22:09:08 +0100
committerFlorian Diebold <[email protected]>2019-08-22 18:33:00 +0100
commit16a7d8cc850002b427fdc8d21ccde81caaed7902 (patch)
tree7f3c43cf9e83d479edc7f9b4849dae5fbd0f356d /crates/ra_hir/src/ty.rs
parent08e5d394dfbca28b15ed5dc772d55d48f87c3f54 (diff)
Add `impl Trait` and `dyn Trait` types
- refactor bounds handling in the AST a bit - add HIR for bounds - add `Ty::Dyn` and `Ty::Opaque` variants and lower `dyn Trait` / `impl Trait` syntax to them
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r--crates/ra_hir/src/ty.rs120
1 files changed, 110 insertions, 10 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 642dd02cb..4e5bdbae4 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);
@@ -669,6 +723,28 @@ impl HirDisplay for Ty {
669 Ty::UnselectedProjection(p_ty) => p_ty.hir_fmt(f)?, 723 Ty::UnselectedProjection(p_ty) => p_ty.hir_fmt(f)?,
670 Ty::Param { name, .. } => write!(f, "{}", name)?, 724 Ty::Param { name, .. } => write!(f, "{}", name)?,
671 Ty::Bound(idx) => write!(f, "?{}", idx)?, 725 Ty::Bound(idx) => write!(f, "?{}", idx)?,
726 Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
727 match self {
728 Ty::Dyn(_) => write!(f, "dyn ")?,
729 Ty::Opaque(_) => write!(f, "impl ")?,
730 _ => unreachable!(),
731 };
732 // looping by hand here just to format the bounds in a slightly nicer way
733 let mut first = true;
734 for p in predicates.iter() {
735 if !first {
736 write!(f, " + ")?;
737 }
738 first = false;
739 match p {
740 // don't show the $0 self type
741 GenericPredicate::Implemented(trait_ref) => {
742 trait_ref.hir_fmt_ext(f, false)?
743 }
744 GenericPredicate::Error => p.hir_fmt(f)?,
745 }
746 }
747 }
672 Ty::Unknown => write!(f, "{{unknown}}")?, 748 Ty::Unknown => write!(f, "{{unknown}}")?,
673 Ty::Infer(..) => write!(f, "_")?, 749 Ty::Infer(..) => write!(f, "_")?,
674 } 750 }
@@ -676,14 +752,16 @@ impl HirDisplay for Ty {
676 } 752 }
677} 753}
678 754
679impl HirDisplay for TraitRef { 755impl TraitRef {
680 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 756 fn hir_fmt_ext(
681 write!( 757 &self,
682 f, 758 f: &mut HirFormatter<impl HirDatabase>,
683 "{}: {}", 759 with_self_ty: bool,
684 self.substs[0].display(f.db), 760 ) -> fmt::Result {
685 self.trait_.name(f.db).unwrap_or_else(Name::missing) 761 if with_self_ty {
686 )?; 762 write!(f, "{}: ", self.substs[0].display(f.db),)?;
763 }
764 write!(f, "{}", self.trait_.name(f.db).unwrap_or_else(Name::missing))?;
687 if self.substs.len() > 1 { 765 if self.substs.len() > 1 {
688 write!(f, "<")?; 766 write!(f, "<")?;
689 f.write_joined(&self.substs[1..], ", ")?; 767 f.write_joined(&self.substs[1..], ", ")?;
@@ -693,6 +771,28 @@ impl HirDisplay for TraitRef {
693 } 771 }
694} 772}
695 773
774impl HirDisplay for TraitRef {
775 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
776 self.hir_fmt_ext(f, true)
777 }
778}
779
780impl HirDisplay for &GenericPredicate {
781 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
782 HirDisplay::hir_fmt(*self, f)
783 }
784}
785
786impl HirDisplay for GenericPredicate {
787 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
788 match self {
789 GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
790 GenericPredicate::Error => write!(f, "{{error}}")?,
791 }
792 Ok(())
793 }
794}
795
696impl HirDisplay for Obligation { 796impl HirDisplay for Obligation {
697 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 797 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
698 match self { 798 match self {