diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 20 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 134 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 6 |
5 files changed, 146 insertions, 35 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index a23daabc2..e79e5e223 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -849,8 +849,14 @@ 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(def.into()); | ||
853 | for predicate in generic_predicates.iter() { | ||
854 | let predicate = predicate.clone().subst(&a_ty.parameters); | ||
855 | if let Some(obligation) = Obligation::from_predicate(predicate) { | ||
856 | self.obligations.push(obligation); | ||
857 | } | ||
858 | } | ||
852 | // add obligation for trait implementation, if this is a trait method | 859 | // 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 { | 860 | match def { |
855 | CallableDef::Function(f) => { | 861 | CallableDef::Function(f) => { |
856 | if let Some(trait_) = f.parent_trait(self.db) { | 862 | if let Some(trait_) = f.parent_trait(self.db) { |
@@ -992,7 +998,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
992 | (Vec::new(), Ty::Unknown) | 998 | (Vec::new(), Ty::Unknown) |
993 | } | 999 | } |
994 | }; | 1000 | }; |
995 | // FIXME register obligations from where clauses from the function | 1001 | self.register_obligations_for_call(&callee_ty); |
996 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | 1002 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); |
997 | for (arg, param) in args.iter().zip(param_iter) { | 1003 | for (arg, param) in args.iter().zip(param_iter) { |
998 | self.infer_expr(*arg, &Expectation::has_type(param)); | 1004 | 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..b48ada760 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 | ||
@@ -511,3 +509,13 @@ pub enum CallableDef { | |||
511 | EnumVariant(EnumVariant), | 509 | EnumVariant(EnumVariant), |
512 | } | 510 | } |
513 | impl_froms!(CallableDef: Function, Struct, EnumVariant); | 511 | impl_froms!(CallableDef: Function, Struct, EnumVariant); |
512 | |||
513 | impl From<CallableDef> for GenericDef { | ||
514 | fn from(def: CallableDef) -> GenericDef { | ||
515 | match def { | ||
516 | CallableDef::Function(f) => f.into(), | ||
517 | CallableDef::Struct(s) => s.into(), | ||
518 | CallableDef::EnumVariant(e) => e.into(), | ||
519 | } | ||
520 | } | ||
521 | } | ||
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, |
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 2a0537bc3..4c3744b44 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -428,11 +428,7 @@ pub(crate) fn struct_datum_query( | |||
428 | CallableDef::Struct(s) => s.module(db).krate(db), | 428 | CallableDef::Struct(s) => s.module(db).krate(db), |
429 | CallableDef::EnumVariant(v) => v.parent_enum(db).module(db).krate(db), | 429 | CallableDef::EnumVariant(v) => v.parent_enum(db).module(db).krate(db), |
430 | } != Some(krate); | 430 | } != Some(krate); |
431 | let generic_def: GenericDef = match callable { | 431 | let generic_def: GenericDef = callable.into(); |
432 | CallableDef::Function(f) => f.into(), | ||
433 | CallableDef::Struct(s) => s.into(), | ||
434 | CallableDef::EnumVariant(v) => v.parent_enum(db).into(), | ||
435 | }; | ||
436 | let generic_params = generic_def.generic_params(db); | 432 | let generic_params = generic_def.generic_params(db); |
437 | let bound_vars = Substs::bound_vars(&generic_params); | 433 | let bound_vars = Substs::bound_vars(&generic_params); |
438 | let where_clauses = convert_where_clauses(db, generic_def, &bound_vars); | 434 | let where_clauses = convert_where_clauses(db, generic_def, &bound_vars); |