Skip to content

Commit 1629fb7

Browse files
committed
Push obligation instead of matching on solution
1 parent d8f5192 commit 1629fb7

File tree

2 files changed

+40
-45
lines changed

2 files changed

+40
-45
lines changed

crates/ra_hir_ty/src/infer/expr.rs

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ use ra_syntax::ast::RangeOp;
1515

1616
use crate::{
1717
autoderef, method_resolution, op,
18-
traits::{FnTrait, Guidance, InEnvironment, SolutionVariables},
18+
traits::{FnTrait, InEnvironment},
1919
utils::{generics, variant_data, Generics},
2020
ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs,
2121
TraitRef, Ty, TypeCtor,
2222
};
2323

2424
use super::{
2525
find_breakable, BindingMode, BreakableContext, Diverges, Expectation, InferenceContext,
26-
InferenceDiagnostic, Solution, TypeMismatch,
26+
InferenceDiagnostic, TypeMismatch,
2727
};
2828

2929
impl<'a> InferenceContext<'a> {
@@ -65,52 +65,47 @@ impl<'a> InferenceContext<'a> {
6565

6666
fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
6767
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();
7268
let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
7369
let output_assoc_type =
7470
self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
75-
for fn_trait in fn_traits {
76-
let generic_params = generics(self.db.upcast(), fn_trait.into());
77-
if generic_params.len() != 2 {
78-
continue;
79-
}
80-
81-
let mut param_builder = Substs::builder(num_args);
82-
for _ in 0..num_args {
83-
param_builder = param_builder.push(self.table.new_type_var());
84-
}
85-
let arg_ty = Ty::Apply(ApplicationTy {
86-
ctor: TypeCtor::Tuple { cardinality: num_args as u16 },
87-
parameters: param_builder.build(),
88-
});
89-
let substs = Substs::build_for_generics(&generic_params)
90-
.push(ty.clone())
91-
.push(arg_ty.clone())
92-
.build();
93-
94-
let trait_ref = TraitRef { trait_: fn_trait, substs: substs.clone() };
95-
let trait_env = Arc::clone(&self.trait_env);
96-
let implements_fn_goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
97-
value: Obligation::Trait(trait_ref),
98-
environment: trait_env,
99-
});
100-
let solution = match self.db.trait_solve(krate, implements_fn_goal.value.clone()) {
101-
Some(Solution::Unique(SolutionVariables(solution)))
102-
| Some(Solution::Ambig(Guidance::Definite(SolutionVariables(solution))))
103-
| Some(Solution::Ambig(Guidance::Suggested(SolutionVariables(solution)))) => {
104-
solution
105-
}
106-
_ => continue,
107-
};
71+
let generic_params = generics(self.db.upcast(), fn_once_trait.into());
72+
if generic_params.len() != 2 {
73+
return None;
74+
}
75+
76+
let mut param_builder = Substs::builder(num_args);
77+
let mut arg_tys = vec![];
78+
for _ in 0..num_args {
79+
let arg = self.table.new_type_var();
80+
param_builder = param_builder.push(arg.clone());
81+
arg_tys.push(arg);
82+
}
83+
let parameters = param_builder.build();
84+
let arg_ty = Ty::Apply(ApplicationTy {
85+
ctor: TypeCtor::Tuple { cardinality: num_args as u16 },
86+
parameters,
87+
});
88+
let substs = Substs::build_for_generics(&generic_params)
89+
.push(ty.clone())
90+
.push(arg_ty.clone())
91+
.build();
92+
93+
let trait_env = Arc::clone(&self.trait_env);
94+
let implements_fn_trait =
95+
Obligation::Trait(TraitRef { trait_: fn_once_trait, substs: substs.clone() });
96+
let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
97+
value: implements_fn_trait.clone(),
98+
environment: trait_env,
99+
});
100+
if self.db.trait_solve(krate, goal.value).is_some() {
101+
self.obligations.push(implements_fn_trait);
108102
let output_proj_ty =
109103
crate::ProjectionTy { associated_ty: output_assoc_type, parameters: substs };
110104
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
112108
}
113-
None
114109
}
115110

116111
pub fn callable_sig(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {

crates/ra_hir_ty/src/tests/traits.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3028,7 +3028,7 @@ fn infer_box_fn_arg() {
30283028
656..667 '&self.inner': &*mut T
30293029
657..661 'self': &Box<T>
30303030
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>,)>
30323032
834..835 's': Option<i32>
30333033
838..850 'Option::None': Option<i32>
30343034
872..873 'f': Box<dyn FnOnce<(&Option<i32>,)>>
@@ -3037,7 +3037,7 @@ fn infer_box_fn_arg() {
30373037
913..915 'ps': {unknown}
30383038
917..919 '{}': ()
30393039
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>,)>
30413041
940..942 '&s': &Option<i32>
30423042
941..942 's': Option<i32>
30433043
"###
@@ -3105,9 +3105,9 @@ fn infer_dyn_fn_output() {
31053105
937..946 'box(|| 5)': Box<|| -> i32>
31063106
941..945 '|| 5': || -> i32
31073107
944..945 '5': i32
3108-
968..969 'x': i32
3108+
968..969 'x': FnOnce::Output<dyn Fn<(), Output = i32>, ()>
31093109
972..973 'f': Box<dyn Fn<(), Output = i32>>
3110-
972..975 'f()': i32
3110+
972..975 'f()': FnOnce::Output<dyn Fn<(), Output = i32>, ()>
31113111
"###
31123112
);
31133113
}

0 commit comments

Comments
 (0)