diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 233 |
1 files changed, 120 insertions, 113 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index c0c609d78..a3df08827 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -130,12 +130,14 @@ impl ProjectionTy { | |||
130 | substs: self.parameters.clone(), | 130 | substs: self.parameters.clone(), |
131 | } | 131 | } |
132 | } | 132 | } |
133 | } | ||
133 | 134 | ||
134 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | 135 | impl TypeWalk for ProjectionTy { |
136 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
135 | self.parameters.walk(f); | 137 | self.parameters.walk(f); |
136 | } | 138 | } |
137 | 139 | ||
138 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 140 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
139 | self.parameters.walk_mut(f); | 141 | self.parameters.walk_mut(f); |
140 | } | 142 | } |
141 | } | 143 | } |
@@ -146,12 +148,12 @@ pub struct UnselectedProjectionTy { | |||
146 | pub parameters: Substs, | 148 | pub parameters: Substs, |
147 | } | 149 | } |
148 | 150 | ||
149 | impl UnselectedProjectionTy { | 151 | impl TypeWalk for UnselectedProjectionTy { |
150 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | 152 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
151 | self.parameters.walk(f); | 153 | self.parameters.walk(f); |
152 | } | 154 | } |
153 | 155 | ||
154 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 156 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
155 | self.parameters.walk_mut(f); | 157 | self.parameters.walk_mut(f); |
156 | } | 158 | } |
157 | } | 159 | } |
@@ -312,20 +314,14 @@ impl TraitRef { | |||
312 | pub fn self_ty(&self) -> &Ty { | 314 | pub fn self_ty(&self) -> &Ty { |
313 | &self.substs[0] | 315 | &self.substs[0] |
314 | } | 316 | } |
317 | } | ||
315 | 318 | ||
316 | pub fn subst(mut self, substs: &Substs) -> TraitRef { | 319 | impl TypeWalk for TraitRef { |
317 | self.substs.walk_mut(&mut |ty_mut| { | 320 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
318 | let ty = mem::replace(ty_mut, Ty::Unknown); | ||
319 | *ty_mut = ty.subst(substs); | ||
320 | }); | ||
321 | self | ||
322 | } | ||
323 | |||
324 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
325 | self.substs.walk(f); | 321 | self.substs.walk(f); |
326 | } | 322 | } |
327 | 323 | ||
328 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 324 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
329 | self.substs.walk_mut(f); | 325 | self.substs.walk_mut(f); |
330 | } | 326 | } |
331 | } | 327 | } |
@@ -365,20 +361,10 @@ impl GenericPredicate { | |||
365 | GenericPredicate::Error => None, | 361 | GenericPredicate::Error => None, |
366 | } | 362 | } |
367 | } | 363 | } |
364 | } | ||
368 | 365 | ||
369 | pub fn subst(self, substs: &Substs) -> GenericPredicate { | 366 | impl TypeWalk for GenericPredicate { |
370 | match self { | 367 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
371 | GenericPredicate::Implemented(trait_ref) => { | ||
372 | GenericPredicate::Implemented(trait_ref.subst(substs)) | ||
373 | } | ||
374 | GenericPredicate::Projection(projection_predicate) => { | ||
375 | GenericPredicate::Projection(projection_predicate.subst(substs)) | ||
376 | } | ||
377 | GenericPredicate::Error => self, | ||
378 | } | ||
379 | } | ||
380 | |||
381 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
382 | match self { | 368 | match self { |
383 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f), | 369 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f), |
384 | GenericPredicate::Projection(projection_pred) => projection_pred.walk(f), | 370 | GenericPredicate::Projection(projection_pred) => projection_pred.walk(f), |
@@ -386,7 +372,7 @@ impl GenericPredicate { | |||
386 | } | 372 | } |
387 | } | 373 | } |
388 | 374 | ||
389 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 375 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
390 | match self { | 376 | match self { |
391 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut(f), | 377 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut(f), |
392 | GenericPredicate::Projection(projection_pred) => projection_pred.walk_mut(f), | 378 | GenericPredicate::Projection(projection_pred) => projection_pred.walk_mut(f), |
@@ -430,16 +416,16 @@ impl FnSig { | |||
430 | pub fn ret(&self) -> &Ty { | 416 | pub fn ret(&self) -> &Ty { |
431 | &self.params_and_return[self.params_and_return.len() - 1] | 417 | &self.params_and_return[self.params_and_return.len() - 1] |
432 | } | 418 | } |
419 | } | ||
433 | 420 | ||
434 | /// Applies the given substitutions to all types in this signature and | 421 | impl TypeWalk for FnSig { |
435 | /// returns the result. | 422 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
436 | pub fn subst(&self, substs: &Substs) -> FnSig { | 423 | for t in self.params_and_return.iter() { |
437 | let result: Vec<_> = | 424 | t.walk(f); |
438 | self.params_and_return.iter().map(|ty| ty.clone().subst(substs)).collect(); | 425 | } |
439 | FnSig { params_and_return: result.into() } | ||
440 | } | 426 | } |
441 | 427 | ||
442 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 428 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
443 | // 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: |
444 | let mut v: Vec<_> = self.params_and_return.iter().cloned().collect(); | 430 | let mut v: Vec<_> = self.params_and_return.iter().cloned().collect(); |
445 | for t in &mut v { | 431 | for t in &mut v { |
@@ -463,64 +449,6 @@ impl Ty { | |||
463 | Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty()) | 449 | Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty()) |
464 | } | 450 | } |
465 | 451 | ||
466 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
467 | match self { | ||
468 | Ty::Apply(a_ty) => { | ||
469 | for t in a_ty.parameters.iter() { | ||
470 | t.walk(f); | ||
471 | } | ||
472 | } | ||
473 | Ty::Projection(p_ty) => { | ||
474 | for t in p_ty.parameters.iter() { | ||
475 | t.walk(f); | ||
476 | } | ||
477 | } | ||
478 | Ty::UnselectedProjection(p_ty) => { | ||
479 | for t in p_ty.parameters.iter() { | ||
480 | t.walk(f); | ||
481 | } | ||
482 | } | ||
483 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | ||
484 | for p in predicates.iter() { | ||
485 | p.walk(f); | ||
486 | } | ||
487 | } | ||
488 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | ||
489 | } | ||
490 | f(self); | ||
491 | } | ||
492 | |||
493 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
494 | match self { | ||
495 | Ty::Apply(a_ty) => { | ||
496 | a_ty.parameters.walk_mut(f); | ||
497 | } | ||
498 | Ty::Projection(p_ty) => { | ||
499 | p_ty.parameters.walk_mut(f); | ||
500 | } | ||
501 | Ty::UnselectedProjection(p_ty) => { | ||
502 | p_ty.parameters.walk_mut(f); | ||
503 | } | ||
504 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | ||
505 | let mut v: Vec<_> = predicates.iter().cloned().collect(); | ||
506 | for p in &mut v { | ||
507 | p.walk_mut(f); | ||
508 | } | ||
509 | *predicates = v.into(); | ||
510 | } | ||
511 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | ||
512 | } | ||
513 | f(self); | ||
514 | } | ||
515 | |||
516 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Ty { | ||
517 | self.walk_mut(&mut |ty_mut| { | ||
518 | let ty = mem::replace(ty_mut, Ty::Unknown); | ||
519 | *ty_mut = f(ty); | ||
520 | }); | ||
521 | self | ||
522 | } | ||
523 | |||
524 | pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { | 452 | pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { |
525 | match self { | 453 | match self { |
526 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => { | 454 | Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => { |
@@ -596,10 +524,53 @@ impl Ty { | |||
596 | } | 524 | } |
597 | } | 525 | } |
598 | 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 | |||
599 | /// 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. |
600 | /// 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 |
601 | /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.) | 569 | /// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.) |
602 | pub fn subst(self, substs: &Substs) -> Ty { | 570 | fn subst(self, substs: &Substs) -> Self |
571 | where | ||
572 | Self: Sized, | ||
573 | { | ||
603 | self.fold(&mut |ty| match ty { | 574 | self.fold(&mut |ty| match ty { |
604 | Ty::Param { idx, name } => { | 575 | Ty::Param { idx, name } => { |
605 | 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 }) |
@@ -609,24 +580,21 @@ impl Ty { | |||
609 | } | 580 | } |
610 | 581 | ||
611 | /// Substitutes `Ty::Bound` vars (as opposed to type parameters). | 582 | /// Substitutes `Ty::Bound` vars (as opposed to type parameters). |
612 | pub fn subst_bound_vars(self, substs: &Substs) -> Ty { | 583 | fn subst_bound_vars(self, substs: &Substs) -> Self |
584 | where | ||
585 | Self: Sized, | ||
586 | { | ||
613 | self.fold(&mut |ty| match ty { | 587 | self.fold(&mut |ty| match ty { |
614 | 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)), |
615 | ty => ty, | 589 | ty => ty, |
616 | }) | 590 | }) |
617 | } | 591 | } |
618 | 592 | ||
619 | /// Returns the type parameters of this type if it has some (i.e. is an ADT | ||
620 | /// or function); so if `self` is `Option<u32>`, this returns the `u32`. | ||
621 | pub fn substs(&self) -> Option<Substs> { | ||
622 | match self { | ||
623 | Ty::Apply(ApplicationTy { parameters, .. }) => Some(parameters.clone()), | ||
624 | _ => None, | ||
625 | } | ||
626 | } | ||
627 | |||
628 | /// Shifts up `Ty::Bound` vars by `n`. | 593 | /// Shifts up `Ty::Bound` vars by `n`. |
629 | pub fn shift_bound_vars(self, n: i32) -> Ty { | 594 | fn shift_bound_vars(self, n: i32) -> Self |
595 | where | ||
596 | Self: Sized, | ||
597 | { | ||
630 | self.fold(&mut |ty| match ty { | 598 | self.fold(&mut |ty| match ty { |
631 | Ty::Bound(idx) => { | 599 | Ty::Bound(idx) => { |
632 | assert!(idx as i32 >= -n); | 600 | assert!(idx as i32 >= -n); |
@@ -635,18 +603,57 @@ impl Ty { | |||
635 | ty => ty, | 603 | ty => ty, |
636 | }) | 604 | }) |
637 | } | 605 | } |
606 | } | ||
638 | 607 | ||
639 | /// If this is an `impl Trait` or `dyn Trait`, returns that trait. | 608 | impl TypeWalk for Ty { |
640 | pub fn inherent_trait(&self) -> Option<Trait> { | 609 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
641 | match self { | 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 | } | ||
642 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | 626 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { |
643 | predicates.iter().find_map(|pred| match pred { | 627 | for p in predicates.iter() { |
644 | GenericPredicate::Implemented(tr) => Some(tr.trait_), | 628 | p.walk(f); |
645 | _ => None, | 629 | } |
646 | }) | ||
647 | } | 630 | } |
648 | _ => None, | 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)) { | ||
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 | } | ||
647 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | ||
648 | let mut v: Vec<_> = predicates.iter().cloned().collect(); | ||
649 | for p in &mut v { | ||
650 | p.walk_mut(f); | ||
651 | } | ||
652 | *predicates = v.into(); | ||
653 | } | ||
654 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | ||
649 | } | 655 | } |
656 | f(self); | ||
650 | } | 657 | } |
651 | } | 658 | } |
652 | 659 | ||