diff options
-rw-r--r-- | crates/ra_hir/src/db.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 12 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 134 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 11 |
7 files changed, 156 insertions, 34 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index a9c6c52d9..0e6e3fdb7 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -163,10 +163,10 @@ pub trait HirDatabase: DefDatabase + AstDatabase { | |||
163 | #[salsa::invoke(crate::ty::callable_item_sig)] | 163 | #[salsa::invoke(crate::ty::callable_item_sig)] |
164 | fn callable_item_signature(&self, def: CallableDef) -> FnSig; | 164 | fn callable_item_signature(&self, def: CallableDef) -> FnSig; |
165 | 165 | ||
166 | #[salsa::invoke(crate::ty::generic_predicates)] | 166 | #[salsa::invoke(crate::ty::generic_predicates_query)] |
167 | fn generic_predicates(&self, def: GenericDef) -> Arc<[GenericPredicate]>; | 167 | fn generic_predicates(&self, def: GenericDef) -> Arc<[GenericPredicate]>; |
168 | 168 | ||
169 | #[salsa::invoke(crate::ty::generic_defaults)] | 169 | #[salsa::invoke(crate::ty::generic_defaults_query)] |
170 | fn generic_defaults(&self, def: GenericDef) -> Substs; | 170 | fn generic_defaults(&self, def: GenericDef) -> Substs; |
171 | 171 | ||
172 | #[salsa::invoke(crate::expr::body_with_source_map_query)] | 172 | #[salsa::invoke(crate::expr::body_with_source_map_query)] |
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs index c8be27e54..e2a7639b0 100644 --- a/crates/ra_hir/src/resolve.rs +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -221,6 +221,18 @@ impl Resolver { | |||
221 | pub(crate) fn krate(&self) -> Option<Crate> { | 221 | pub(crate) fn krate(&self) -> Option<Crate> { |
222 | self.module().map(|t| t.0.krate()) | 222 | self.module().map(|t| t.0.krate()) |
223 | } | 223 | } |
224 | |||
225 | pub(crate) fn where_predicates_in_scope<'a>( | ||
226 | &'a self, | ||
227 | ) -> impl Iterator<Item = &'a crate::generics::WherePredicate> + 'a { | ||
228 | self.scopes | ||
229 | .iter() | ||
230 | .filter_map(|scope| match scope { | ||
231 | Scope::GenericParams(params) => Some(params), | ||
232 | _ => None, | ||
233 | }) | ||
234 | .flat_map(|params| params.where_predicates.iter()) | ||
235 | } | ||
224 | } | 236 | } |
225 | 237 | ||
226 | impl Resolver { | 238 | impl Resolver { |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 11afdc0f3..d8c7945e1 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -23,8 +23,8 @@ pub(crate) use autoderef::autoderef; | |||
23 | pub(crate) use infer::{infer_query, InferTy, InferenceResult}; | 23 | pub(crate) use infer::{infer_query, InferTy, InferenceResult}; |
24 | pub use lower::CallableDef; | 24 | pub use lower::CallableDef; |
25 | pub(crate) use lower::{ | 25 | pub(crate) use lower::{ |
26 | callable_item_sig, generic_defaults, generic_predicates, type_for_def, type_for_field, | 26 | callable_item_sig, generic_defaults_query, generic_predicates_query, type_for_def, |
27 | TypableDef, | 27 | type_for_field, TypableDef, |
28 | }; | 28 | }; |
29 | pub(crate) use traits::ProjectionPredicate; | 29 | pub(crate) use traits::ProjectionPredicate; |
30 | 30 | ||
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index a23daabc2..f5d8cd4b1 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -849,8 +849,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
849 | fn register_obligations_for_call(&mut self, callable_ty: &Ty) { | 849 | fn register_obligations_for_call(&mut self, callable_ty: &Ty) { |
850 | if let Ty::Apply(a_ty) = callable_ty { | 850 | if let Ty::Apply(a_ty) = callable_ty { |
851 | if let TypeCtor::FnDef(def) = a_ty.ctor { | 851 | if let TypeCtor::FnDef(def) = a_ty.ctor { |
852 | let generic_predicates = self.db.generic_predicates(match def { | ||
853 | // TODO add helper function | ||
854 | CallableDef::Function(f) => f.into(), | ||
855 | CallableDef::Struct(s) => s.into(), | ||
856 | CallableDef::EnumVariant(_e) => unimplemented!(), | ||
857 | }); | ||
858 | for predicate in generic_predicates.iter() { | ||
859 | let predicate = predicate.clone().subst(&a_ty.parameters); | ||
860 | if let Some(obligation) = Obligation::from_predicate(predicate) { | ||
861 | self.obligations.push(obligation); | ||
862 | } | ||
863 | } | ||
852 | // add obligation for trait implementation, if this is a trait method | 864 | // add obligation for trait implementation, if this is a trait method |
853 | // FIXME also register obligations from where clauses from the trait or impl and method | ||
854 | match def { | 865 | match def { |
855 | CallableDef::Function(f) => { | 866 | CallableDef::Function(f) => { |
856 | if let Some(trait_) = f.parent_trait(self.db) { | 867 | if let Some(trait_) = f.parent_trait(self.db) { |
@@ -992,7 +1003,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
992 | (Vec::new(), Ty::Unknown) | 1003 | (Vec::new(), Ty::Unknown) |
993 | } | 1004 | } |
994 | }; | 1005 | }; |
995 | // FIXME register obligations from where clauses from the function | 1006 | self.register_obligations_for_call(&callee_ty); |
996 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | 1007 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); |
997 | for (arg, param) in args.iter().zip(param_iter) { | 1008 | for (arg, param) in args.iter().zip(param_iter) { |
998 | self.infer_expr(*arg, &Expectation::has_type(param)); | 1009 | self.infer_expr(*arg, &Expectation::has_type(param)); |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 8b1b2a7f9..24755c6aa 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -318,15 +318,13 @@ pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { | |||
318 | } | 318 | } |
319 | 319 | ||
320 | /// Resolve the where clause(s) of an item with generics. | 320 | /// Resolve the where clause(s) of an item with generics. |
321 | pub(crate) fn generic_predicates( | 321 | pub(crate) fn generic_predicates_query( |
322 | db: &impl HirDatabase, | 322 | db: &impl HirDatabase, |
323 | def: GenericDef, | 323 | def: GenericDef, |
324 | ) -> Arc<[GenericPredicate]> { | 324 | ) -> Arc<[GenericPredicate]> { |
325 | let resolver = def.resolver(db); | 325 | let resolver = def.resolver(db); |
326 | let generic_params = def.generic_params(db); | 326 | let predicates = resolver |
327 | let predicates = generic_params | 327 | .where_predicates_in_scope() |
328 | .where_predicates | ||
329 | .iter() | ||
330 | .map(|pred| { | 328 | .map(|pred| { |
331 | TraitRef::for_where_predicate(db, &resolver, pred) | 329 | TraitRef::for_where_predicate(db, &resolver, pred) |
332 | .map_or(GenericPredicate::Error, GenericPredicate::Implemented) | 330 | .map_or(GenericPredicate::Error, GenericPredicate::Implemented) |
@@ -336,7 +334,7 @@ pub(crate) fn generic_predicates( | |||
336 | } | 334 | } |
337 | 335 | ||
338 | /// Resolve the default type params from generics | 336 | /// Resolve the default type params from generics |
339 | pub(crate) fn generic_defaults(db: &impl HirDatabase, def: GenericDef) -> Substs { | 337 | pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) -> Substs { |
340 | let resolver = def.resolver(db); | 338 | let resolver = def.resolver(db); |
341 | let generic_params = def.generic_params(db); | 339 | let generic_params = def.generic_params(db); |
342 | 340 | ||
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 20fa74fb4..aacd94a26 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -2232,16 +2232,18 @@ fn test() { | |||
2232 | } | 2232 | } |
2233 | "#), | 2233 | "#), |
2234 | @r###" | 2234 | @r###" |
2235 | [86; 87) 't': T | 2235 | ⋮ |
2236 | [92; 94) '{}': () | 2236 | ⋮[86; 87) 't': T |
2237 | [105; 144) '{ ...(s); }': () | 2237 | ⋮[92; 94) '{}': () |
2238 | [115; 116) 's': S<{unknown}> | 2238 | ⋮[105; 144) '{ ...(s); }': () |
2239 | [119; 120) 'S': S<{unknown}>(T) -> S<T> | 2239 | ⋮[115; 116) 's': S<u32> |
2240 | [119; 129) 'S(unknown)': S<{unknown}> | 2240 | ⋮[119; 120) 'S': S<u32>(T) -> S<T> |
2241 | [121; 128) 'unknown': {unknown} | 2241 | ⋮[119; 129) 'S(unknown)': S<u32> |
2242 | [135; 138) 'foo': fn foo<S<{unknown}>>(T) -> () | 2242 | ⋮[121; 128) 'unknown': u32 |
2243 | [135; 141) 'foo(s)': () | 2243 | ⋮[135; 138) 'foo': fn foo<S<u32>>(T) -> () |
2244 | [139; 140) 's': S<{unknown}>"### | 2244 | ⋮[135; 141) 'foo(s)': () |
2245 | ⋮[139; 140) 's': S<u32> | ||
2246 | "### | ||
2245 | ); | 2247 | ); |
2246 | } | 2248 | } |
2247 | 2249 | ||
@@ -2259,17 +2261,19 @@ fn test() { | |||
2259 | } | 2261 | } |
2260 | "#), | 2262 | "#), |
2261 | @r###" | 2263 | @r###" |
2262 | [87; 88) 't': T | 2264 | ⋮ |
2263 | [98; 100) '{}': () | 2265 | ⋮[87; 88) 't': T |
2264 | [111; 163) '{ ...(s); }': () | 2266 | ⋮[98; 100) '{}': () |
2265 | [121; 122) 's': S<{unknown}> | 2267 | ⋮[111; 163) '{ ...(s); }': () |
2266 | [125; 126) 'S': S<{unknown}>(T) -> S<T> | 2268 | ⋮[121; 122) 's': S<u32> |
2267 | [125; 135) 'S(unknown)': S<{unknown}> | 2269 | ⋮[125; 126) 'S': S<u32>(T) -> S<T> |
2268 | [127; 134) 'unknown': {unknown} | 2270 | ⋮[125; 135) 'S(unknown)': S<u32> |
2269 | [145; 146) 'x': u32 | 2271 | ⋮[127; 134) 'unknown': u32 |
2270 | [154; 157) 'foo': fn foo<u32, S<{unknown}>>(T) -> U | 2272 | ⋮[145; 146) 'x': u32 |
2271 | [154; 160) 'foo(s)': u32 | 2273 | ⋮[154; 157) 'foo': fn foo<u32, S<u32>>(T) -> U |
2272 | [158; 159) 's': S<{unknown}>"### | 2274 | ⋮[154; 160) 'foo(s)': u32 |
2275 | ⋮[158; 159) 's': S<u32> | ||
2276 | "### | ||
2273 | ); | 2277 | ); |
2274 | } | 2278 | } |
2275 | 2279 | ||
@@ -2822,6 +2826,94 @@ fn test(s: S) { | |||
2822 | assert_eq!(t, "{unknown}"); | 2826 | assert_eq!(t, "{unknown}"); |
2823 | } | 2827 | } |
2824 | 2828 | ||
2829 | #[test] | ||
2830 | fn obligation_from_function_clause() { | ||
2831 | let t = type_at( | ||
2832 | r#" | ||
2833 | //- /main.rs | ||
2834 | struct S; | ||
2835 | |||
2836 | trait Trait<T> {} | ||
2837 | impl Trait<u32> for S {} | ||
2838 | |||
2839 | fn foo<T: Trait<U>, U>(t: T) -> U {} | ||
2840 | |||
2841 | fn test(s: S) { | ||
2842 | foo(s)<|>; | ||
2843 | } | ||
2844 | "#, | ||
2845 | ); | ||
2846 | assert_eq!(t, "u32"); | ||
2847 | } | ||
2848 | |||
2849 | #[test] | ||
2850 | fn obligation_from_method_clause() { | ||
2851 | let t = type_at( | ||
2852 | r#" | ||
2853 | //- /main.rs | ||
2854 | struct S; | ||
2855 | |||
2856 | trait Trait<T> {} | ||
2857 | impl Trait<isize> for S {} | ||
2858 | |||
2859 | struct O; | ||
2860 | impl O { | ||
2861 | fn foo<T: Trait<U>, U>(&self, t: T) -> U {} | ||
2862 | } | ||
2863 | |||
2864 | fn test() { | ||
2865 | O.foo(S)<|>; | ||
2866 | } | ||
2867 | "#, | ||
2868 | ); | ||
2869 | assert_eq!(t, "isize"); | ||
2870 | } | ||
2871 | |||
2872 | #[test] | ||
2873 | fn obligation_from_self_method_clause() { | ||
2874 | let t = type_at( | ||
2875 | r#" | ||
2876 | //- /main.rs | ||
2877 | struct S; | ||
2878 | |||
2879 | trait Trait<T> {} | ||
2880 | impl Trait<i64> for S {} | ||
2881 | |||
2882 | impl S { | ||
2883 | fn foo<U>(&self) -> U where Self: Trait<U> {} | ||
2884 | } | ||
2885 | |||
2886 | fn test() { | ||
2887 | S.foo()<|>; | ||
2888 | } | ||
2889 | "#, | ||
2890 | ); | ||
2891 | assert_eq!(t, "i64"); | ||
2892 | } | ||
2893 | |||
2894 | #[test] | ||
2895 | fn obligation_from_impl_clause() { | ||
2896 | let t = type_at( | ||
2897 | r#" | ||
2898 | //- /main.rs | ||
2899 | struct S; | ||
2900 | |||
2901 | trait Trait<T> {} | ||
2902 | impl Trait<&str> for S {} | ||
2903 | |||
2904 | struct O<T>; | ||
2905 | impl<U, T: Trait<U>> O<T> { | ||
2906 | fn foo(&self) -> U {} | ||
2907 | } | ||
2908 | |||
2909 | fn test(o: O<S>) { | ||
2910 | o.foo()<|>; | ||
2911 | } | ||
2912 | "#, | ||
2913 | ); | ||
2914 | assert_eq!(t, "&str"); | ||
2915 | } | ||
2916 | |||
2825 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 2917 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { |
2826 | let file = db.parse(pos.file_id).ok().unwrap(); | 2918 | let file = db.parse(pos.file_id).ok().unwrap(); |
2827 | let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); | 2919 | 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 cff4de316..23a26a971 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -7,7 +7,7 @@ use parking_lot::Mutex; | |||
7 | use ra_prof::profile; | 7 | use ra_prof::profile; |
8 | use rustc_hash::FxHashSet; | 8 | use rustc_hash::FxHashSet; |
9 | 9 | ||
10 | use super::{Canonical, ProjectionTy, TraitRef, Ty}; | 10 | use super::{Canonical, GenericPredicate, ProjectionTy, TraitRef, Ty}; |
11 | use crate::{db::HirDatabase, Crate, ImplBlock, Trait}; | 11 | use crate::{db::HirDatabase, Crate, ImplBlock, Trait}; |
12 | 12 | ||
13 | use self::chalk::{from_chalk, ToChalk}; | 13 | use self::chalk::{from_chalk, ToChalk}; |
@@ -78,6 +78,15 @@ pub enum Obligation { | |||
78 | // Projection(ProjectionPredicate), | 78 | // Projection(ProjectionPredicate), |
79 | } | 79 | } |
80 | 80 | ||
81 | impl Obligation { | ||
82 | pub fn from_predicate(predicate: GenericPredicate) -> Option<Obligation> { | ||
83 | match predicate { | ||
84 | GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)), | ||
85 | GenericPredicate::Error => None, | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | |||
81 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | 90 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
82 | pub struct ProjectionPredicate { | 91 | pub struct ProjectionPredicate { |
83 | pub projection_ty: ProjectionTy, | 92 | pub projection_ty: ProjectionTy, |