From 3d7099a9682e1911b18cf440738ab97ae2fecc6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 14 Aug 2018 16:46:28 -0700 Subject: [PATCH 1/4] Do not emit E0277 on incorrect tuple destructured binding --- src/librustc_typeck/check/_match.rs | 15 ++++++++-- src/librustc_typeck/check/demand.rs | 1 + .../ui/elide-errors-on-mismatched-tuple.rs | 28 +++++++++++++++++++ .../elide-errors-on-mismatched-tuple.stderr | 12 ++++++++ 4 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/elide-errors-on-mismatched-tuple.rs create mode 100644 src/test/ui/elide-errors-on-mismatched-tuple.stderr diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 2a8ee4bd8df0e..ca2b892018b5f 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -299,10 +299,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let element_tys = tcx.mk_type_list(element_tys_iter); let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); self.demand_eqtype(pat.span, expected, pat_ty); - for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat_walk(elem, &element_tys[i], def_bm, true); + if self.has_errors.get() { + let element_tys_iter = (0..max_len).map(|_| tcx.types.err); + let element_tys = tcx.mk_type_list(element_tys_iter); + for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { + self.check_pat_walk(elem, &tcx.types.err, def_bm, true); + } + tcx.mk_ty(ty::TyTuple(element_tys)) + } else { + for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { + self.check_pat_walk(elem, &element_tys[i], def_bm, true); + } + pat_ty } - pat_ty } PatKind::Box(ref inner) => { let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span)); diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 4e22ead8db987..47bbc95aa496b 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -50,6 +50,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { if let Some(mut err) = self.demand_eqtype_diag(sp, expected, actual) { + self.has_errors.set(true); err.emit(); } } diff --git a/src/test/ui/elide-errors-on-mismatched-tuple.rs b/src/test/ui/elide-errors-on-mismatched-tuple.rs new file mode 100644 index 0000000000000..68e579788bca1 --- /dev/null +++ b/src/test/ui/elide-errors-on-mismatched-tuple.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Hide irrelevant E0277 errors (#50333) + +trait T {} + +struct A; +impl T for A {} +impl A { + fn new() -> Self { + Self {} + } +} + +fn main() { + let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three + //~^ ERROR mismatched types + let ts: Vec<&T> = vec![&a, &b, &c]; + // There is no E0277 error above, as `a`, `b` and `c` are `TyErr` +} diff --git a/src/test/ui/elide-errors-on-mismatched-tuple.stderr b/src/test/ui/elide-errors-on-mismatched-tuple.stderr new file mode 100644 index 0000000000000..b901175d53450 --- /dev/null +++ b/src/test/ui/elide-errors-on-mismatched-tuple.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/elide-errors-on-mismatched-tuple.rs:24:9 + | +LL | let (a, b, c) = (A::new(), A::new()); // This tuple is 2 elements, should be three + | ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements + | + = note: expected type `(A, A)` + found type `(_, _, _)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 633a47becb0a64156694827fa44481b16cb4c891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 19 Aug 2018 15:12:09 -0700 Subject: [PATCH 2/4] Simplify the recovered tuple ty --- src/librustc_typeck/check/_match.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index ca2b892018b5f..b7b1751a8ea5f 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -301,11 +301,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.demand_eqtype(pat.span, expected, pat_ty); if self.has_errors.get() { let element_tys_iter = (0..max_len).map(|_| tcx.types.err); - let element_tys = tcx.mk_type_list(element_tys_iter); for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { self.check_pat_walk(elem, &tcx.types.err, def_bm, true); } - tcx.mk_ty(ty::TyTuple(element_tys)) + tcx.mk_tup(element_tys_iter) } else { for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { self.check_pat_walk(elem, &element_tys[i], def_bm, true); From 5f8bf91e968b1816f9a1c746749c2136069fbcd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 11 Sep 2018 17:06:11 -0700 Subject: [PATCH 3/4] address review comment, reduce scope --- src/librustc_typeck/check/_match.rs | 4 ++-- src/librustc_typeck/check/demand.rs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index b7b1751a8ea5f..a7b266143ba92 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -298,8 +298,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { TypeVariableOrigin::TypeInference(pat.span))); let element_tys = tcx.mk_type_list(element_tys_iter); let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); - self.demand_eqtype(pat.span, expected, pat_ty); - if self.has_errors.get() { + if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) { + err.emit(); let element_tys_iter = (0..max_len).map(|_| tcx.types.err); for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { self.check_pat_walk(elem, &tcx.types.err, def_bm, true); diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 47bbc95aa496b..4e22ead8db987 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -50,7 +50,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { if let Some(mut err) = self.demand_eqtype_diag(sp, expected, actual) { - self.has_errors.set(true); err.emit(); } } From 63cd81c7d6eecc580b72fe1b5028a35ca9e19ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 12 Sep 2018 10:47:55 -0700 Subject: [PATCH 4/4] Add comment explaining reasoning --- src/librustc_typeck/check/_match.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index a7b266143ba92..7f65a5f0b5a63 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -300,6 +300,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); if let Some(mut err) = self.demand_eqtype_diag(pat.span, expected, pat_ty) { err.emit(); + // Walk subpatterns with an expected type of `err` in this case to silence + // further errors being emitted when using the bindings. #50333 let element_tys_iter = (0..max_len).map(|_| tcx.types.err); for (_, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { self.check_pat_walk(elem, &tcx.types.err, def_bm, true);