Skip to content

Commit f0c8058

Browse files
committed
Fixes to callable_sig_from_fn_trait
1 parent 38f6cdb commit f0c8058

File tree

2 files changed

+72
-67
lines changed

2 files changed

+72
-67
lines changed

crates/ra_hir_ty/src/infer/expr.rs

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

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

2424
use super::{
@@ -63,72 +63,70 @@ impl<'a> InferenceContext<'a> {
6363
self.resolve_ty_as_possible(ty)
6464
}
6565

66-
fn callable_sig_from_fn_trait(&mut self, ty: &Ty) -> Option<FnSig> {
67-
if let Some(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-
for fn_trait in fn_traits {
73-
let fn_trait_data = self.db.trait_data(fn_trait);
74-
let generic_params = generics(self.db.upcast(), fn_trait.into());
75-
if generic_params.len() != 2 {
76-
continue;
77-
}
78-
79-
let arg_ty = self.table.new_type_var();
80-
let substs = Substs::build_for_generics(&generic_params)
81-
.push(ty.clone())
82-
.push(arg_ty.clone())
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-
}
66+
fn callable_sig_from_fn_trait(&mut self, ty: &Ty, num_args: usize) -> Option<(Vec<Ty>, Ty)> {
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)?;
73+
let output_assoc_type = match self
74+
.db
75+
.trait_data(fn_once_trait)
76+
.associated_types()
77+
.collect::<Vec<hir_def::TypeAliasId>>()
78+
.as_slice()
79+
{
80+
[output] => *output,
81+
_ => {
82+
return None;
12383
}
12484
};
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+
}
125123
None
126124
}
127125

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)> {
129127
match ty.callable_sig(self.db) {
130-
result @ Some(_) => result,
131-
None => self.callable_sig_from_fn_trait(ty),
128+
Some(sig) => Some((sig.params().to_vec(), sig.ret().clone())),
129+
None => self.callable_sig_from_fn_trait(ty, num_args),
132130
}
133131
}
134132

@@ -278,8 +276,10 @@ impl<'a> InferenceContext<'a> {
278276
);
279277
let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs
280278
.find_map(|callee_deref_ty| {
281-
self.callable_sig(&canonicalized.decanonicalize_ty(callee_deref_ty.value))
282-
.map(|sig| (sig.params().to_vec(), sig.ret().clone()))
279+
self.callable_sig(
280+
&canonicalized.decanonicalize_ty(callee_deref_ty.value),
281+
args.len(),
282+
)
283283
})
284284
.unwrap_or((Vec::new(), Ty::Unknown));
285285
self.register_obligations_for_call(&callee_ty);

crates/ra_ide/src/hover.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2438,10 +2438,15 @@ fn func(foo: i32) { if true { <|>foo; }; }
24382438
r#"
24392439
//- /lib.rs deps:std
24402440
2441-
#[lang = "fn"]
2442-
pub trait Fn<Args> {
2441+
#[lang = "fn_once"]
2442+
pub trait FnOnce<Args> {
24432443
type Output;
24442444
2445+
extern "rust-call" fn call_once(&self, args: Args) -> Self::Output;
2446+
}
2447+
2448+
#[lang = "fn"]
2449+
pub trait Fn<Args>:FnOnce<Args> {
24452450
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
24462451
}
24472452

0 commit comments

Comments
 (0)