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.rs45
-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, 85 insertions, 58 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 41c99d227..44547197c 100644
--- a/crates/ra_hir/src/ty/autoderef.rs
+++ b/crates/ra_hir/src/ty/autoderef.rs
@@ -5,42 +5,49 @@
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;
11 12
12use crate::{db::HirDatabase, Trait}; 13use crate::{db::HirDatabase, Trait};
13 14
14use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; 15use super::{
16 traits::{InEnvironment, Solution},
17 Canonical, Substs, Ty, TypeWalk,
18};
15 19
16const AUTODEREF_RECURSION_LIMIT: usize = 10; 20const AUTODEREF_RECURSION_LIMIT: usize = 10;
17 21
18pub(crate) fn autoderef<'a>( 22pub(crate) fn autoderef<'a>(
19 db: &'a impl HirDatabase, 23 db: &'a impl HirDatabase,
20 resolver: &'a Resolver, 24 krate: Option<CrateId>,
21 ty: Canonical<Ty>, 25 ty: InEnvironment<Canonical<Ty>>,
22) -> impl Iterator<Item = Canonical<Ty>> + 'a { 26) -> impl Iterator<Item = Canonical<Ty>> + 'a {
23 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)
24} 32}
25 33
26pub(crate) fn deref( 34pub(crate) fn deref(
27 db: &impl HirDatabase, 35 db: &impl HirDatabase,
28 resolver: &Resolver, 36 krate: CrateId,
29 ty: &Canonical<Ty>, 37 ty: InEnvironment<&Canonical<Ty>>,
30) -> Option<Canonical<Ty>> { 38) -> Option<Canonical<Ty>> {
31 if let Some(derefed) = ty.value.builtin_deref() { 39 if let Some(derefed) = ty.value.value.builtin_deref() {
32 Some(Canonical { value: derefed, num_vars: ty.num_vars }) 40 Some(Canonical { value: derefed, num_vars: ty.value.num_vars })
33 } else { 41 } else {
34 deref_by_trait(db, resolver, ty) 42 deref_by_trait(db, krate, ty)
35 } 43 }
36} 44}
37 45
38fn deref_by_trait( 46fn deref_by_trait(
39 db: &impl HirDatabase, 47 db: &impl HirDatabase,
40 resolver: &Resolver, 48 krate: CrateId,
41 ty: &Canonical<Ty>, 49 ty: InEnvironment<&Canonical<Ty>>,
42) -> Option<Canonical<Ty>> { 50) -> Option<Canonical<Ty>> {
43 let krate = resolver.krate()?;
44 let deref_trait = match db.lang_item(krate.into(), "deref".into())? { 51 let deref_trait = match db.lang_item(krate.into(), "deref".into())? {
45 LangItemTarget::TraitId(t) => Trait::from(t), 52 LangItemTarget::TraitId(t) => Trait::from(t),
46 _ => return None, 53 _ => return None,
@@ -56,10 +63,8 @@ fn deref_by_trait(
56 63
57 // FIXME make the Canonical handling nicer 64 // FIXME make the Canonical handling nicer
58 65
59 let env = super::lower::trait_env(db, resolver);
60
61 let parameters = Substs::build_for_generics(&generic_params) 66 let parameters = Substs::build_for_generics(&generic_params)
62 .push(ty.value.clone().shift_bound_vars(1)) 67 .push(ty.value.value.clone().shift_bound_vars(1))
63 .build(); 68 .build();
64 69
65 let projection = super::traits::ProjectionPredicate { 70 let projection = super::traits::ProjectionPredicate {
@@ -69,9 +74,9 @@ fn deref_by_trait(
69 74
70 let obligation = super::Obligation::Projection(projection); 75 let obligation = super::Obligation::Projection(projection);
71 76
72 let in_env = super::traits::InEnvironment { value: obligation, environment: env }; 77 let in_env = InEnvironment { value: obligation, environment: ty.environment };
73 78
74 let canonical = super::Canonical { num_vars: 1 + ty.num_vars, value: in_env }; 79 let canonical = super::Canonical { num_vars: 1 + ty.value.num_vars, value: in_env };
75 80
76 let solution = db.trait_solve(krate.into(), canonical)?; 81 let solution = db.trait_solve(krate.into(), canonical)?;
77 82
@@ -89,14 +94,14 @@ fn deref_by_trait(
89 // the case. 94 // the case.
90 for i in 1..vars.0.num_vars { 95 for i in 1..vars.0.num_vars {
91 if vars.0.value[i] != Ty::Bound((i - 1) as u32) { 96 if vars.0.value[i] != Ty::Bound((i - 1) as u32) {
92 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty, solution); 97 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution);
93 return None; 98 return None;
94 } 99 }
95 } 100 }
96 Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars }) 101 Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars })
97 } 102 }
98 Solution::Ambig(_) => { 103 Solution::Ambig(_) => {
99 info!("Ambiguous solution for derefing {:?}: {:?}", ty, solution); 104 info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution);
100 None 105 None
101 } 106 }
102 } 107 }
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