aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-06-29 18:14:52 +0100
committerFlorian Diebold <[email protected]>2019-07-08 20:20:17 +0100
commitb1b12072eddaf989fb08ed7a2e39ec2dbbb83dde (patch)
tree63bb052a39df80dcd0771a18a7a475df3e6a5fe1 /crates/ra_hir/src/ty
parent638100dc8bea69cc4093d15f1641ed39a8d27a43 (diff)
Start handling environment in trait resolution
I.e. if we are inside a function with some where clauses, we assume these where clauses hold.
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/infer.rs11
-rw-r--r--crates/ra_hir/src/ty/lower.rs12
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs7
-rw-r--r--crates/ra_hir/src/ty/tests.rs60
-rw-r--r--crates/ra_hir/src/ty/traits.rs8
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs19
6 files changed, 103 insertions, 14 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 84edd3d46..f8839ebd2 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -27,10 +27,10 @@ use ra_prof::profile;
27use test_utils::tested_by; 27use test_utils::tested_by;
28 28
29use super::{ 29use super::{
30 autoderef, method_resolution, op, primitive, 30 autoderef, lower, method_resolution, op, primitive,
31 traits::{Guidance, Obligation, ProjectionPredicate, Solution}, 31 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
32 ApplicationTy, CallableDef, InEnvironment, ProjectionTy, Substs, TraitRef, Ty, TypableDef, 32 ApplicationTy, CallableDef, Environment, InEnvironment, ProjectionTy, Substs, TraitRef, Ty,
33 TypeCtor, 33 TypableDef, TypeCtor,
34}; 34};
35use crate::{ 35use crate::{
36 adt::VariantDef, 36 adt::VariantDef,
@@ -166,6 +166,7 @@ struct InferenceContext<'a, D: HirDatabase> {
166 body: Arc<Body>, 166 body: Arc<Body>,
167 resolver: Resolver, 167 resolver: Resolver,
168 var_unification_table: InPlaceUnificationTable<TypeVarId>, 168 var_unification_table: InPlaceUnificationTable<TypeVarId>,
169 trait_env: Arc<Environment>,
169 obligations: Vec<Obligation>, 170 obligations: Vec<Obligation>,
170 method_resolutions: FxHashMap<ExprId, Function>, 171 method_resolutions: FxHashMap<ExprId, Function>,
171 field_resolutions: FxHashMap<ExprId, StructField>, 172 field_resolutions: FxHashMap<ExprId, StructField>,
@@ -189,6 +190,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
189 var_unification_table: InPlaceUnificationTable::new(), 190 var_unification_table: InPlaceUnificationTable::new(),
190 obligations: Vec::default(), 191 obligations: Vec::default(),
191 return_ty: Ty::Unknown, // set in collect_fn_signature 192 return_ty: Ty::Unknown, // set in collect_fn_signature
193 trait_env: lower::trait_env(db, &resolver),
192 db, 194 db,
193 body, 195 body,
194 resolver, 196 resolver,
@@ -331,8 +333,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
331 for obligation in obligations { 333 for obligation in obligations {
332 match &obligation { 334 match &obligation {
333 Obligation::Trait(tr) => { 335 Obligation::Trait(tr) => {
334 let env = Arc::new(super::Environment); // FIXME add environment 336 let in_env = InEnvironment::new(self.trait_env.clone(), tr.clone());
335 let in_env = InEnvironment::new(env, tr.clone());
336 let canonicalized = self.canonicalizer().canonicalize_trait_ref(in_env); 337 let canonicalized = self.canonicalizer().canonicalize_trait_ref(in_env);
337 let solution = self 338 let solution = self
338 .db 339 .db
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index b48ada760..ca47d6e96 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -317,6 +317,18 @@ pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty {
317 Ty::from_hir(db, &resolver, type_ref) 317 Ty::from_hir(db, &resolver, type_ref)
318} 318}
319 319
320pub(crate) fn trait_env(db: &impl HirDatabase, resolver: &Resolver) -> Arc<super::Environment> {
321 let predicates = resolver
322 .where_predicates_in_scope()
323 .map(|pred| {
324 TraitRef::for_where_predicate(db, &resolver, pred)
325 .map_or(GenericPredicate::Error, GenericPredicate::Implemented)
326 })
327 .collect::<Vec<_>>();
328
329 Arc::new(super::Environment { predicates })
330}
331
320/// Resolve the where clause(s) of an item with generics. 332/// Resolve the where clause(s) of an item with generics.
321pub(crate) fn generic_predicates_query( 333pub(crate) fn generic_predicates_query(
322 db: &impl HirDatabase, 334 db: &impl HirDatabase,
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 770e1964e..40f5eabf0 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -7,7 +7,7 @@ use std::sync::Arc;
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9 9
10use super::{autoderef, Canonical, Environment, InEnvironment, TraitRef}; 10use super::{autoderef, lower, Canonical, Environment, InEnvironment, TraitRef};
11use crate::{ 11use crate::{
12 generics::HasGenericParams, 12 generics::HasGenericParams,
13 impl_block::{ImplBlock, ImplId, ImplItem}, 13 impl_block::{ImplBlock, ImplId, ImplItem},
@@ -198,6 +198,8 @@ fn iterate_trait_method_candidates<T>(
198 mut callback: impl FnMut(&Ty, Function) -> Option<T>, 198 mut callback: impl FnMut(&Ty, Function) -> Option<T>,
199) -> Option<T> { 199) -> Option<T> {
200 let krate = resolver.krate()?; 200 let krate = resolver.krate()?;
201 // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that)
202 let env = lower::trait_env(db, resolver);
201 'traits: for t in resolver.traits_in_scope(db) { 203 'traits: for t in resolver.traits_in_scope(db) {
202 let data = t.trait_data(db); 204 let data = t.trait_data(db);
203 // we'll be lazy about checking whether the type implements the 205 // we'll be lazy about checking whether the type implements the
@@ -209,8 +211,7 @@ fn iterate_trait_method_candidates<T>(
209 let data = m.data(db); 211 let data = m.data(db);
210 if name.map_or(true, |name| data.name() == name) && data.has_self_param() { 212 if name.map_or(true, |name| data.name() == name) && data.has_self_param() {
211 if !known_implemented { 213 if !known_implemented {
212 let env = Arc::new(super::Environment); // FIXME add environment 214 let trait_ref = canonical_trait_ref(db, env.clone(), t, ty.clone());
213 let trait_ref = canonical_trait_ref(db, env, t, ty.clone());
214 if db.implements(krate, trait_ref).is_none() { 215 if db.implements(krate, trait_ref).is_none() {
215 continue 'traits; 216 continue 'traits;
216 } 217 }
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index fe5e89f2d..594e82af2 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2950,6 +2950,66 @@ fn test(o: O<S>) {
2950 assert_eq!(t, "&str"); 2950 assert_eq!(t, "&str");
2951} 2951}
2952 2952
2953#[test]
2954fn generic_param_env_1() {
2955 let t = type_at(
2956 r#"
2957//- /main.rs
2958trait Clone {}
2959trait Trait { fn foo(self) -> u128; }
2960struct S;
2961impl Clone for S {}
2962impl<T> Trait for T where T: Clone {}
2963fn test<T: Clone>(t: T) { t.foo()<|>; }
2964"#,
2965 );
2966 assert_eq!(t, "u128");
2967}
2968
2969#[test]
2970fn generic_param_env_1_not_met() {
2971 let t = type_at(
2972 r#"
2973//- /main.rs
2974trait Clone {}
2975trait Trait { fn foo(self) -> u128; }
2976struct S;
2977impl Clone for S {}
2978impl<T> Trait for T where T: Clone {}
2979fn test<T>(t: T) { t.foo()<|>; }
2980"#,
2981 );
2982 assert_eq!(t, "{unknown}");
2983}
2984
2985#[test]
2986fn generic_param_env_2() {
2987 let t = type_at(
2988 r#"
2989//- /main.rs
2990trait Trait { fn foo(self) -> u128; }
2991struct S;
2992impl Trait for S {}
2993fn test<T: Trait>(t: T) { t.foo()<|>; }
2994"#,
2995 );
2996 assert_eq!(t, "u128");
2997}
2998
2999#[test]
3000fn generic_param_env_2_not_met() {
3001 let t = type_at(
3002 r#"
3003//- /main.rs
3004trait Trait { fn foo(self) -> u128; }
3005struct S;
3006impl Trait for S {}
3007fn test<T>(t: T) { t.foo()<|>; }
3008"#,
3009 );
3010 assert_eq!(t, "{unknown}");
3011}
3012
2953fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 3013fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
2954 let file = db.parse(pos.file_id).ok().unwrap(); 3014 let file = db.parse(pos.file_id).ok().unwrap();
2955 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 3015 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index 718970553..e0c93550a 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -72,11 +72,13 @@ fn solve(
72/// fn foo<T: Default>(t: T) {} 72/// fn foo<T: Default>(t: T) {}
73/// ``` 73/// ```
74/// we assume that `T: Default`. 74/// we assume that `T: Default`.
75#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 75#[derive(Clone, Debug, PartialEq, Eq, Hash)]
76pub struct Environment; 76pub struct Environment {
77 pub predicates: Vec<GenericPredicate>,
78}
77 79
78/// Something (usually a goal), along with an environment. 80/// Something (usually a goal), along with an environment.
79#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 81#[derive(Clone, Debug, PartialEq, Eq, Hash)]
80pub struct InEnvironment<T> { 82pub struct InEnvironment<T> {
81 pub environment: Arc<Environment>, 83 pub environment: Arc<Environment>,
82 pub value: T, 84 pub value: T,
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index bee35fa62..f36ff2fc6 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -239,15 +239,28 @@ where
239impl ToChalk for Arc<super::Environment> { 239impl ToChalk for Arc<super::Environment> {
240 type Chalk = Arc<chalk_ir::Environment>; 240 type Chalk = Arc<chalk_ir::Environment>;
241 241
242 fn to_chalk(self, _db: &impl HirDatabase) -> Arc<chalk_ir::Environment> { 242 fn to_chalk(self, db: &impl HirDatabase) -> Arc<chalk_ir::Environment> {
243 chalk_ir::Environment::new() 243 let mut clauses = Vec::new();
244 for pred in &self.predicates {
245 if pred.is_error() {
246 // for env, we just ignore errors
247 continue;
248 }
249 if let GenericPredicate::Implemented(trait_ref) = pred {
250 if blacklisted_trait(db, trait_ref.trait_) {
251 continue;
252 }
253 }
254 clauses.push(pred.clone().to_chalk(db).cast());
255 }
256 chalk_ir::Environment::new().add_clauses(clauses)
244 } 257 }
245 258
246 fn from_chalk( 259 fn from_chalk(
247 _db: &impl HirDatabase, 260 _db: &impl HirDatabase,
248 _env: Arc<chalk_ir::Environment>, 261 _env: Arc<chalk_ir::Environment>,
249 ) -> Arc<super::Environment> { 262 ) -> Arc<super::Environment> {
250 Arc::new(super::Environment) 263 unimplemented!()
251 } 264 }
252} 265}
253 266