mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 13:25:09 +00:00
Make type walking infrastructure a bit nicer
If/when we switch to using Chalk's Ty, we'll need to replace this by its `Fold` trait, but I didn't want to import the whole thing just yet.
This commit is contained in:
parent
c4fcfa2b0d
commit
b8c1e402fa
10 changed files with 146 additions and 147 deletions
|
@ -1,7 +1,7 @@
|
||||||
use std::{collections::HashSet, fmt::Write, path::Path, time::Instant};
|
use std::{collections::HashSet, fmt::Write, path::Path, time::Instant};
|
||||||
|
|
||||||
use ra_db::SourceDatabase;
|
use ra_db::SourceDatabase;
|
||||||
use ra_hir::{Crate, HasBodySource, HasSource, HirDisplay, ImplItem, ModuleDef, Ty};
|
use ra_hir::{Crate, HasBodySource, HasSource, HirDisplay, ImplItem, ModuleDef, Ty, TypeWalk};
|
||||||
use ra_syntax::AstNode;
|
use ra_syntax::AstNode;
|
||||||
|
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
|
@ -69,7 +69,9 @@ pub use self::{
|
||||||
resolve::Resolution,
|
resolve::Resolution,
|
||||||
source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
|
source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
|
||||||
source_id::{AstIdMap, ErasedFileAstId},
|
source_id::{AstIdMap, ErasedFileAstId},
|
||||||
ty::{display::HirDisplay, ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor},
|
ty::{
|
||||||
|
display::HirDisplay, ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
|
||||||
|
},
|
||||||
type_ref::Mutability,
|
type_ref::Mutability,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -130,12 +130,14 @@ impl ProjectionTy {
|
||||||
substs: self.parameters.clone(),
|
substs: self.parameters.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
impl TypeWalk for ProjectionTy {
|
||||||
|
fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
||||||
self.parameters.walk(f);
|
self.parameters.walk(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
||||||
self.parameters.walk_mut(f);
|
self.parameters.walk_mut(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,12 +148,12 @@ pub struct UnselectedProjectionTy {
|
||||||
pub parameters: Substs,
|
pub parameters: Substs,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnselectedProjectionTy {
|
impl TypeWalk for UnselectedProjectionTy {
|
||||||
pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
||||||
self.parameters.walk(f);
|
self.parameters.walk(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
||||||
self.parameters.walk_mut(f);
|
self.parameters.walk_mut(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,20 +314,14 @@ impl TraitRef {
|
||||||
pub fn self_ty(&self) -> &Ty {
|
pub fn self_ty(&self) -> &Ty {
|
||||||
&self.substs[0]
|
&self.substs[0]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn subst(mut self, substs: &Substs) -> TraitRef {
|
impl TypeWalk for TraitRef {
|
||||||
self.substs.walk_mut(&mut |ty_mut| {
|
fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
||||||
let ty = mem::replace(ty_mut, Ty::Unknown);
|
|
||||||
*ty_mut = ty.subst(substs);
|
|
||||||
});
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
|
||||||
self.substs.walk(f);
|
self.substs.walk(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
||||||
self.substs.walk_mut(f);
|
self.substs.walk_mut(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,20 +361,10 @@ impl GenericPredicate {
|
||||||
GenericPredicate::Error => None,
|
GenericPredicate::Error => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn subst(self, substs: &Substs) -> GenericPredicate {
|
impl TypeWalk for GenericPredicate {
|
||||||
match self {
|
fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
||||||
GenericPredicate::Implemented(trait_ref) => {
|
|
||||||
GenericPredicate::Implemented(trait_ref.subst(substs))
|
|
||||||
}
|
|
||||||
GenericPredicate::Projection(projection_predicate) => {
|
|
||||||
GenericPredicate::Projection(projection_predicate.subst(substs))
|
|
||||||
}
|
|
||||||
GenericPredicate::Error => self,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
|
||||||
match self {
|
match self {
|
||||||
GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f),
|
GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f),
|
||||||
GenericPredicate::Projection(projection_pred) => projection_pred.walk(f),
|
GenericPredicate::Projection(projection_pred) => projection_pred.walk(f),
|
||||||
|
@ -386,7 +372,7 @@ impl GenericPredicate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
||||||
match self {
|
match self {
|
||||||
GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut(f),
|
GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut(f),
|
||||||
GenericPredicate::Projection(projection_pred) => projection_pred.walk_mut(f),
|
GenericPredicate::Projection(projection_pred) => projection_pred.walk_mut(f),
|
||||||
|
@ -430,16 +416,16 @@ impl FnSig {
|
||||||
pub fn ret(&self) -> &Ty {
|
pub fn ret(&self) -> &Ty {
|
||||||
&self.params_and_return[self.params_and_return.len() - 1]
|
&self.params_and_return[self.params_and_return.len() - 1]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Applies the given substitutions to all types in this signature and
|
impl TypeWalk for FnSig {
|
||||||
/// returns the result.
|
fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
||||||
pub fn subst(&self, substs: &Substs) -> FnSig {
|
for t in self.params_and_return.iter() {
|
||||||
let result: Vec<_> =
|
t.walk(f);
|
||||||
self.params_and_return.iter().map(|ty| ty.clone().subst(substs)).collect();
|
}
|
||||||
FnSig { params_and_return: result.into() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
||||||
// Without an Arc::make_mut_slice, we can't avoid the clone here:
|
// Without an Arc::make_mut_slice, we can't avoid the clone here:
|
||||||
let mut v: Vec<_> = self.params_and_return.iter().cloned().collect();
|
let mut v: Vec<_> = self.params_and_return.iter().cloned().collect();
|
||||||
for t in &mut v {
|
for t in &mut v {
|
||||||
|
@ -463,64 +449,6 @@ impl Ty {
|
||||||
Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty())
|
Ty::apply(TypeCtor::Tuple { cardinality: 0 }, Substs::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
|
||||||
match self {
|
|
||||||
Ty::Apply(a_ty) => {
|
|
||||||
for t in a_ty.parameters.iter() {
|
|
||||||
t.walk(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ty::Projection(p_ty) => {
|
|
||||||
for t in p_ty.parameters.iter() {
|
|
||||||
t.walk(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ty::UnselectedProjection(p_ty) => {
|
|
||||||
for t in p_ty.parameters.iter() {
|
|
||||||
t.walk(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
|
|
||||||
for p in predicates.iter() {
|
|
||||||
p.walk(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
|
|
||||||
}
|
|
||||||
f(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
|
||||||
match self {
|
|
||||||
Ty::Apply(a_ty) => {
|
|
||||||
a_ty.parameters.walk_mut(f);
|
|
||||||
}
|
|
||||||
Ty::Projection(p_ty) => {
|
|
||||||
p_ty.parameters.walk_mut(f);
|
|
||||||
}
|
|
||||||
Ty::UnselectedProjection(p_ty) => {
|
|
||||||
p_ty.parameters.walk_mut(f);
|
|
||||||
}
|
|
||||||
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
|
|
||||||
let mut v: Vec<_> = predicates.iter().cloned().collect();
|
|
||||||
for p in &mut v {
|
|
||||||
p.walk_mut(f);
|
|
||||||
}
|
|
||||||
*predicates = v.into();
|
|
||||||
}
|
|
||||||
Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
|
|
||||||
}
|
|
||||||
f(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Ty {
|
|
||||||
self.walk_mut(&mut |ty_mut| {
|
|
||||||
let ty = mem::replace(ty_mut, Ty::Unknown);
|
|
||||||
*ty_mut = f(ty);
|
|
||||||
});
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
|
pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
|
||||||
match self {
|
match self {
|
||||||
Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => {
|
Ty::Apply(ApplicationTy { ctor: TypeCtor::Ref(mutability), parameters }) => {
|
||||||
|
@ -596,26 +524,6 @@ impl Ty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces type parameters in this type using the given `Substs`. (So e.g.
|
|
||||||
/// if `self` is `&[T]`, where type parameter T has index 0, and the
|
|
||||||
/// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.)
|
|
||||||
pub fn subst(self, substs: &Substs) -> Ty {
|
|
||||||
self.fold(&mut |ty| match ty {
|
|
||||||
Ty::Param { idx, name } => {
|
|
||||||
substs.get(idx as usize).cloned().unwrap_or(Ty::Param { idx, name })
|
|
||||||
}
|
|
||||||
ty => ty,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Substitutes `Ty::Bound` vars (as opposed to type parameters).
|
|
||||||
pub fn subst_bound_vars(self, substs: &Substs) -> Ty {
|
|
||||||
self.fold(&mut |ty| match ty {
|
|
||||||
Ty::Bound(idx) => substs.get(idx as usize).cloned().unwrap_or_else(|| Ty::Bound(idx)),
|
|
||||||
ty => ty,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the type parameters of this type if it has some (i.e. is an ADT
|
/// Returns the type parameters of this type if it has some (i.e. is an ADT
|
||||||
/// or function); so if `self` is `Option<u32>`, this returns the `u32`.
|
/// or function); so if `self` is `Option<u32>`, this returns the `u32`.
|
||||||
pub fn substs(&self) -> Option<Substs> {
|
pub fn substs(&self) -> Option<Substs> {
|
||||||
|
@ -625,17 +533,6 @@ impl Ty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shifts up `Ty::Bound` vars by `n`.
|
|
||||||
pub fn shift_bound_vars(self, n: i32) -> Ty {
|
|
||||||
self.fold(&mut |ty| match ty {
|
|
||||||
Ty::Bound(idx) => {
|
|
||||||
assert!(idx as i32 >= -n);
|
|
||||||
Ty::Bound((idx as i32 + n) as u32)
|
|
||||||
}
|
|
||||||
ty => ty,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If this is an `impl Trait` or `dyn Trait`, returns that trait.
|
/// If this is an `impl Trait` or `dyn Trait`, returns that trait.
|
||||||
pub fn inherent_trait(&self) -> Option<Trait> {
|
pub fn inherent_trait(&self) -> Option<Trait> {
|
||||||
match self {
|
match self {
|
||||||
|
@ -650,6 +547,116 @@ impl Ty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This allows walking structures that contain types to do something with those
|
||||||
|
/// types, similar to Chalk's `Fold` trait.
|
||||||
|
pub trait TypeWalk {
|
||||||
|
fn walk(&self, f: &mut impl FnMut(&Ty));
|
||||||
|
fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty));
|
||||||
|
|
||||||
|
fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
self.walk_mut(&mut |ty_mut| {
|
||||||
|
let ty = mem::replace(ty_mut, Ty::Unknown);
|
||||||
|
*ty_mut = f(ty);
|
||||||
|
});
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replaces type parameters in this type using the given `Substs`. (So e.g.
|
||||||
|
/// if `self` is `&[T]`, where type parameter T has index 0, and the
|
||||||
|
/// `Substs` contain `u32` at index 0, we'll have `&[u32]` afterwards.)
|
||||||
|
fn subst(self, substs: &Substs) -> Self
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
self.fold(&mut |ty| match ty {
|
||||||
|
Ty::Param { idx, name } => {
|
||||||
|
substs.get(idx as usize).cloned().unwrap_or(Ty::Param { idx, name })
|
||||||
|
}
|
||||||
|
ty => ty,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Substitutes `Ty::Bound` vars (as opposed to type parameters).
|
||||||
|
fn subst_bound_vars(self, substs: &Substs) -> Self
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
self.fold(&mut |ty| match ty {
|
||||||
|
Ty::Bound(idx) => substs.get(idx as usize).cloned().unwrap_or_else(|| Ty::Bound(idx)),
|
||||||
|
ty => ty,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shifts up `Ty::Bound` vars by `n`.
|
||||||
|
fn shift_bound_vars(self, n: i32) -> Self
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
self.fold(&mut |ty| match ty {
|
||||||
|
Ty::Bound(idx) => {
|
||||||
|
assert!(idx as i32 >= -n);
|
||||||
|
Ty::Bound((idx as i32 + n) as u32)
|
||||||
|
}
|
||||||
|
ty => ty,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypeWalk for Ty {
|
||||||
|
fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
||||||
|
match self {
|
||||||
|
Ty::Apply(a_ty) => {
|
||||||
|
for t in a_ty.parameters.iter() {
|
||||||
|
t.walk(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ty::Projection(p_ty) => {
|
||||||
|
for t in p_ty.parameters.iter() {
|
||||||
|
t.walk(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ty::UnselectedProjection(p_ty) => {
|
||||||
|
for t in p_ty.parameters.iter() {
|
||||||
|
t.walk(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
|
||||||
|
for p in predicates.iter() {
|
||||||
|
p.walk(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
|
||||||
|
}
|
||||||
|
f(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
||||||
|
match self {
|
||||||
|
Ty::Apply(a_ty) => {
|
||||||
|
a_ty.parameters.walk_mut(f);
|
||||||
|
}
|
||||||
|
Ty::Projection(p_ty) => {
|
||||||
|
p_ty.parameters.walk_mut(f);
|
||||||
|
}
|
||||||
|
Ty::UnselectedProjection(p_ty) => {
|
||||||
|
p_ty.parameters.walk_mut(f);
|
||||||
|
}
|
||||||
|
Ty::Dyn(predicates) | Ty::Opaque(predicates) => {
|
||||||
|
let mut v: Vec<_> = predicates.iter().cloned().collect();
|
||||||
|
for p in &mut v {
|
||||||
|
p.walk_mut(f);
|
||||||
|
}
|
||||||
|
*predicates = v.into();
|
||||||
|
}
|
||||||
|
Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {}
|
||||||
|
}
|
||||||
|
f(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HirDisplay for &Ty {
|
impl HirDisplay for &Ty {
|
||||||
fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
|
fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
|
||||||
HirDisplay::hir_fmt(*self, f)
|
HirDisplay::hir_fmt(*self, f)
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::iter::successors;
|
||||||
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
|
|
||||||
use super::{traits::Solution, Canonical, Ty};
|
use super::{traits::Solution, Canonical, Ty, TypeWalk};
|
||||||
use crate::{HasGenericParams, HirDatabase, Name, Resolver};
|
use crate::{HasGenericParams, HirDatabase, Name, Resolver};
|
||||||
|
|
||||||
const AUTODEREF_RECURSION_LIMIT: usize = 10;
|
const AUTODEREF_RECURSION_LIMIT: usize = 10;
|
||||||
|
|
|
@ -30,7 +30,7 @@ use super::{
|
||||||
autoderef, lower, method_resolution, op, primitive,
|
autoderef, lower, method_resolution, op, primitive,
|
||||||
traits::{Guidance, Obligation, ProjectionPredicate, Solution},
|
traits::{Guidance, Obligation, ProjectionPredicate, Solution},
|
||||||
ApplicationTy, CallableDef, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef,
|
ApplicationTy, CallableDef, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef,
|
||||||
Ty, TypableDef, TypeCtor,
|
Ty, TypableDef, TypeCtor, TypeWalk,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
adt::VariantDef,
|
adt::VariantDef,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use super::{InferenceContext, Obligation};
|
use super::{InferenceContext, Obligation};
|
||||||
use crate::db::HirDatabase;
|
use crate::db::HirDatabase;
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty,
|
Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, TypeWalk,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
|
|
|
@ -10,6 +10,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
|
FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
|
||||||
|
TypeWalk,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
adt::VariantDef,
|
adt::VariantDef,
|
||||||
|
|
|
@ -8,7 +8,7 @@ use ra_db::salsa;
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
|
|
||||||
use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty};
|
use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
|
||||||
use crate::{db::HirDatabase, Crate, ImplBlock, Trait};
|
use crate::{db::HirDatabase, Crate, ImplBlock, Trait};
|
||||||
|
|
||||||
use self::chalk::{from_chalk, ToChalk};
|
use self::chalk::{from_chalk, ToChalk};
|
||||||
|
@ -138,25 +138,13 @@ pub struct ProjectionPredicate {
|
||||||
pub ty: Ty,
|
pub ty: Ty,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProjectionPredicate {
|
impl TypeWalk for ProjectionPredicate {
|
||||||
pub fn subst(mut self, substs: &super::Substs) -> ProjectionPredicate {
|
fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
||||||
self.walk_mut(&mut |ty| match ty {
|
|
||||||
Ty::Param { idx, .. } => {
|
|
||||||
if let Some(t) = substs.get(*idx as usize).cloned() {
|
|
||||||
*ty = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
});
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn walk(&self, f: &mut impl FnMut(&Ty)) {
|
|
||||||
self.projection_ty.walk(f);
|
self.projection_ty.walk(f);
|
||||||
self.ty.walk(f);
|
self.ty.walk(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
|
||||||
self.projection_ty.walk_mut(f);
|
self.projection_ty.walk_mut(f);
|
||||||
self.ty.walk_mut(f);
|
self.ty.walk_mut(f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ use crate::{
|
||||||
ty::display::HirDisplay,
|
ty::display::HirDisplay,
|
||||||
ty::{
|
ty::{
|
||||||
ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
|
ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
|
||||||
|
TypeWalk,
|
||||||
},
|
},
|
||||||
Crate, HasGenericParams, ImplBlock, ImplItem, Trait, TypeAlias,
|
Crate, HasGenericParams, ImplBlock, ImplItem, Trait, TypeAlias,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//! This modules takes care of rendering various defenitions as completion items.
|
//! This modules takes care of rendering various defenitions as completion items.
|
||||||
use hir::{Docs, HasSource, HirDisplay, PerNs, Resolution, Ty};
|
use hir::{Docs, HasSource, HirDisplay, PerNs, Resolution, Ty, TypeWalk};
|
||||||
use join_to_string::join;
|
use join_to_string::join;
|
||||||
use ra_syntax::ast::NameOwner;
|
use ra_syntax::ast::NameOwner;
|
||||||
use test_utils::tested_by;
|
use test_utils::tested_by;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue