From 6f67a46a6a264ac7985a10ee19fbf9bbaef924bc Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 29 May 2020 17:35:57 +0200 Subject: [PATCH] Fix match ergonomics in closure parameters Fixes #4476. --- crates/ra_hir_ty/src/infer/expr.rs | 16 ++++++--- crates/ra_hir_ty/src/tests/patterns.rs | 50 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 54bab3476c7..78084cb573c 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -140,13 +140,13 @@ impl<'a> InferenceContext<'a> { let mut sig_tys = Vec::new(); - for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { - let expected = if let Some(type_ref) = arg_type { + // collect explicitly written argument types + for arg_type in arg_types.iter() { + let arg_ty = if let Some(type_ref) = arg_type { self.make_ty(type_ref) } else { - Ty::Unknown + self.table.new_type_var() }; - let arg_ty = self.infer_pat(*arg_pat, &expected, BindingMode::default()); sig_tys.push(arg_ty); } @@ -158,7 +158,7 @@ impl<'a> InferenceContext<'a> { sig_tys.push(ret_ty.clone()); let sig_ty = Ty::apply( TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, - Substs(sig_tys.into()), + Substs(sig_tys.clone().into()), ); let closure_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. 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_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs index 0c5f972a2c6..fe62587c0d7 100644 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ b/crates/ra_hir_ty/src/tests/patterns.rs @@ -520,3 +520,53 @@ fn main() { 105..107 '()': () ") } + +#[test] +fn match_ergonomics_in_closure_params() { + assert_snapshot!( + infer(r#" +#[lang = "fn_once"] +trait FnOnce { + type Output; +} + +fn foo 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 + "### + ); +}