aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs77
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs8
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
16use crate::{ 16use 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
24use super::{ 24use 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
29impl<'a> InferenceContext<'a> { 29impl<'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}