diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 60 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 19 |
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; | |||
27 | use test_utils::tested_by; | 27 | use test_utils::tested_by; |
28 | 28 | ||
29 | use super::{ | 29 | use 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 | }; |
35 | use crate::{ | 35 | use 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 | ||
320 | pub(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. |
321 | pub(crate) fn generic_predicates_query( | 333 | pub(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; | |||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
9 | 9 | ||
10 | use super::{autoderef, Canonical, Environment, InEnvironment, TraitRef}; | 10 | use super::{autoderef, lower, Canonical, Environment, InEnvironment, TraitRef}; |
11 | use crate::{ | 11 | use 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] | ||
2954 | fn generic_param_env_1() { | ||
2955 | let t = type_at( | ||
2956 | r#" | ||
2957 | //- /main.rs | ||
2958 | trait Clone {} | ||
2959 | trait Trait { fn foo(self) -> u128; } | ||
2960 | struct S; | ||
2961 | impl Clone for S {} | ||
2962 | impl<T> Trait for T where T: Clone {} | ||
2963 | fn test<T: Clone>(t: T) { t.foo()<|>; } | ||
2964 | "#, | ||
2965 | ); | ||
2966 | assert_eq!(t, "u128"); | ||
2967 | } | ||
2968 | |||
2969 | #[test] | ||
2970 | fn generic_param_env_1_not_met() { | ||
2971 | let t = type_at( | ||
2972 | r#" | ||
2973 | //- /main.rs | ||
2974 | trait Clone {} | ||
2975 | trait Trait { fn foo(self) -> u128; } | ||
2976 | struct S; | ||
2977 | impl Clone for S {} | ||
2978 | impl<T> Trait for T where T: Clone {} | ||
2979 | fn test<T>(t: T) { t.foo()<|>; } | ||
2980 | "#, | ||
2981 | ); | ||
2982 | assert_eq!(t, "{unknown}"); | ||
2983 | } | ||
2984 | |||
2985 | #[test] | ||
2986 | fn generic_param_env_2() { | ||
2987 | let t = type_at( | ||
2988 | r#" | ||
2989 | //- /main.rs | ||
2990 | trait Trait { fn foo(self) -> u128; } | ||
2991 | struct S; | ||
2992 | impl Trait for S {} | ||
2993 | fn test<T: Trait>(t: T) { t.foo()<|>; } | ||
2994 | "#, | ||
2995 | ); | ||
2996 | assert_eq!(t, "u128"); | ||
2997 | } | ||
2998 | |||
2999 | #[test] | ||
3000 | fn generic_param_env_2_not_met() { | ||
3001 | let t = type_at( | ||
3002 | r#" | ||
3003 | //- /main.rs | ||
3004 | trait Trait { fn foo(self) -> u128; } | ||
3005 | struct S; | ||
3006 | impl Trait for S {} | ||
3007 | fn test<T>(t: T) { t.foo()<|>; } | ||
3008 | "#, | ||
3009 | ); | ||
3010 | assert_eq!(t, "{unknown}"); | ||
3011 | } | ||
3012 | |||
2953 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 3013 | fn 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)] |
76 | pub struct Environment; | 76 | pub 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)] |
80 | pub struct InEnvironment<T> { | 82 | pub 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 | |||
239 | impl ToChalk for Arc<super::Environment> { | 239 | impl 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 | ||