aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs130
-rw-r--r--crates/ra_ide/src/hover.rs9
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
16use crate::{ 16use 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
24use super::{ 24use 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