aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/source_binder.rs10
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs24
-rw-r--r--crates/ra_hir/src/ty/infer.rs3
-rw-r--r--crates/ra_hir/src/ty/infer/coerce.rs13
-rw-r--r--crates/ra_hir/src/ty/infer/expr.rs40
-rw-r--r--crates/ra_hir/src/ty/lower.rs21
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs11
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::{
26use crate::{ 26use 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
6use std::iter::successors; 6use std::iter::successors;
7 7
8use hir_def::{lang_item::LangItemTarget, resolver::Resolver}; 8use hir_def::lang_item::LangItemTarget;
9use hir_expand::name; 9use hir_expand::name;
10use log::{info, warn}; 10use log::{info, warn};
11use ra_db::CrateId; 11use ra_db::CrateId;
@@ -21,23 +21,25 @@ const AUTODEREF_RECURSION_LIMIT: usize = 10;
21 21
22pub(crate) fn autoderef<'a>( 22pub(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
30pub(crate) fn deref( 34pub(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;
34use test_utils::tested_by; 34use test_utils::tested_by;
35 35
36use super::{ 36use 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
17use super::{InferTy, InferenceContext, TypeVarValue}; 17use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue};
18 18
19impl<'a, D: HirDatabase> InferenceContext<'a, D> { 19impl<'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::{
19use ra_arena::map::ArenaMap; 19use ra_arena::map::ArenaMap;
20 20
21use super::{ 21use 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};
25use crate::{ 25use 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
594pub(crate) fn trait_env( 594impl 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
18use super::{autoderef, lower, Canonical, InEnvironment, TraitEnvironment, TraitRef}; 18use 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