mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 04:44:57 +00:00
Merge #4653
4653: Fix match ergonomics in closure parameters r=matklad a=flodiebold Fixes #4476. Co-authored-by: Florian Diebold <florian.diebold@freiheit.com>
This commit is contained in:
commit
11f74f2827
2 changed files with 61 additions and 5 deletions
|
@ -140,13 +140,13 @@ impl<'a> InferenceContext<'a> {
|
||||||
|
|
||||||
let mut sig_tys = Vec::new();
|
let mut sig_tys = Vec::new();
|
||||||
|
|
||||||
for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) {
|
// collect explicitly written argument types
|
||||||
let expected = if let Some(type_ref) = arg_type {
|
for arg_type in arg_types.iter() {
|
||||||
|
let arg_ty = if let Some(type_ref) = arg_type {
|
||||||
self.make_ty(type_ref)
|
self.make_ty(type_ref)
|
||||||
} else {
|
} else {
|
||||||
Ty::Unknown
|
self.table.new_type_var()
|
||||||
};
|
};
|
||||||
let arg_ty = self.infer_pat(*arg_pat, &expected, BindingMode::default());
|
|
||||||
sig_tys.push(arg_ty);
|
sig_tys.push(arg_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
sig_tys.push(ret_ty.clone());
|
sig_tys.push(ret_ty.clone());
|
||||||
let sig_ty = Ty::apply(
|
let sig_ty = Ty::apply(
|
||||||
TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
|
TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
|
||||||
Substs(sig_tys.into()),
|
Substs(sig_tys.clone().into()),
|
||||||
);
|
);
|
||||||
let closure_ty =
|
let closure_ty =
|
||||||
Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty);
|
Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty);
|
||||||
|
@ -168,6 +168,12 @@ impl<'a> InferenceContext<'a> {
|
||||||
// infer the body.
|
// infer the body.
|
||||||
self.coerce(&closure_ty, &expected.ty);
|
self.coerce(&closure_ty, &expected.ty);
|
||||||
|
|
||||||
|
// Now go through the argument patterns
|
||||||
|
for (arg_pat, arg_ty) in args.iter().zip(sig_tys) {
|
||||||
|
let resolved = self.resolve_ty_as_possible(arg_ty);
|
||||||
|
self.infer_pat(*arg_pat, &resolved, BindingMode::default());
|
||||||
|
}
|
||||||
|
|
||||||
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
||||||
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
|
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
|
||||||
|
|
||||||
|
|
|
@ -520,3 +520,53 @@ fn main() {
|
||||||
105..107 '()': ()
|
105..107 '()': ()
|
||||||
")
|
")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn match_ergonomics_in_closure_params() {
|
||||||
|
assert_snapshot!(
|
||||||
|
infer(r#"
|
||||||
|
#[lang = "fn_once"]
|
||||||
|
trait FnOnce<Args> {
|
||||||
|
type Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo<T, U, F: FnOnce(T) -> U>(t: T, f: F) -> U { loop {} }
|
||||||
|
|
||||||
|
fn test() {
|
||||||
|
foo(&(1, "a"), |&(x, y)| x); // normal, no match ergonomics
|
||||||
|
foo(&(1, "a"), |(x, y)| x);
|
||||||
|
}
|
||||||
|
"#),
|
||||||
|
@r###"
|
||||||
|
94..95 't': T
|
||||||
|
100..101 'f': F
|
||||||
|
111..122 '{ loop {} }': U
|
||||||
|
113..120 'loop {}': !
|
||||||
|
118..120 '{}': ()
|
||||||
|
134..233 '{ ... x); }': ()
|
||||||
|
140..143 'foo': fn foo<&(i32, &str), i32, |&(i32, &str)| -> i32>(&(i32, &str), |&(i32, &str)| -> i32) -> i32
|
||||||
|
140..167 'foo(&(...y)| x)': i32
|
||||||
|
144..153 '&(1, "a")': &(i32, &str)
|
||||||
|
145..153 '(1, "a")': (i32, &str)
|
||||||
|
146..147 '1': i32
|
||||||
|
149..152 '"a"': &str
|
||||||
|
155..166 '|&(x, y)| x': |&(i32, &str)| -> i32
|
||||||
|
156..163 '&(x, y)': &(i32, &str)
|
||||||
|
157..163 '(x, y)': (i32, &str)
|
||||||
|
158..159 'x': i32
|
||||||
|
161..162 'y': &str
|
||||||
|
165..166 'x': i32
|
||||||
|
204..207 'foo': fn foo<&(i32, &str), &i32, |&(i32, &str)| -> &i32>(&(i32, &str), |&(i32, &str)| -> &i32) -> &i32
|
||||||
|
204..230 'foo(&(...y)| x)': &i32
|
||||||
|
208..217 '&(1, "a")': &(i32, &str)
|
||||||
|
209..217 '(1, "a")': (i32, &str)
|
||||||
|
210..211 '1': i32
|
||||||
|
213..216 '"a"': &str
|
||||||
|
219..229 '|(x, y)| x': |&(i32, &str)| -> &i32
|
||||||
|
220..226 '(x, y)': (i32, &str)
|
||||||
|
221..222 'x': &i32
|
||||||
|
224..225 'y': &&str
|
||||||
|
228..229 'x': &i32
|
||||||
|
"###
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue