From 052bdff8fbaef9b3c32eec842fc9c03877651cf5 Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 15 Nov 2018 16:35:23 +0800 Subject: [PATCH 1/3] lint based on closure pipe span --- src/librustc/traits/error_reporting.rs | 16 +++++++++++++++- .../ui/mismatched_types/closure-arg-count.rs | 2 ++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 2761a954cea88..d08a4b47b31bf 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1092,13 +1092,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Some(found_span) = found_span { err.span_label(found_span, format!("takes {}", found_str)); + // move |_| { ... } + // ^^^^^^^^-- def_span + // + // move |_| { ... } + // ^^^^^-- prefix + let prefix_span = self.tcx.sess.source_map().span_until_char(found_span, '|'); + // move |_| { ... } + // ^^^-- pipe_span + let pipe_span = if let Some(span) = found_span.trim_start(prefix_span) { + span + } else { + found_span + }; + // Suggest to take and ignore the arguments with expected_args_length `_`s if // found arguments is empty (assume the user just wants to ignore args in this case). // For example, if `expected_args_length` is 2, suggest `|_, _|`. if found_args.is_empty() && is_closure { let underscores = vec!["_"; expected_args.len()].join(", "); err.span_suggestion_with_applicability( - found_span, + pipe_span, &format!( "consider changing the closure to take and ignore the expected argument{}", if expected_args.len() < 2 { diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs index 9eb11148a8bce..ed9162d234892 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.rs +++ b/src/test/ui/mismatched_types/closure-arg-count.rs @@ -22,6 +22,8 @@ fn main() { //~^ ERROR closure is expected to take f(|| panic!()); //~^ ERROR closure is expected to take + f(move || panic!()); + //~^ ERROR closure is expected to take let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i); //~^ ERROR closure is expected to take From dbd9abd74d1ca8329f483c30ba04526d8c45a5ac Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 15 Nov 2018 22:17:49 +0800 Subject: [PATCH 2/3] update closure arg suggesstion ui test --- .../mismatched_types/closure-arg-count.stderr | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 057cf6efa1dea..89977aadf88f0 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -60,8 +60,26 @@ help: consider changing the closure to take and ignore the expected argument LL | f(|_| panic!()); | ^^^ +error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments + --> $DIR/closure-arg-count.rs:25:5 + | +LL | f(move || panic!()); + | ^ ------- takes 0 arguments + | | + | expected closure that takes 1 argument + | +note: required by `f` + --> $DIR/closure-arg-count.rs:13:1 + | +LL | fn f>(_: F) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider changing the closure to take and ignore the expected argument + | +LL | f(move|_| panic!()); + | ^^^ + error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments - --> $DIR/closure-arg-count.rs:26:53 + --> $DIR/closure-arg-count.rs:28:53 | LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i); | ^^^ ------ takes 2 distinct arguments @@ -73,7 +91,7 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i); | ^^^^^^^^ error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments - --> $DIR/closure-arg-count.rs:28:53 + --> $DIR/closure-arg-count.rs:30:53 | LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i: usize, x| i); | ^^^ ------------- takes 2 distinct arguments @@ -85,7 +103,7 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|(i, x)| i); | ^^^^^^^^ error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments - --> $DIR/closure-arg-count.rs:30:53 + --> $DIR/closure-arg-count.rs:32:53 | LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i); | ^^^ --------- takes 3 distinct arguments @@ -93,7 +111,7 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x, y| i); | expected closure that takes a single 2-tuple as argument error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 0 arguments - --> $DIR/closure-arg-count.rs:32:53 + --> $DIR/closure-arg-count.rs:34:53 | LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(foo); | ^^^ expected function that takes a single 2-tuple as argument @@ -102,7 +120,7 @@ LL | fn foo() {} | -------- takes 0 arguments error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 3 distinct arguments - --> $DIR/closure-arg-count.rs:35:53 + --> $DIR/closure-arg-count.rs:37:53 | LL | let bar = |i, x, y| i; | --------- takes 3 distinct arguments @@ -110,7 +128,7 @@ LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(bar); | ^^^ expected closure that takes a single 2-tuple as argument error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments - --> $DIR/closure-arg-count.rs:37:53 + --> $DIR/closure-arg-count.rs:39:53 | LL | let _it = vec![1, 2, 3].into_iter().enumerate().map(qux); | ^^^ expected function that takes a single 2-tuple as argument @@ -119,13 +137,13 @@ LL | fn qux(x: usize, y: usize) {} | -------------------------- takes 2 distinct arguments error[E0593]: function is expected to take 1 argument, but it takes 2 arguments - --> $DIR/closure-arg-count.rs:40:41 + --> $DIR/closure-arg-count.rs:42:41 | LL | let _it = vec![1, 2, 3].into_iter().map(usize::checked_add); | ^^^ expected function that takes 1 argument error[E0593]: function is expected to take 0 arguments, but it takes 1 argument - --> $DIR/closure-arg-count.rs:43:5 + --> $DIR/closure-arg-count.rs:45:5 | LL | call(Foo); | ^^^^ expected function that takes 0 arguments @@ -134,11 +152,11 @@ LL | struct Foo(u8); | --------------- takes 1 argument | note: required by `call` - --> $DIR/closure-arg-count.rs:50:1 + --> $DIR/closure-arg-count.rs:52:1 | LL | fn call(_: F) where F: FnOnce() -> R {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 13 previous errors +error: aborting due to 14 previous errors For more information about this error, try `rustc --explain E0593`. From d93e5b04f4817718480d17eafa0ee5e7bbe1f019 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 17 Nov 2018 17:57:17 +0800 Subject: [PATCH 3/3] reserve whitespaces between prefix and pipe --- src/librustc/traits/error_reporting.rs | 2 +- src/test/ui/mismatched_types/closure-arg-count.rs | 2 +- src/test/ui/mismatched_types/closure-arg-count.stderr | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index d08a4b47b31bf..48b2b25d6adf9 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1097,7 +1097,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // // move |_| { ... } // ^^^^^-- prefix - let prefix_span = self.tcx.sess.source_map().span_until_char(found_span, '|'); + let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span); // move |_| { ... } // ^^^-- pipe_span let pipe_span = if let Some(span) = found_span.trim_start(prefix_span) { diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs index ed9162d234892..2dcc7a25c8401 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.rs +++ b/src/test/ui/mismatched_types/closure-arg-count.rs @@ -22,7 +22,7 @@ fn main() { //~^ ERROR closure is expected to take f(|| panic!()); //~^ ERROR closure is expected to take - f(move || panic!()); + f( move || panic!()); //~^ ERROR closure is expected to take let _it = vec![1, 2, 3].into_iter().enumerate().map(|i, x| i); diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 89977aadf88f0..eeadf07262c3e 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -63,8 +63,8 @@ LL | f(|_| panic!()); error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments --> $DIR/closure-arg-count.rs:25:5 | -LL | f(move || panic!()); - | ^ ------- takes 0 arguments +LL | f( move || panic!()); + | ^ ---------- takes 0 arguments | | | expected closure that takes 1 argument | @@ -75,8 +75,8 @@ LL | fn f>(_: F) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing the closure to take and ignore the expected argument | -LL | f(move|_| panic!()); - | ^^^ +LL | f( move |_| panic!()); + | ^^^ error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments --> $DIR/closure-arg-count.rs:28:53