Push obligation instead of matching on solution
This commit is contained in:
parent
d8f5192d99
commit
1629fb770e
@ -15,7 +15,7 @@ use ra_syntax::ast::RangeOp;
|
||||
|
||||
use crate::{
|
||||
autoderef, method_resolution, op,
|
||||
traits::{FnTrait, Guidance, InEnvironment, SolutionVariables},
|
||||
traits::{FnTrait, InEnvironment},
|
||||
utils::{generics, variant_data, Generics},
|
||||
ApplicationTy, Binders, CallableDef, InferTy, IntTy, Mutability, Obligation, Rawness, Substs,
|
||||
TraitRef, Ty, TypeCtor,
|
||||
@ -23,7 +23,7 @@ use crate::{
|
||||
|
||||
use super::{
|
||||
find_breakable, BindingMode, BreakableContext, Diverges, Expectation, InferenceContext,
|
||||
InferenceDiagnostic, Solution, TypeMismatch,
|
||||
InferenceDiagnostic, TypeMismatch,
|
||||
};
|
||||
|
||||
impl<'a> InferenceContext<'a> {
|
||||
@ -65,52 +65,47 @@ impl<'a> InferenceContext<'a> {
|
||||
|
||||
fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
|
||||
let krate = self.resolver.krate()?;
|
||||
let fn_traits: Vec<crate::TraitId> = [FnTrait::FnOnce, FnTrait::FnMut, FnTrait::Fn]
|
||||
.iter()
|
||||
.filter_map(|f| f.get_id(self.db, krate))
|
||||
.collect();
|
||||
let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
|
||||
let output_assoc_type =
|
||||
self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
|
||||
for fn_trait in fn_traits {
|
||||
let generic_params = generics(self.db.upcast(), fn_trait.into());
|
||||
if generic_params.len() != 2 {
|
||||
continue;
|
||||
}
|
||||
let generic_params = generics(self.db.upcast(), fn_once_trait.into());
|
||||
if generic_params.len() != 2 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut param_builder = Substs::builder(num_args);
|
||||
for _ in 0..num_args {
|
||||
param_builder = param_builder.push(self.table.new_type_var());
|
||||
}
|
||||
let arg_ty = Ty::Apply(ApplicationTy {
|
||||
ctor: TypeCtor::Tuple { cardinality: num_args as u16 },
|
||||
parameters: param_builder.build(),
|
||||
});
|
||||
let substs = Substs::build_for_generics(&generic_params)
|
||||
.push(ty.clone())
|
||||
.push(arg_ty.clone())
|
||||
.build();
|
||||
let mut param_builder = Substs::builder(num_args);
|
||||
let mut arg_tys = vec![];
|
||||
for _ in 0..num_args {
|
||||
let arg = self.table.new_type_var();
|
||||
param_builder = param_builder.push(arg.clone());
|
||||
arg_tys.push(arg);
|
||||
}
|
||||
let parameters = param_builder.build();
|
||||
let arg_ty = Ty::Apply(ApplicationTy {
|
||||
ctor: TypeCtor::Tuple { cardinality: num_args as u16 },
|
||||
parameters,
|
||||
});
|
||||
let substs = Substs::build_for_generics(&generic_params)
|
||||
.push(ty.clone())
|
||||
.push(arg_ty.clone())
|
||||
.build();
|
||||
|
||||
let trait_ref = TraitRef { trait_: fn_trait, substs: substs.clone() };
|
||||
let trait_env = Arc::clone(&self.trait_env);
|
||||
let implements_fn_goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
|
||||
value: Obligation::Trait(trait_ref),
|
||||
environment: trait_env,
|
||||
});
|
||||
let solution = match self.db.trait_solve(krate, implements_fn_goal.value.clone()) {
|
||||
Some(Solution::Unique(SolutionVariables(solution)))
|
||||
| Some(Solution::Ambig(Guidance::Definite(SolutionVariables(solution))))
|
||||
| Some(Solution::Ambig(Guidance::Suggested(SolutionVariables(solution)))) => {
|
||||
solution
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
let trait_env = Arc::clone(&self.trait_env);
|
||||
let implements_fn_trait =
|
||||
Obligation::Trait(TraitRef { trait_: fn_once_trait, substs: substs.clone() });
|
||||
let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
|
||||
value: implements_fn_trait.clone(),
|
||||
environment: trait_env,
|
||||
});
|
||||
if self.db.trait_solve(krate, goal.value).is_some() {
|
||||
self.obligations.push(implements_fn_trait);
|
||||
let output_proj_ty =
|
||||
crate::ProjectionTy { associated_ty: output_assoc_type, parameters: substs };
|
||||
let return_ty = self.normalize_projection_ty(output_proj_ty);
|
||||
return Some((solution.value, return_ty));
|
||||
Some((arg_tys, return_ty))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn callable_sig(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
|
||||
|
@ -3028,7 +3028,7 @@ fn infer_box_fn_arg() {
|
||||
656..667 '&self.inner': &*mut T
|
||||
657..661 'self': &Box<T>
|
||||
657..667 'self.inner': *mut T
|
||||
812..957 '{ ... }': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, ({unknown},)>
|
||||
812..957 '{ ... }': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)>
|
||||
834..835 's': Option<i32>
|
||||
838..850 'Option::None': Option<i32>
|
||||
872..873 'f': Box<dyn FnOnce<(&Option<i32>,)>>
|
||||
@ -3037,7 +3037,7 @@ fn infer_box_fn_arg() {
|
||||
913..915 'ps': {unknown}
|
||||
917..919 '{}': ()
|
||||
938..939 'f': Box<dyn FnOnce<(&Option<i32>,)>>
|
||||
938..943 'f(&s)': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, ({unknown},)>
|
||||
938..943 'f(&s)': FnOnce::Output<dyn FnOnce<(&Option<i32>,)>, (&Option<i32>,)>
|
||||
940..942 '&s': &Option<i32>
|
||||
941..942 's': Option<i32>
|
||||
"###
|
||||
@ -3105,9 +3105,9 @@ fn infer_dyn_fn_output() {
|
||||
937..946 'box(|| 5)': Box<|| -> i32>
|
||||
941..945 '|| 5': || -> i32
|
||||
944..945 '5': i32
|
||||
968..969 'x': i32
|
||||
968..969 'x': FnOnce::Output<dyn Fn<(), Output = i32>, ()>
|
||||
972..973 'f': Box<dyn Fn<(), Output = i32>>
|
||||
972..975 'f()': i32
|
||||
972..975 'f()': FnOnce::Output<dyn Fn<(), Output = i32>, ()>
|
||||
"###
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user