aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r--crates/ra_hir/src/ty.rs348
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
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}
134
135impl 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)]
124pub struct UnselectedProjectionTy { 146pub struct UnselectedProjectionTy {
125 pub type_name: Name, 147 pub type_name: Name,
126 pub parameters: Substs, 148 pub parameters: Substs,
127} 149}
128 150
151impl 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 { 319impl 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 {
306pub enum GenericPredicate { 332pub 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
366impl 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 421impl 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.
552pub 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. 608impl 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
768impl TraitRef { 873impl 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
787impl HirDisplay for TraitRef { 891impl 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(())