aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-05-30 08:52:07 +0100
committerGitHub <[email protected]>2020-05-30 08:52:07 +0100
commit11f74f28271279e998f28d62034bffe9cf7610a3 (patch)
treebb41fa611ad3ef43c9f25650576b412144dd779b
parent40bdd2e161e0e29805462fe3f2a8ea624e4a38d4 (diff)
parent6f67a46a6a264ac7985a10ee19fbf9bbaef924bc (diff)
Merge #4653
4653: Fix match ergonomics in closure parameters r=matklad a=flodiebold Fixes #4476. Co-authored-by: Florian Diebold <[email protected]>
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs16
-rw-r--r--crates/ra_hir_ty/src/tests/patterns.rs50
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 54bab3476..78084cb57 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> {
140 140
141 let mut sig_tys = Vec::new(); 141 let mut sig_tys = Vec::new();
142 142
143 for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { 143 // collect explicitly written argument types
144 let expected = if let Some(type_ref) = arg_type { 144 for arg_type in arg_types.iter() {
145 let arg_ty = if let Some(type_ref) = arg_type {
145 self.make_ty(type_ref) 146 self.make_ty(type_ref)
146 } else { 147 } else {
147 Ty::Unknown 148 self.table.new_type_var()
148 }; 149 };
149 let arg_ty = self.infer_pat(*arg_pat, &expected, BindingMode::default());
150 sig_tys.push(arg_ty); 150 sig_tys.push(arg_ty);
151 } 151 }
152 152
@@ -158,7 +158,7 @@ impl<'a> InferenceContext<'a> {
158 sig_tys.push(ret_ty.clone()); 158 sig_tys.push(ret_ty.clone());
159 let sig_ty = Ty::apply( 159 let sig_ty = Ty::apply(
160 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, 160 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
161 Substs(sig_tys.into()), 161 Substs(sig_tys.clone().into()),
162 ); 162 );
163 let closure_ty = 163 let closure_ty =
164 Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty); 164 Ty::apply_one(TypeCtor::Closure { def: self.owner, expr: tgt_expr }, sig_ty);
@@ -168,6 +168,12 @@ impl<'a> InferenceContext<'a> {
168 // infer the body. 168 // infer the body.
169 self.coerce(&closure_ty, &expected.ty); 169 self.coerce(&closure_ty, &expected.ty);
170 170
171 // Now go through the argument patterns
172 for (arg_pat, arg_ty) in args.iter().zip(sig_tys) {
173 let resolved = self.resolve_ty_as_possible(arg_ty);
174 self.infer_pat(*arg_pat, &resolved, BindingMode::default());
175 }
176
171 let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); 177 let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
172 let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone()); 178 let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
173 179
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs
index 0c5f972a2..fe62587c0 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() {
520 105..107 '()': () 520 105..107 '()': ()
521 ") 521 ")
522} 522}
523
524#[test]
525fn match_ergonomics_in_closure_params() {
526 assert_snapshot!(
527 infer(r#"
528#[lang = "fn_once"]
529trait FnOnce<Args> {
530 type Output;
531}
532
533fn foo<T, U, F: FnOnce(T) -> U>(t: T, f: F) -> U { loop {} }
534
535fn test() {
536 foo(&(1, "a"), |&(x, y)| x); // normal, no match ergonomics
537 foo(&(1, "a"), |(x, y)| x);
538}
539"#),
540 @r###"
541 94..95 't': T
542 100..101 'f': F
543 111..122 '{ loop {} }': U
544 113..120 'loop {}': !
545 118..120 '{}': ()
546 134..233 '{ ... x); }': ()
547 140..143 'foo': fn foo<&(i32, &str), i32, |&(i32, &str)| -> i32>(&(i32, &str), |&(i32, &str)| -> i32) -> i32
548 140..167 'foo(&(...y)| x)': i32
549 144..153 '&(1, "a")': &(i32, &str)
550 145..153 '(1, "a")': (i32, &str)
551 146..147 '1': i32
552 149..152 '"a"': &str
553 155..166 '|&(x, y)| x': |&(i32, &str)| -> i32
554 156..163 '&(x, y)': &(i32, &str)
555 157..163 '(x, y)': (i32, &str)
556 158..159 'x': i32
557 161..162 'y': &str
558 165..166 'x': i32
559 204..207 'foo': fn foo<&(i32, &str), &i32, |&(i32, &str)| -> &i32>(&(i32, &str), |&(i32, &str)| -> &i32) -> &i32
560 204..230 'foo(&(...y)| x)': &i32
561 208..217 '&(1, "a")': &(i32, &str)
562 209..217 '(1, "a")': (i32, &str)
563 210..211 '1': i32
564 213..216 '"a"': &str
565 219..229 '|(x, y)| x': |&(i32, &str)| -> &i32
566 220..226 '(x, y)': (i32, &str)
567 221..222 'x': &i32
568 224..225 'y': &&str
569 228..229 'x': &i32
570 "###
571 );
572}