diff options
author | Aleksey Kladov <[email protected]> | 2019-11-25 10:10:26 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-11-25 10:10:26 +0000 |
commit | 8c3e372835243c922b0eff7ca23f79f227991e88 (patch) | |
tree | 5dda185ddeba593b7af36f66eeb6098e4f913c05 /crates | |
parent | bd53bd80bff9a1f320615a975235399b1fa4792e (diff) |
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.
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/autoderef.rs | 24 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/coerce.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/expr.rs | 40 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 21 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 11 |
7 files changed, 73 insertions, 49 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 31390bb7f..b4f0e81d3 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -26,7 +26,10 @@ use ra_syntax::{ | |||
26 | use crate::{ | 26 | use crate::{ |
27 | db::HirDatabase, | 27 | db::HirDatabase, |
28 | expr::{BodySourceMap, ExprScopes, ScopeId}, | 28 | expr::{BodySourceMap, ExprScopes, ScopeId}, |
29 | ty::method_resolution::{self, implements_trait}, | 29 | ty::{ |
30 | method_resolution::{self, implements_trait}, | ||
31 | TraitEnvironment, | ||
32 | }, | ||
30 | Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, | 33 | Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, |
31 | GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Ty, TypeAlias, | 34 | GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Ty, TypeAlias, |
32 | }; | 35 | }; |
@@ -408,7 +411,10 @@ impl SourceAnalyzer { | |||
408 | // There should be no inference vars in types passed here | 411 | // There should be no inference vars in types passed here |
409 | // FIXME check that? | 412 | // FIXME check that? |
410 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; | 413 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; |
411 | crate::ty::autoderef(db, &self.resolver, canonical).map(|canonical| canonical.value) | 414 | let krate = self.resolver.krate(); |
415 | let environment = TraitEnvironment::lower(db, &self.resolver); | ||
416 | let ty = crate::ty::InEnvironment { value: canonical, environment }; | ||
417 | crate::ty::autoderef(db, krate, ty).map(|canonical| canonical.value) | ||
412 | } | 418 | } |
413 | 419 | ||
414 | /// Checks that particular type `ty` implements `std::future::Future`. | 420 | /// Checks that particular type `ty` implements `std::future::Future`. |
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index 86b08ae6f..44547197c 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | 5 | ||
6 | use std::iter::successors; | 6 | use std::iter::successors; |
7 | 7 | ||
8 | use hir_def::{lang_item::LangItemTarget, resolver::Resolver}; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | use hir_expand::name; | 9 | use hir_expand::name; |
10 | use log::{info, warn}; | 10 | use log::{info, warn}; |
11 | use ra_db::CrateId; | 11 | use ra_db::CrateId; |
@@ -21,23 +21,25 @@ const AUTODEREF_RECURSION_LIMIT: usize = 10; | |||
21 | 21 | ||
22 | pub(crate) fn autoderef<'a>( | 22 | pub(crate) fn autoderef<'a>( |
23 | db: &'a impl HirDatabase, | 23 | db: &'a impl HirDatabase, |
24 | resolver: &'a Resolver, | 24 | krate: Option<CrateId>, |
25 | ty: Canonical<Ty>, | 25 | ty: InEnvironment<Canonical<Ty>>, |
26 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { | 26 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { |
27 | successors(Some(ty), move |ty| deref(db, resolver, ty)).take(AUTODEREF_RECURSION_LIMIT) | 27 | let InEnvironment { value: ty, environment } = ty; |
28 | successors(Some(ty), move |ty| { | ||
29 | deref(db, krate?, InEnvironment { value: ty, environment: environment.clone() }) | ||
30 | }) | ||
31 | .take(AUTODEREF_RECURSION_LIMIT) | ||
28 | } | 32 | } |
29 | 33 | ||
30 | pub(crate) fn deref( | 34 | pub(crate) fn deref( |
31 | db: &impl HirDatabase, | 35 | db: &impl HirDatabase, |
32 | resolver: &Resolver, | 36 | krate: CrateId, |
33 | ty: &Canonical<Ty>, | 37 | ty: InEnvironment<&Canonical<Ty>>, |
34 | ) -> Option<Canonical<Ty>> { | 38 | ) -> Option<Canonical<Ty>> { |
35 | if let Some(derefed) = ty.value.builtin_deref() { | 39 | if let Some(derefed) = ty.value.value.builtin_deref() { |
36 | Some(Canonical { value: derefed, num_vars: ty.num_vars }) | 40 | Some(Canonical { value: derefed, num_vars: ty.value.num_vars }) |
37 | } else { | 41 | } else { |
38 | let krate = resolver.krate()?; | 42 | deref_by_trait(db, krate, ty) |
39 | let environment = super::lower::trait_env(db, resolver); | ||
40 | deref_by_trait(db, krate, InEnvironment { value: ty, environment }) | ||
41 | } | 43 | } |
42 | } | 44 | } |
43 | 45 | ||
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index ddc7d262a..6fd00d457 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -34,7 +34,6 @@ use ra_prof::profile; | |||
34 | use test_utils::tested_by; | 34 | use test_utils::tested_by; |
35 | 35 | ||
36 | use super::{ | 36 | use super::{ |
37 | lower, | ||
38 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, | 37 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, |
39 | ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypableDef, | 38 | ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypableDef, |
40 | TypeCtor, TypeWalk, Uncertain, | 39 | TypeCtor, TypeWalk, Uncertain, |
@@ -216,7 +215,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
216 | var_unification_table: InPlaceUnificationTable::new(), | 215 | var_unification_table: InPlaceUnificationTable::new(), |
217 | obligations: Vec::default(), | 216 | obligations: Vec::default(), |
218 | return_ty: Ty::Unknown, // set in collect_fn_signature | 217 | return_ty: Ty::Unknown, // set in collect_fn_signature |
219 | trait_env: lower::trait_env(db, &resolver), | 218 | trait_env: TraitEnvironment::lower(db, &resolver), |
220 | coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver), | 219 | coerce_unsized_map: Self::init_coerce_unsized_map(db, &resolver), |
221 | db, | 220 | db, |
222 | owner, | 221 | owner, |
diff --git a/crates/ra_hir/src/ty/infer/coerce.rs b/crates/ra_hir/src/ty/infer/coerce.rs index 54765da35..4b53bba73 100644 --- a/crates/ra_hir/src/ty/infer/coerce.rs +++ b/crates/ra_hir/src/ty/infer/coerce.rs | |||
@@ -14,7 +14,7 @@ use crate::{ | |||
14 | Adt, Mutability, | 14 | Adt, Mutability, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | use super::{InferTy, InferenceContext, TypeVarValue}; | 17 | use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; |
18 | 18 | ||
19 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 19 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
20 | /// Unify two types, but may coerce the first one to the second one | 20 | /// Unify two types, but may coerce the first one to the second one |
@@ -320,9 +320,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
320 | let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone()); | 320 | let canonicalized = self.canonicalizer().canonicalize_ty(from_ty.clone()); |
321 | let to_ty = self.resolve_ty_shallow(&to_ty); | 321 | let to_ty = self.resolve_ty_shallow(&to_ty); |
322 | // FIXME: Auto DerefMut | 322 | // FIXME: Auto DerefMut |
323 | for derefed_ty in | 323 | for derefed_ty in autoderef::autoderef( |
324 | autoderef::autoderef(self.db, &self.resolver.clone(), canonicalized.value.clone()) | 324 | self.db, |
325 | { | 325 | self.resolver.krate(), |
326 | InEnvironment { | ||
327 | value: canonicalized.value.clone(), | ||
328 | environment: self.trait_env.clone(), | ||
329 | }, | ||
330 | ) { | ||
326 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); | 331 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); |
327 | match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { | 332 | match (&*self.resolve_ty_shallow(&derefed_ty), &*to_ty) { |
328 | // Stop when constructor matches. | 333 | // Stop when constructor matches. |
diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs index 663ff9435..194e55819 100644 --- a/crates/ra_hir/src/ty/infer/expr.rs +++ b/crates/ra_hir/src/ty/infer/expr.rs | |||
@@ -15,9 +15,9 @@ use crate::{ | |||
15 | db::HirDatabase, | 15 | db::HirDatabase, |
16 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, | 16 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, |
17 | ty::{ | 17 | ty::{ |
18 | autoderef, method_resolution, op, CallableDef, InferTy, IntTy, Mutability, Namespace, | 18 | autoderef, method_resolution, op, traits::InEnvironment, CallableDef, InferTy, IntTy, |
19 | Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, | 19 | Mutability, Namespace, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, |
20 | Uncertain, | 20 | TypeCtor, TypeWalk, Uncertain, |
21 | }, | 21 | }, |
22 | Adt, Name, | 22 | Adt, Name, |
23 | }; | 23 | }; |
@@ -245,8 +245,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
245 | let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); | 245 | let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); |
246 | let ty = autoderef::autoderef( | 246 | let ty = autoderef::autoderef( |
247 | self.db, | 247 | self.db, |
248 | &self.resolver.clone(), | 248 | self.resolver.krate(), |
249 | canonicalized.value.clone(), | 249 | InEnvironment { |
250 | value: canonicalized.value.clone(), | ||
251 | environment: self.trait_env.clone(), | ||
252 | }, | ||
250 | ) | 253 | ) |
251 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { | 254 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { |
252 | Ty::Apply(a_ty) => match a_ty.ctor { | 255 | Ty::Apply(a_ty) => match a_ty.ctor { |
@@ -337,16 +340,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
337 | Expr::UnaryOp { expr, op } => { | 340 | Expr::UnaryOp { expr, op } => { |
338 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | 341 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); |
339 | match op { | 342 | match op { |
340 | UnaryOp::Deref => { | 343 | UnaryOp::Deref => match self.resolver.krate() { |
341 | let canonicalized = self.canonicalizer().canonicalize_ty(inner_ty); | 344 | Some(krate) => { |
342 | if let Some(derefed_ty) = | 345 | let canonicalized = self.canonicalizer().canonicalize_ty(inner_ty); |
343 | autoderef::deref(self.db, &self.resolver, &canonicalized.value) | 346 | match autoderef::deref( |
344 | { | 347 | self.db, |
345 | canonicalized.decanonicalize_ty(derefed_ty.value) | 348 | krate, |
346 | } else { | 349 | InEnvironment { |
347 | Ty::Unknown | 350 | value: &canonicalized.value, |
351 | environment: self.trait_env.clone(), | ||
352 | }, | ||
353 | ) { | ||
354 | Some(derefed_ty) => { | ||
355 | canonicalized.decanonicalize_ty(derefed_ty.value) | ||
356 | } | ||
357 | None => Ty::Unknown, | ||
358 | } | ||
348 | } | 359 | } |
349 | } | 360 | None => Ty::Unknown, |
361 | }, | ||
350 | UnaryOp::Neg => { | 362 | UnaryOp::Neg => { |
351 | match &inner_ty { | 363 | match &inner_ty { |
352 | Ty::Apply(a_ty) => match a_ty.ctor { | 364 | Ty::Apply(a_ty) => match a_ty.ctor { |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index a39beb2a0..b76929501 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -19,8 +19,8 @@ use hir_def::{ | |||
19 | use ra_arena::map::ArenaMap; | 19 | use ra_arena::map::ArenaMap; |
20 | 20 | ||
21 | use super::{ | 21 | use super::{ |
22 | FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 22 | FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, |
23 | TypeWalk, | 23 | Ty, TypeCtor, TypeWalk, |
24 | }; | 24 | }; |
25 | use crate::{ | 25 | use crate::{ |
26 | db::HirDatabase, | 26 | db::HirDatabase, |
@@ -591,16 +591,15 @@ pub(crate) fn generic_predicates_for_param_query( | |||
591 | .collect() | 591 | .collect() |
592 | } | 592 | } |
593 | 593 | ||
594 | pub(crate) fn trait_env( | 594 | impl TraitEnvironment { |
595 | db: &impl HirDatabase, | 595 | pub(crate) fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { |
596 | resolver: &Resolver, | 596 | let predicates = resolver |
597 | ) -> Arc<super::TraitEnvironment> { | 597 | .where_predicates_in_scope() |
598 | let predicates = resolver | 598 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) |
599 | .where_predicates_in_scope() | 599 | .collect::<Vec<_>>(); |
600 | .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) | ||
601 | .collect::<Vec<_>>(); | ||
602 | 600 | ||
603 | Arc::new(super::TraitEnvironment { predicates }) | 601 | Arc::new(TraitEnvironment { predicates }) |
602 | } | ||
604 | } | 603 | } |
605 | 604 | ||
606 | /// Resolve the where clause(s) of an item with generics. | 605 | /// Resolve the where clause(s) of an item with generics. |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index caa5f5f74..f7905b5ff 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -15,7 +15,7 @@ use crate::{ | |||
15 | AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait, | 15 | AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; | 18 | use super::{autoderef, Canonical, InEnvironment, TraitEnvironment, TraitRef}; |
19 | 19 | ||
20 | /// This is used as a key for indexing impls. | 20 | /// This is used as a key for indexing impls. |
21 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 21 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
@@ -179,8 +179,9 @@ pub(crate) fn iterate_method_candidates<T>( | |||
179 | // Also note that when we've got a receiver like &S, even if the method we | 179 | // Also note that when we've got a receiver like &S, even if the method we |
180 | // find in the end takes &self, we still do the autoderef step (just as | 180 | // find in the end takes &self, we still do the autoderef step (just as |
181 | // rustc does an autoderef and then autoref again). | 181 | // rustc does an autoderef and then autoref again). |
182 | 182 | let environment = TraitEnvironment::lower(db, resolver); | |
183 | for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) { | 183 | let ty = InEnvironment { value: ty.clone(), environment }; |
184 | for derefed_ty in autoderef::autoderef(db, resolver.krate(), ty) { | ||
184 | if let Some(result) = iterate_inherent_methods( | 185 | if let Some(result) = iterate_inherent_methods( |
185 | &derefed_ty, | 186 | &derefed_ty, |
186 | db, | 187 | db, |
@@ -230,7 +231,7 @@ fn iterate_trait_method_candidates<T>( | |||
230 | ) -> Option<T> { | 231 | ) -> Option<T> { |
231 | let krate = resolver.krate()?; | 232 | let krate = resolver.krate()?; |
232 | // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) | 233 | // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) |
233 | let env = lower::trait_env(db, resolver); | 234 | let env = TraitEnvironment::lower(db, resolver); |
234 | // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope | 235 | // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope |
235 | let inherent_trait = ty.value.inherent_trait().into_iter(); | 236 | let inherent_trait = ty.value.inherent_trait().into_iter(); |
236 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope | 237 | // 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( | |||
324 | // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet | 325 | // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet |
325 | return true; | 326 | return true; |
326 | } | 327 | } |
327 | let env = lower::trait_env(db, resolver); | 328 | let env = TraitEnvironment::lower(db, resolver); |
328 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); | 329 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); |
329 | let solution = db.trait_solve(krate, goal); | 330 | let solution = db.trait_solve(krate, goal); |
330 | 331 | ||