From 994d76d1ad2ccaad2ce0dc09af2431a522e8df50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Gardstr=C3=B6m?= Date: Fri, 7 Jul 2017 03:01:45 +0200 Subject: [PATCH 1/2] Fix wrong report on closure args mismatch when a ref is expected but not found. Adds new error E0622 Fixes #42143 --- src/librustc/diagnostics.rs | 1 + src/librustc/traits/error_reporting.rs | 64 +++++++++++-------- .../closure-arg-type-mismatch.rs | 21 ++++++ .../closure-arg-type-mismatch.stderr | 36 +++++++++++ 4 files changed, 97 insertions(+), 25 deletions(-) create mode 100644 src/test/ui/mismatched_types/closure-arg-type-mismatch.rs create mode 100644 src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 035640b9710e2..54a0bf6faf85c 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -2027,4 +2027,5 @@ register_diagnostics! { E0495, // cannot infer an appropriate lifetime due to conflicting requirements E0566, // conflicting representation hints E0587, // conflicting packed and align representation hints + E0622, // type mismatch in closure arguments } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 0bf0e21baaf93..51baaa89bc253 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -725,32 +725,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { expected_found.found, expected_trait_ty.is_closure()) } else if let &TypeError::Sorts(ref expected_found) = e { - let expected = if let ty::TyTuple(tys, _) = expected_found.expected.sty { - tys.len() - } else { - 1 - }; - let found = if let ty::TyTuple(tys, _) = expected_found.found.sty { - tys.len() - } else { - 1 - }; - - if expected != found { - // Expected `|| { }`, found `|x, y| { }` - // Expected `fn(x) -> ()`, found `|| { }` - self.report_arg_count_mismatch(span, - found_span, - expected, - found, - expected_trait_ty.is_closure()) + let mut count_mismatch = None; + if let ty::TyTuple(expected_tys, _) = expected_found.expected.sty { + if let ty::TyTuple(found_tys, _) = expected_found.found.sty { + if expected_tys.len() != found_tys.len() { + // Expected `|| { }`, found `|x, y| { }` + // Expected `fn(x) -> ()`, found `|| { }` + count_mismatch = Some(self.report_arg_count_mismatch(span, + found_span, + expected_tys.len(), + found_tys.len(), + expected_trait_ty.is_closure())); + } + } + } + if let Some(count_mismatch) = count_mismatch { + count_mismatch } else { - self.report_type_argument_mismatch(span, - found_span, - expected_trait_ty, - expected_trait_ref, - actual_trait_ref, - e) + self.report_closure_arg_mismatch(span, + found_span, + expected_trait_ref, + actual_trait_ref) } } else { self.report_type_argument_mismatch(span, @@ -825,6 +820,25 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } err } + + fn report_closure_arg_mismatch(&self, + span: Span, + found_span: Option, + expected_ref: ty::PolyTraitRef<'tcx>, + found: ty::PolyTraitRef<'tcx>) + -> DiagnosticBuilder<'tcx> + { + let mut err = struct_span_err!(self.tcx.sess, span, E0622, + "type mismatch in closure arguments"); + if let Some(sp) = found_span { + err.span_label(span, format!("expected closure that takes a `{}`", found)); + err.span_label(sp, format!("takes a `{}`", expected_ref)); + } else { + panic!(); + } + + err + } } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs new file mode 100644 index 0000000000000..d451dc086864b --- /dev/null +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -0,0 +1,21 @@ +// Copyright 2017 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. + +use std::ops::{FnOnce, Fn}; + +pub fn main() { + let a = [(1u32,2u32)]; + let b = a.iter().map(|x: (u32, u32)| 45); + let d1 = a.iter().map(|x: &(u16,u16)| 45); + let d2 = a.iter().map(|x: (u16,u16)| 45); + foo(|y: isize| ()); +} + +fn foo(m: F) where F: Fn(usize) {} \ No newline at end of file diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr new file mode 100644 index 0000000000000..1479282ac3c11 --- /dev/null +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -0,0 +1,36 @@ +error[E0622]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:15:26 + | +15 | let b = a.iter().map(|x: (u32, u32)| 45); + | ^^^ ------------------ takes a `std::ops::FnMut<((u32, u32),)>` + | | + | expected closure that takes a `std::ops::FnMut<(&(u32, u32),)>` + +error[E0622]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:16:27 + | +16 | let d1 = a.iter().map(|x: &(u16,u16)| 45); + | ^^^ ------------------ takes a `for<'r> std::ops::FnMut<(&'r (u16, u16),)>` + | | + | expected closure that takes a `std::ops::FnMut<(&(u32, u32),)>` + +error[E0622]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:17:27 + | +17 | let d2 = a.iter().map(|x: (u16,u16)| 45); + | ^^^ ----------------- takes a `std::ops::FnMut<((u16, u16),)>` + | | + | expected closure that takes a `std::ops::FnMut<(&(u32, u32),)>` + +error[E0622]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:18:9 + | +18 | foo(|y: isize| ()); + | ^^^ ------------- takes a `std::ops::Fn<(isize,)>` + | | + | expected closure that takes a `std::ops::Fn<(usize,)>` + | + = note: required by `foo` + +error: aborting due to 4 previous errors + From 74cb9b97e7b47e6d7c2170ce019965f0e4ab4737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Gardstr=C3=B6m?= Date: Fri, 7 Jul 2017 04:46:53 +0200 Subject: [PATCH 2/2] Fix trailing whitespace and duplicate error code. New error code is E0623 Also cleanup/fix ui test --- src/librustc/diagnostics.rs | 2 +- src/librustc/traits/error_reporting.rs | 7 +++--- .../closure-arg-type-mismatch.rs | 6 ++--- .../closure-arg-type-mismatch.stderr | 24 +++++++++---------- 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 54a0bf6faf85c..707f8bc9c60d2 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -2027,5 +2027,5 @@ register_diagnostics! { E0495, // cannot infer an appropriate lifetime due to conflicting requirements E0566, // conflicting representation hints E0587, // conflicting packed and align representation hints - E0622, // type mismatch in closure arguments + E0623, // type mismatch in closure arguments } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 51baaa89bc253..535057c9a4269 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -728,7 +728,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let mut count_mismatch = None; if let ty::TyTuple(expected_tys, _) = expected_found.expected.sty { if let ty::TyTuple(found_tys, _) = expected_found.found.sty { - if expected_tys.len() != found_tys.len() { + if expected_tys.len() != found_tys.len() { // Expected `|| { }`, found `|x, y| { }` // Expected `fn(x) -> ()`, found `|| { }` count_mismatch = Some(self.report_arg_count_mismatch(span, @@ -745,7 +745,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.report_closure_arg_mismatch(span, found_span, expected_trait_ref, - actual_trait_ref) + actual_trait_ref) } } else { self.report_type_argument_mismatch(span, @@ -828,7 +828,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { found: ty::PolyTraitRef<'tcx>) -> DiagnosticBuilder<'tcx> { - let mut err = struct_span_err!(self.tcx.sess, span, E0622, + let mut err = struct_span_err!(self.tcx.sess, span, E0623, "type mismatch in closure arguments"); if let Some(sp) = found_span { err.span_label(span, format!("expected closure that takes a `{}`", found)); @@ -836,7 +836,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } else { panic!(); } - err } } diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs index d451dc086864b..a76790bce7aeb 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::ops::{FnOnce, Fn}; - -pub fn main() { +fn main() { let a = [(1u32,2u32)]; let b = a.iter().map(|x: (u32, u32)| 45); let d1 = a.iter().map(|x: &(u16,u16)| 45); @@ -18,4 +16,4 @@ pub fn main() { foo(|y: isize| ()); } -fn foo(m: F) where F: Fn(usize) {} \ No newline at end of file +fn foo(m: F) where F: ::std::ops::Fn(usize) {} \ No newline at end of file diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr index 1479282ac3c11..79c62f7577841 100644 --- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -1,31 +1,31 @@ -error[E0622]: type mismatch in closure arguments - --> $DIR/closure-arg-type-mismatch.rs:15:26 +error[E0623]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:13:26 | -15 | let b = a.iter().map(|x: (u32, u32)| 45); +13 | let b = a.iter().map(|x: (u32, u32)| 45); | ^^^ ------------------ takes a `std::ops::FnMut<((u32, u32),)>` | | | expected closure that takes a `std::ops::FnMut<(&(u32, u32),)>` -error[E0622]: type mismatch in closure arguments - --> $DIR/closure-arg-type-mismatch.rs:16:27 +error[E0623]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:14:27 | -16 | let d1 = a.iter().map(|x: &(u16,u16)| 45); +14 | let d1 = a.iter().map(|x: &(u16,u16)| 45); | ^^^ ------------------ takes a `for<'r> std::ops::FnMut<(&'r (u16, u16),)>` | | | expected closure that takes a `std::ops::FnMut<(&(u32, u32),)>` -error[E0622]: type mismatch in closure arguments - --> $DIR/closure-arg-type-mismatch.rs:17:27 +error[E0623]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:15:27 | -17 | let d2 = a.iter().map(|x: (u16,u16)| 45); +15 | let d2 = a.iter().map(|x: (u16,u16)| 45); | ^^^ ----------------- takes a `std::ops::FnMut<((u16, u16),)>` | | | expected closure that takes a `std::ops::FnMut<(&(u32, u32),)>` -error[E0622]: type mismatch in closure arguments - --> $DIR/closure-arg-type-mismatch.rs:18:9 +error[E0623]: type mismatch in closure arguments + --> $DIR/closure-arg-type-mismatch.rs:16:9 | -18 | foo(|y: isize| ()); +16 | foo(|y: isize| ()); | ^^^ ------------- takes a `std::ops::Fn<(isize,)>` | | | expected closure that takes a `std::ops::Fn<(usize,)>`