diff options
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 130 | ||||
-rw-r--r-- | crates/ra_ide/src/hover.rs | 9 |
2 files changed, 72 insertions, 67 deletions
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 8c924ad42..359befe4f 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs | |||
@@ -15,10 +15,10 @@ 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, InEnvironment, SolutionVariables}, | 18 | traits::{FnTrait, Guidance, InEnvironment, SolutionVariables}, |
19 | utils::{generics, variant_data, Generics}, | 19 | utils::{generics, variant_data, Generics}, |
20 | ApplicationTy, Binders, CallableDef, FnSig, InferTy, IntTy, Mutability, Obligation, Rawness, | 20 | ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs, |
21 | Substs, TraitRef, Ty, TypeCtor, | 21 | TraitRef, Ty, TypeCtor, |
22 | }; | 22 | }; |
23 | 23 | ||
24 | use super::{ | 24 | use super::{ |
@@ -63,72 +63,70 @@ impl<'a> InferenceContext<'a> { | |||
63 | self.resolve_ty_as_possible(ty) | 63 | self.resolve_ty_as_possible(ty) |
64 | } | 64 | } |
65 | 65 | ||
66 | fn callable_sig_from_fn_trait(&mut self, ty: &Ty) -> Option<FnSig> { | 66 | fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> { |
67 | if let Some(krate) = self.resolver.krate() { | 67 | let krate = self.resolver.krate()?; |
68 | let fn_traits: Vec<crate::TraitId> = [FnTrait::FnOnce, FnTrait::FnMut, FnTrait::Fn] | 68 | let fn_traits: Vec<crate::TraitId> = [FnTrait::FnOnce, FnTrait::FnMut, FnTrait::Fn] |
69 | .iter() | 69 | .iter() |
70 | .filter_map(|f| f.get_id(self.db, krate)) | 70 | .filter_map(|f| f.get_id(self.db, krate)) |
71 | .collect(); | 71 | .collect(); |
72 | for fn_trait in fn_traits { | 72 | let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?; |
73 | let fn_trait_data = self.db.trait_data(fn_trait); | 73 | let output_assoc_type = match self |
74 | let generic_params = generics(self.db.upcast(), fn_trait.into()); | 74 | .db |
75 | if generic_params.len() != 2 { | 75 | .trait_data(fn_once_trait) |
76 | continue; | 76 | .associated_types() |
77 | } | 77 | .collect::<Vec<hir_def::TypeAliasId>>() |
78 | 78 | .as_slice() | |
79 | let arg_ty = self.table.new_type_var(); | 79 | { |
80 | let substs = Substs::build_for_generics(&generic_params) | 80 | [output] => *output, |
81 | .push(ty.clone()) | 81 | _ => { |
82 | .push(arg_ty.clone()) | 82 | return None; |
83 | .build(); | ||
84 | |||
85 | let trait_ref = TraitRef { trait_: fn_trait, substs: substs.clone() }; | ||
86 | let trait_env = Arc::clone(&self.trait_env); | ||
87 | let implements_fn_goal = | ||
88 | self.canonicalizer().canonicalize_obligation(InEnvironment { | ||
89 | value: Obligation::Trait(trait_ref), | ||
90 | environment: trait_env, | ||
91 | }); | ||
92 | if let Some(Solution::Unique(SolutionVariables(solution))) = | ||
93 | self.db.trait_solve(krate, implements_fn_goal.value.clone()) | ||
94 | { | ||
95 | match solution.value.as_slice() { | ||
96 | [Ty::Apply(ApplicationTy { | ||
97 | ctor: TypeCtor::Tuple { cardinality: _ }, | ||
98 | parameters, | ||
99 | })] => { | ||
100 | let output_assoc_type = match fn_trait_data | ||
101 | .associated_types() | ||
102 | .collect::<Vec<hir_def::TypeAliasId>>() | ||
103 | .as_slice() | ||
104 | { | ||
105 | [output] => *output, | ||
106 | _ => { | ||
107 | continue; | ||
108 | } | ||
109 | }; | ||
110 | let output_proj_ty = crate::ProjectionTy { | ||
111 | associated_ty: output_assoc_type, | ||
112 | parameters: substs, | ||
113 | }; | ||
114 | let return_ty = self.normalize_projection_ty(output_proj_ty); | ||
115 | return Some(FnSig::from_params_and_return( | ||
116 | parameters.into_iter().map(|ty| ty.clone()).collect(), | ||
117 | return_ty, | ||
118 | )); | ||
119 | } | ||
120 | _ => (), | ||
121 | } | ||
122 | } | ||
123 | } | 83 | } |
124 | }; | 84 | }; |
85 | for fn_trait in fn_traits { | ||
86 | let generic_params = generics(self.db.upcast(), fn_trait.into()); | ||
87 | if generic_params.len() != 2 { | ||
88 | continue; | ||
89 | } | ||
90 | |||
91 | let mut param_builder = Substs::builder(num_args); | ||
92 | for _ in 0..num_args { | ||
93 | param_builder = param_builder.push(self.table.new_type_var()); | ||
94 | } | ||
95 | let arg_ty = Ty::Apply(ApplicationTy { | ||
96 | ctor: TypeCtor::Tuple { cardinality: num_args as u16 }, | ||
97 | parameters: param_builder.build(), | ||
98 | }); | ||
99 | let substs = Substs::build_for_generics(&generic_params) | ||
100 | .push(ty.clone()) | ||
101 | .push(arg_ty.clone()) | ||
102 | .build(); | ||
103 | |||
104 | let trait_ref = TraitRef { trait_: fn_trait, substs: substs.clone() }; | ||
105 | let trait_env = Arc::clone(&self.trait_env); | ||
106 | let implements_fn_goal = self.canonicalizer().canonicalize_obligation(InEnvironment { | ||
107 | value: Obligation::Trait(trait_ref), | ||
108 | environment: trait_env, | ||
109 | }); | ||
110 | let solution = match self.db.trait_solve(krate, implements_fn_goal.value.clone()) { | ||
111 | Some(Solution::Unique(SolutionVariables(solution))) | ||
112 | | Some(Solution::Ambig(Guidance::Definite(SolutionVariables(solution)))) | ||
113 | | Some(Solution::Ambig(Guidance::Suggested(SolutionVariables(solution)))) => { | ||
114 | solution | ||
115 | } | ||
116 | _ => continue, | ||
117 | }; | ||
118 | let output_proj_ty = | ||
119 | crate::ProjectionTy { associated_ty: output_assoc_type, parameters: substs }; | ||
120 | let return_ty = self.normalize_projection_ty(output_proj_ty); | ||
121 | return Some((solution.value, return_ty)); | ||
122 | } | ||
125 | None | 123 | None |
126 | } | 124 | } |
127 | 125 | ||
128 | pub fn callable_sig(&mut self, ty: &Ty) -> Option<FnSig> { | 126 | pub fn callable_sig(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> { |
129 | match ty.callable_sig(self.db) { | 127 | match ty.callable_sig(self.db) { |
130 | result @ Some(_) => result, | 128 | Some(sig) => Some((sig.params().to_vec(), sig.ret().clone())), |
131 | None => self.callable_sig_from_fn_trait(ty), | 129 | None => self.callable_sig_from_fn_trait(ty, num_args), |
132 | } | 130 | } |
133 | } | 131 | } |
134 | 132 | ||
@@ -278,8 +276,10 @@ impl<'a> InferenceContext<'a> { | |||
278 | ); | 276 | ); |
279 | let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs | 277 | let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs |
280 | .find_map(|callee_deref_ty| { | 278 | .find_map(|callee_deref_ty| { |
281 | self.callable_sig(&canonicalized.decanonicalize_ty(callee_deref_ty.value)) | 279 | self.callable_sig( |
282 | .map(|sig| (sig.params().to_vec(), sig.ret().clone())) | 280 | &canonicalized.decanonicalize_ty(callee_deref_ty.value), |
281 | args.len(), | ||
282 | ) | ||
283 | }) | 283 | }) |
284 | .unwrap_or((Vec::new(), Ty::Unknown)); | 284 | .unwrap_or((Vec::new(), Ty::Unknown)); |
285 | self.register_obligations_for_call(&callee_ty); | 285 | self.register_obligations_for_call(&callee_ty); |
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 9a88b4977..a03024d09 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -2438,10 +2438,15 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
2438 | r#" | 2438 | r#" |
2439 | //- /lib.rs deps:std | 2439 | //- /lib.rs deps:std |
2440 | 2440 | ||
2441 | #[lang = "fn"] | 2441 | #[lang = "fn_once"] |
2442 | pub trait Fn<Args> { | 2442 | pub trait FnOnce<Args> { |
2443 | type Output; | 2443 | type Output; |
2444 | 2444 | ||
2445 | extern "rust-call" fn call_once(&self, args: Args) -> Self::Output; | ||
2446 | } | ||
2447 | |||
2448 | #[lang = "fn"] | ||
2449 | pub trait Fn<Args>:FnOnce<Args> { | ||
2445 | extern "rust-call" fn call(&self, args: Args) -> Self::Output; | 2450 | extern "rust-call" fn call(&self, args: Args) -> Self::Output; |
2446 | } | 2451 | } |
2447 | 2452 | ||