mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Remove Resolver from autoderef
Resolver holds onto too much context, including local scopes. Let's try to pass in only what is necessary -- the trait environment.
This commit is contained in:
parent
bd53bd80bf
commit
8c3e372835
@ -26,7 +26,10 @@ use ra_syntax::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
expr::{BodySourceMap, ExprScopes, ScopeId},
|
expr::{BodySourceMap, ExprScopes, ScopeId},
|
||||||
ty::method_resolution::{self, implements_trait},
|
ty::{
|
||||||
|
method_resolution::{self, implements_trait},
|
||||||
|
TraitEnvironment,
|
||||||
|
},
|
||||||
Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function,
|
Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function,
|
||||||
GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Ty, TypeAlias,
|
GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Ty, TypeAlias,
|
||||||
};
|
};
|
||||||
@ -408,7 +411,10 @@ impl SourceAnalyzer {
|
|||||||
// There should be no inference vars in types passed here
|
// There should be no inference vars in types passed here
|
||||||
// FIXME check that?
|
// FIXME check that?
|
||||||
let canonical = crate::ty::Canonical { value: ty, num_vars: 0 };
|
let canonical = crate::ty::Canonical { value: ty, num_vars: 0 };
|
||||||
crate::ty::autoderef(db, &self.resolver, canonical).map(|canonical| canonical.value)
|
let krate = self.resolver.krate();
|
||||||
|
let environment = TraitEnvironment::lower(db, &self.resolver);
|
||||||
|
let ty = crate::ty::InEnvironment { value: canonical, environment };
|
||||||
|
crate::ty::autoderef(db, krate, ty).map(|canonical| canonical.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks that particular type `ty` implements `std::future::Future`.
|
/// Checks that particular type `ty` implements `std::future::Future`.
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
use std::iter::successors;
|
use std::iter::successors;
|
||||||
|
|
||||||
use hir_def::{lang_item::LangItemTarget, resolver::Resolver};
|
use hir_def::lang_item::LangItemTarget;
|
||||||
use hir_expand::name;
|
use hir_expand::name;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use ra_db::CrateId;
|
use ra_db::CrateId;
|
||||||
@ -21,23 +21,25 @@ const AUTODEREF_RECURSION_LIMIT: usize = 10;
|
|||||||
|
|
||||||
pub(crate) fn autoderef<'a>(
|
pub(crate) fn autoderef<'a>(
|
||||||
db: &'a impl HirDatabase,
|
db: &'a impl HirDatabase,
|
||||||
resolver: &'a Resolver,
|
krate: Option<CrateId>,
|
||||||
ty: Canonical<Ty>,
|
ty: InEnvironment<Canonical<Ty>>,
|
||||||
) -> impl Iterator<Item = Canonical<Ty>> + 'a {
|
) -> impl Iterator<Item = Canonical<Ty>> + 'a {
|
||||||
successors(Some(ty), move |ty| deref(db, resolver, ty)).take(AUTODEREF_RECURSION_LIMIT)
|
let InEnvironment { value: ty, environment } = ty;
|
||||||
|
successors(Some(ty), move |ty| {
|
||||||
|
deref(db, krate?, InEnvironment { value: ty, environment: environment.clone() })
|
||||||
|
})
|
||||||
|
.take(AUTODEREF_RECURSION_LIMIT)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn deref(
|
pub(crate) fn deref(
|
||||||
db: &impl HirDatabase,
|
db: &impl HirDatabase,
|
||||||
resolver: &Resolver,
|
krate: CrateId,
|
||||||
ty: &Canonical<Ty>,
|
ty: InEnvironment<&Canonical<Ty>>,
|
||||||
) -> Option<Canonical<Ty>> {
|
) -> Option<Canonical<Ty>> {
|
||||||
if let Some(derefed) = ty.value.builtin_deref() {
|
if let Some(derefed) = ty.value.value.builtin_deref() {
|
||||||
Some(Canonical { value: derefed, num_vars: ty.num_vars })
|
Some(Canonical { value: derefed, num_vars: ty.value.num_vars })
|
||||||
} else {
|
} else {
|
||||||
let krate = resolver.krate()?;
|
deref_by_trait(db, krate, ty)
|
||||||
let environment = super::lower::trait_env(db, resolver);
|
|
||||||
deref_by_trait(db, krate, InEnvironment { value: ty, environment })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,6 @@ use ra_prof::profile;
|
|||||||
use test_utils::tested_by;
|
use test_utils::tested_by;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
lower,
|
|
||||||
traits::{Guidance, Obligation, ProjectionPredicate, Solution},
|
traits::{Guidance, Obligation, ProjectionPredicate, Solution},
|
||||||
ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypableDef,
|
ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypableDef,
|
||||||
TypeCtor, TypeWalk, Uncertain,
|
TypeCtor, TypeWalk, Uncertain,
|
||||||
@ -216,7 +215,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||||||
var_unification_table: InPlaceUnificationTable::new(),
|
var_unification_table: InPlaceUnificationTable::new(),
|
||||||
obligations: Vec::default(),
|
obligations: Vec::default(),
|
||||||
return_ty: Ty::Unknown, // set in collect_fn_signature
|
return_ty: Ty::Unknown, // set in collect_fn_signature
|
||||||
trait_env: lower::trait_env(db, &resolver),
|
trait_env: TraitEnvironment::lower(db, &resolver),
|
||||||
coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver),
|
coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver),
|
||||||
db,
|
db,
|
||||||
owner,
|
owner,
|
||||||
|
@ -14,7 +14,7 @@ use crate::{
|
|||||||
Adt, Mutability,
|
Adt, Mutability,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{InferTy, InferenceContext, TypeVarValue};
|
use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue};
|
||||||
|
|
||||||
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
/// Unify two types, but may coerce the first one to the second one
|
/// Unify two types, but may coerce the first one to the second one
|
||||||
@ -320,9 +320,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||||||
let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone());
|
let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone());
|
||||||
let to_ty = self.resolve_ty_shallow(&to_ty);
|
let to_ty = self.resolve_ty_shallow(&to_ty);
|
||||||
// FIXME: Auto DerefMut
|
// FIXME: Auto DerefMut
|
||||||
for derefed_ty in
|
for derefed_ty in autoderef::autoderef(
|
||||||
autoderef::autoderef(self.db, &self.resolver.clone(), canonicalized.value.clone())
|
self.db,
|
||||||
{
|
self.resolver.krate(),
|
||||||
|
InEnvironment {
|
||||||
|
value: canonicalized.value.clone(),
|
||||||
|
environment: self.trait_env.clone(),
|
||||||
|
},
|
||||||
|
) {
|
||||||
let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value);
|
let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value);
|
||||||
match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) {
|
match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) {
|
||||||
// Stop when constructor matches.
|
// Stop when constructor matches.
|
||||||
|
@ -15,9 +15,9 @@ use crate::{
|
|||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
|
expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
|
||||||
ty::{
|
ty::{
|
||||||
autoderef, method_resolution, op, CallableDef, InferTy, IntTy, Mutability, Namespace,
|
autoderef, method_resolution, op, traits::InEnvironment, CallableDef, InferTy, IntTy,
|
||||||
Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk,
|
Mutability, Namespace, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty,
|
||||||
Uncertain,
|
TypeCtor, TypeWalk, Uncertain,
|
||||||
},
|
},
|
||||||
Adt, Name,
|
Adt, Name,
|
||||||
};
|
};
|
||||||
@ -245,8 +245,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||||||
let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty);
|
let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty);
|
||||||
let ty = autoderef::autoderef(
|
let ty = autoderef::autoderef(
|
||||||
self.db,
|
self.db,
|
||||||
&self.resolver.clone(),
|
self.resolver.krate(),
|
||||||
canonicalized.value.clone(),
|
InEnvironment {
|
||||||
|
value: canonicalized.value.clone(),
|
||||||
|
environment: self.trait_env.clone(),
|
||||||
|
},
|
||||||
)
|
)
|
||||||
.find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) {
|
.find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) {
|
||||||
Ty::Apply(a_ty) => match a_ty.ctor {
|
Ty::Apply(a_ty) => match a_ty.ctor {
|
||||||
@ -337,16 +340,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||||||
Expr::UnaryOp { expr, op } => {
|
Expr::UnaryOp { expr, op } => {
|
||||||
let inner_ty = self.infer_expr(*expr, &Expectation::none());
|
let inner_ty = self.infer_expr(*expr, &Expectation::none());
|
||||||
match op {
|
match op {
|
||||||
UnaryOp::Deref => {
|
UnaryOp::Deref => match self.resolver.krate() {
|
||||||
let canonicalized = self.canonicalizer().canonicalize_ty(inner_ty);
|
Some(krate) => {
|
||||||
if let Some(derefed_ty) =
|
let canonicalized = self.canonicalizer().canonicalize_ty(inner_ty);
|
||||||
autoderef::deref(self.db, &self.resolver, &canonicalized.value)
|
match autoderef::deref(
|
||||||
{
|
self.db,
|
||||||
canonicalized.decanonicalize_ty(derefed_ty.value)
|
krate,
|
||||||
} else {
|
InEnvironment {
|
||||||
Ty::Unknown
|
value: &canonicalized.value,
|
||||||
|
environment: self.trait_env.clone(),
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Some(derefed_ty) => {
|
||||||
|
canonicalized.decanonicalize_ty(derefed_ty.value)
|
||||||
|
}
|
||||||
|
None => Ty::Unknown,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
None => Ty::Unknown,
|
||||||
|
},
|
||||||
UnaryOp::Neg => {
|
UnaryOp::Neg => {
|
||||||
match &inner_ty {
|
match &inner_ty {
|
||||||
Ty::Apply(a_ty) => match a_ty.ctor {
|
Ty::Apply(a_ty) => match a_ty.ctor {
|
||||||
|
@ -19,8 +19,8 @@ use hir_def::{
|
|||||||
use ra_arena::map::ArenaMap;
|
use ra_arena::map::ArenaMap;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
|
FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef,
|
||||||
TypeWalk,
|
Ty, TypeCtor, TypeWalk,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
@ -591,16 +591,15 @@ pub(crate) fn generic_predicates_for_param_query(
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn trait_env(
|
impl TraitEnvironment {
|
||||||
db: &impl HirDatabase,
|
pub(crate) fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> {
|
||||||
resolver: &Resolver,
|
let predicates = resolver
|
||||||
) -> Arc<super::TraitEnvironment> {
|
.where_predicates_in_scope()
|
||||||
let predicates = resolver
|
.flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred))
|
||||||
.where_predicates_in_scope()
|
.collect::<Vec<_>>();
|
||||||
.flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
Arc::new(super::TraitEnvironment { predicates })
|
Arc::new(TraitEnvironment { predicates })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve the where clause(s) of an item with generics.
|
/// Resolve the where clause(s) of an item with generics.
|
||||||
|
@ -15,7 +15,7 @@ use crate::{
|
|||||||
AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait,
|
AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef};
|
use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef};
|
||||||
|
|
||||||
/// This is used as a key for indexing impls.
|
/// This is used as a key for indexing impls.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
@ -179,8 +179,9 @@ pub(crate) fn iterate_method_candidates<T>(
|
|||||||
// Also note that when we've got a receiver like &S, even if the method we
|
// Also note that when we've got a receiver like &S, even if the method we
|
||||||
// find in the end takes &self, we still do the autoderef step (just as
|
// find in the end takes &self, we still do the autoderef step (just as
|
||||||
// rustc does an autoderef and then autoref again).
|
// rustc does an autoderef and then autoref again).
|
||||||
|
let environment = TraitEnvironment::lower(db, resolver);
|
||||||
for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) {
|
let ty = InEnvironment { value: ty.clone(), environment };
|
||||||
|
for derefed_ty in autoderef::autoderef(db, resolver.krate(), ty) {
|
||||||
if let Some(result) = iterate_inherent_methods(
|
if let Some(result) = iterate_inherent_methods(
|
||||||
&derefed_ty,
|
&derefed_ty,
|
||||||
db,
|
db,
|
||||||
@ -230,7 +231,7 @@ fn iterate_trait_method_candidates<T>(
|
|||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
let krate = resolver.krate()?;
|
let krate = resolver.krate()?;
|
||||||
// FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
|
// FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
|
||||||
let env = lower::trait_env(db, resolver);
|
let env = TraitEnvironment::lower(db, resolver);
|
||||||
// if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
|
// if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope
|
||||||
let inherent_trait = ty.value.inherent_trait().into_iter();
|
let inherent_trait = ty.value.inherent_trait().into_iter();
|
||||||
// if we have `T: Trait` in the param env, the trait doesn't need to be in scope
|
// if we have `T: Trait` in the param env, the trait doesn't need to be in scope
|
||||||
@ -324,7 +325,7 @@ pub(crate) fn implements_trait(
|
|||||||
// anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
|
// anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
let env = lower::trait_env(db, resolver);
|
let env = TraitEnvironment::lower(db, resolver);
|
||||||
let goal = generic_implements_goal(db, env, trait_, ty.clone());
|
let goal = generic_implements_goal(db, env, trait_, ty.clone());
|
||||||
let solution = db.trait_solve(krate, goal);
|
let solution = db.trait_solve(krate, goal);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user