diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 77 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 8 |
2 files changed, 40 insertions, 45 deletions
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 171330274..a9565a58d 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -15,7 +15,7 @@ use ra_syntax::ast::RangeOp; | |||
15 | 15 | ||
16 | use crate::{ | 16 | use crate::{ |
17 | autoderef, method_resolution, op, | 17 | autoderef, method_resolution, op, |
18 | traits::{FnTrait, Guidance, InEnvironment, SolutionVariables}, | 18 | traits::{FnTrait, InEnvironment}, |
19 | utils::{generics, variant_data, Generics}, | 19 | utils::{generics, variant_data, Generics}, |
20 | ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs, | 20 | ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs, |
21 | TraitRef, Ty, TypeCtor, | 21 | TraitRef, Ty, TypeCtor, |
@@ -23,7 +23,7 @@ use crate::{ | |||
23 | 23 | ||
24 | use super::{ | 24 | use super::{ |
25 | find_breakable, BindingMode, BreakableContext, Diverges, Expectation, InferenceContext, | 25 | find_breakable, BindingMode, BreakableContext, Diverges, Expectation, InferenceContext, |
26 | InferenceDiagnostic, Solution, TypeMismatch, | 26 | InferenceDiagnostic, TypeMismatch, |
27 | }; | 27 | }; |
28 | 28 | ||
29 | impl<'a> InferenceContext<'a> { | 29 | impl<'a> InferenceContext<'a> { |
@@ -65,52 +65,47 @@ impl<'a> InferenceContext<'a> { | |||
65 | 65 | ||
66 | fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> { | 66 | fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> { |
67 | let krate = self.resolver.krate()?; | 67 | let krate = self.resolver.krate()?; |
68 | let fn_traits: Vec<crate::TraitId> = [FnTrait::FnOnce, FnTrait::FnMut, FnTrait::Fn] | ||
69 | .iter() | ||
70 | .filter_map(|f| f.get_id(self.db, krate)) | ||
71 | .collect(); | ||
72 | let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?; | 68 | let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?; |
73 | let output_assoc_type = | 69 | let output_assoc_type = |
74 | self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; | 70 | self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; |
75 | for fn_trait in fn_traits { | 71 | let generic_params = generics(self.db.upcast(), fn_once_trait.into()); |
76 | let generic_params = generics(self.db.upcast(), fn_trait.into()); | 72 | if generic_params.len() != 2 { |
77 | if generic_params.len() != 2 { | 73 | return None; |
78 | continue; | 74 | } |
79 | } | 75 | |
80 | 76 | let mut param_builder = Substs::builder(num_args); | |
81 | let mut param_builder = Substs::builder(num_args); | 77 | let mut arg_tys = vec![]; |
82 | for _ in 0..num_args { | 78 | for _ in 0..num_args { |
83 | param_builder = param_builder.push(self.table.new_type_var()); | 79 | let arg = self.table.new_type_var(); |
84 | } | 80 | param_builder = param_builder.push(arg.clone()); |
85 | let arg_ty = Ty::Apply(ApplicationTy { | 81 | arg_tys.push(arg); |
86 | ctor: TypeCtor::Tuple { cardinality: num_args as u16 }, | 82 | } |
87 | parameters: param_builder.build(), | 83 | let parameters = param_builder.build(); |
88 | }); | 84 | let arg_ty = Ty::Apply(ApplicationTy { |
89 | let substs = Substs::build_for_generics(&generic_params) | 85 | ctor: TypeCtor::Tuple { cardinality: num_args as u16 }, |
90 | .push(ty.clone()) | 86 | parameters, |
91 | .push(arg_ty.clone()) | 87 | }); |
92 | .build(); | 88 | let substs = Substs::build_for_generics(&generic_params) |
93 | 89 | .push(ty.clone()) | |
94 | let trait_ref = TraitRef { trait_: fn_trait, substs: substs.clone() }; | 90 | .push(arg_ty.clone()) |
95 | let trait_env = Arc::clone(&self.trait_env); | 91 | .build(); |
96 | let implements_fn_goal = self.canonicalizer().canonicalize_obligation(InEnvironment { | 92 | |
97 | value: Obligation::Trait(trait_ref), | 93 | let trait_env = Arc::clone(&self.trait_env); |
98 | environment: trait_env, | 94 | let implements_fn_trait = |
99 | }); | 95 | Obligation::Trait(TraitRef { trait_: fn_once_trait, substs: substs.clone() }); |
100 | let solution = match self.db.trait_solve(krate, implements_fn_goal.value.clone()) { | 96 | let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { |
101 | Some(Solution::Unique(SolutionVariables(solution))) | 97 | value: implements_fn_trait.clone(), |
102 | | Some(Solution::Ambig(Guidance::Definite(SolutionVariables(solution)))) | 98 | environment: trait_env, |
103 | | Some(Solution::Ambig(Guidance::Suggested(SolutionVariables(solution)))) => { | 99 | }); |
104 | solution | 100 | if self.db.trait_solve(krate, goal.value).is_some() { |
105 | } | 101 | self.obligations.push(implements_fn_trait); |
106 | _ => continue, | ||
107 | }; | ||
108 | let output_proj_ty = | 102 | let output_proj_ty = |
109 | crate::ProjectionTy { associated_ty: output_assoc_type, parameters: substs }; | 103 | crate::ProjectionTy { associated_ty: output_assoc_type, parameters: substs }; |
110 | let return_ty = self.normalize_projection_ty(output_proj_ty); | 104 | let return_ty = self.normalize_projection_ty(output_proj_ty); |
111 | return Some((solution.value, return_ty)); | 105 | Some((arg_tys, return_ty)) |
106 | } else { | ||
107 | None | ||
112 | } | 108 | } |
113 | None | ||
114 | } | 109 | } |
115 | 110 | ||
116 | pub fn callable_sig(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> { | 111 | pub fn callable_sig(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> { |
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index dd5bdd2d0..961be4abd 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -3028,7 +3028,7 @@ fn infer_box_fn_arg() { | |||
3028 | 656..667 '&self.inner': &*mut T | 3028 | 656..667 '&self.inner': &*mut T |
3029 | 657..661 'self': &Box<T> | 3029 | 657..661 'self': &Box<T> |
3030 | 657..667 'self.inner': *mut T | 3030 | 657..667 'self.inner': *mut T |
3031 | 812..957 '{ ... }': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, ({unknown},)> | 3031 | 812..957 '{ ... }': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)> |
3032 | 834..835 's': Option<i32> | 3032 | 834..835 's': Option<i32> |
3033 | 838..850 'Option::None': Option<i32> | 3033 | 838..850 'Option::None': Option<i32> |
3034 | 872..873 'f': Box<dyn FnOnce<(&Option<i32>,)>> | 3034 | 872..873 'f': Box<dyn FnOnce<(&Option<i32>,)>> |
@@ -3037,7 +3037,7 @@ fn infer_box_fn_arg() { | |||
3037 | 913..915 'ps': {unknown} | 3037 | 913..915 'ps': {unknown} |
3038 | 917..919 '{}': () | 3038 | 917..919 '{}': () |
3039 | 938..939 'f': Box<dyn FnOnce<(&Option<i32>,)>> | 3039 | 938..939 'f': Box<dyn FnOnce<(&Option<i32>,)>> |
3040 | 938..943 'f(&s)': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, ({unknown},)> | 3040 | 938..943 'f(&s)': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)> |
3041 | 940..942 '&s': &Option<i32> | 3041 | 940..942 '&s': &Option<i32> |
3042 | 941..942 's': Option<i32> | 3042 | 941..942 's': Option<i32> |
3043 | "### | 3043 | "### |
@@ -3105,9 +3105,9 @@ fn infer_dyn_fn_output() { | |||
3105 | 937..946 'box(|| 5)': Box<|| -> i32> | 3105 | 937..946 'box(|| 5)': Box<|| -> i32> |
3106 | 941..945 '|| 5': || -> i32 | 3106 | 941..945 '|| 5': || -> i32 |
3107 | 944..945 '5': i32 | 3107 | 944..945 '5': i32 |
3108 | 968..969 'x': i32 | 3108 | 968..969 'x': FnOnce::Output<dyn Fn<(), Output = i32>, ()> |
3109 | 972..973 'f': Box<dyn Fn<(), Output = i32>> | 3109 | 972..973 'f': Box<dyn Fn<(), Output = i32>> |
3110 | 972..975 'f()': i32 | 3110 | 972..975 'f()': FnOnce::Output<dyn Fn<(), Output = i32>, ()> |
3111 | "### | 3111 | "### |
3112 | ); | 3112 | ); |
3113 | } | 3113 | } |