aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/lib.rs4
-rw-r--r--crates/ra_hir/src/ty.rs233
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs2
-rw-r--r--crates/ra_hir/src/ty/infer.rs2
-rw-r--r--crates/ra_hir/src/ty/infer/unify.rs2
-rw-r--r--crates/ra_hir/src/ty/lower.rs1
-rw-r--r--crates/ra_hir/src/ty/traits.rs20
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs1
8 files changed, 132 insertions, 133 deletions
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 752653ad7..c3e589921 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -69,7 +69,9 @@ pub use self::{
69 resolve::Resolution, 69 resolve::Resolution,
70 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, 70 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
71 source_id::{AstIdMap, ErasedFileAstId}, 71 source_id::{AstIdMap, ErasedFileAstId},
72 ty::{display::HirDisplay, ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor}, 72 ty::{
73 display::HirDisplay, ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
74 },
73 type_ref::Mutability, 75 type_ref::Mutability,
74}; 76};
75 77
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)) { 135impl 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
149impl UnselectedProjectionTy { 151impl 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 { 319impl 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 { 366impl 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 421impl 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.
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
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. 608impl 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
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs
index 2535d4ae7..08f52a53b 100644
--- a/crates/ra_hir/src/ty/autoderef.rs
+++ b/crates/ra_hir/src/ty/autoderef.rs
@@ -7,7 +7,7 @@ use std::iter::successors;
7 7
8use log::{info, warn}; 8use log::{info, warn};
9 9
10use super::{traits::Solution, Canonical, Ty}; 10use super::{traits::Solution, Canonical, Ty, TypeWalk};
11use crate::{HasGenericParams, HirDatabase, Name, Resolver}; 11use crate::{HasGenericParams, HirDatabase, Name, Resolver};
12 12
13const AUTODEREF_RECURSION_LIMIT: usize = 10; 13const AUTODEREF_RECURSION_LIMIT: usize = 10;
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index b89a40b4b..ec3b7ffef 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -30,7 +30,7 @@ use super::{
30 autoderef, lower, method_resolution, op, primitive, 30 autoderef, lower, method_resolution, op, primitive,
31 traits::{Guidance, Obligation, ProjectionPredicate, Solution}, 31 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
32 ApplicationTy, CallableDef, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, 32 ApplicationTy, CallableDef, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef,
33 Ty, TypableDef, TypeCtor, 33 Ty, TypableDef, TypeCtor, TypeWalk,
34}; 34};
35use crate::{ 35use crate::{
36 adt::VariantDef, 36 adt::VariantDef,
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs
index e7e8825d1..9a0d2d8f9 100644
--- a/crates/ra_hir/src/ty/infer/unify.rs
+++ b/crates/ra_hir/src/ty/infer/unify.rs
@@ -3,7 +3,7 @@
3use super::{InferenceContext, Obligation}; 3use super::{InferenceContext, Obligation};
4use crate::db::HirDatabase; 4use crate::db::HirDatabase;
5use crate::ty::{ 5use crate::ty::{
6 Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, 6 Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, TypeWalk,
7}; 7};
8 8
9impl<'a, D: HirDatabase> InferenceContext<'a, D> { 9impl<'a, D: HirDatabase> InferenceContext<'a, D> {
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 0011c06b4..f6f0137cf 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -10,6 +10,7 @@ use std::sync::Arc;
10 10
11use super::{ 11use super::{
12 FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, 12 FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
13 TypeWalk,
13}; 14};
14use crate::{ 15use crate::{
15 adt::VariantDef, 16 adt::VariantDef,
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index 25316bc02..6e0271a96 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -8,7 +8,7 @@ use ra_db::salsa;
8use ra_prof::profile; 8use ra_prof::profile;
9use rustc_hash::FxHashSet; 9use rustc_hash::FxHashSet;
10 10
11use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty}; 11use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
12use crate::{db::HirDatabase, Crate, ImplBlock, Trait}; 12use crate::{db::HirDatabase, Crate, ImplBlock, Trait};
13 13
14use self::chalk::{from_chalk, ToChalk}; 14use self::chalk::{from_chalk, ToChalk};
@@ -138,25 +138,13 @@ pub struct ProjectionPredicate {
138 pub ty: Ty, 138 pub ty: Ty,
139} 139}
140 140
141impl ProjectionPredicate { 141impl TypeWalk for ProjectionPredicate {
142 pub fn subst(mut self, substs: &super::Substs) -> ProjectionPredicate { 142 fn walk(&self, f: &mut impl FnMut(&Ty)) {
143 self.walk_mut(&mut |ty| match ty {
144 Ty::Param { idx, .. } => {
145 if let Some(t) = substs.get(*idx as usize).cloned() {
146 *ty = t;
147 }
148 }
149 _ => {}
150 });
151 self
152 }
153
154 pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
155 self.projection_ty.walk(f); 143 self.projection_ty.walk(f);
156 self.ty.walk(f); 144 self.ty.walk(f);
157 } 145 }
158 146
159 pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { 147 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
160 self.projection_ty.walk_mut(f); 148 self.projection_ty.walk_mut(f);
161 self.ty.walk_mut(f); 149 self.ty.walk_mut(f);
162 } 150 }
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 3ab5b7cca..c201c5e50 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -19,6 +19,7 @@ use crate::{
19 ty::display::HirDisplay, 19 ty::display::HirDisplay,
20 ty::{ 20 ty::{
21 ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, 21 ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
22 TypeWalk,
22 }, 23 },
23 Crate, HasGenericParams, ImplBlock, ImplItem, Trait, TypeAlias, 24 Crate, HasGenericParams, ImplBlock, ImplItem, Trait, TypeAlias,
24}; 25};