From 5dab3c5cf5383b1866b374d74305196b72a0b593 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 10 Sep 2021 18:16:58 -0700 Subject: [PATCH 1/4] feat(rustc_typeck): suggest removing bad parens in `(recv.method)()` Fixes #88803 --- compiler/rustc_typeck/src/check/expr.rs | 18 +++++++++++++++++- .../ui/typeck/issue-88803-call-expr-method.rs | 7 +++++++ .../typeck/issue-88803-call-expr-method.stderr | 12 ++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/typeck/issue-88803-call-expr-method.rs create mode 100644 src/test/ui/typeck/issue-88803-call-expr-method.stderr diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index d578fac4cdb22..8513659344018 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1842,7 +1842,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_t ); err.span_label(field.span, "method, not a field"); - if !self.expr_in_place(expr.hir_id) { + let expr_is_call = if let hir::Node::Expr(parent_expr) = + self.tcx.hir().get(self.tcx.hir().get_parent_node(expr.hir_id)) + { + matches!(parent_expr.kind, ExprKind::Call(..)) + } else { + false + }; + let expr_snippet = + self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap_or(String::new()); + if expr_is_call && expr_snippet.starts_with("(") && expr_snippet.ends_with(")") { + err.span_suggestion_short( + expr.span, + "remove wrapping parentheses to call the method", + expr_snippet[1..expr_snippet.len() - 1].to_owned(), + Applicability::MachineApplicable, + ); + } else if !self.expr_in_place(expr.hir_id) { self.suggest_method_call( &mut err, "use parentheses to call the method", diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.rs b/src/test/ui/typeck/issue-88803-call-expr-method.rs new file mode 100644 index 0000000000000..fba233eec9b00 --- /dev/null +++ b/src/test/ui/typeck/issue-88803-call-expr-method.rs @@ -0,0 +1,7 @@ +fn main() { + let a = Some(42); + println!( + "The value is {}.", + (a.unwrap)() //~ERROR [E0615] + ); +} diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.stderr b/src/test/ui/typeck/issue-88803-call-expr-method.stderr new file mode 100644 index 0000000000000..9383848db941f --- /dev/null +++ b/src/test/ui/typeck/issue-88803-call-expr-method.stderr @@ -0,0 +1,12 @@ +error[E0615]: attempted to take value of method `unwrap` on type `Option<{integer}>` + --> $DIR/issue-88803-call-expr-method.rs:5:12 + | +LL | (a.unwrap)() + | ---^^^^^^- + | | | + | | method, not a field + | help: remove wrapping parentheses to call the method + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0615`. From e5c2412e52019ef35f9c6b3524cd5caf972e26b7 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 10 Sep 2021 18:34:51 -0700 Subject: [PATCH 2/4] Add the corrections stuff to the 88803 test case --- src/test/ui/typeck/issue-88803-call-expr-method.fixed | 9 +++++++++ src/test/ui/typeck/issue-88803-call-expr-method.rs | 2 ++ src/test/ui/typeck/issue-88803-call-expr-method.stderr | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/typeck/issue-88803-call-expr-method.fixed diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.fixed b/src/test/ui/typeck/issue-88803-call-expr-method.fixed new file mode 100644 index 0000000000000..19b96ecf3fc3a --- /dev/null +++ b/src/test/ui/typeck/issue-88803-call-expr-method.fixed @@ -0,0 +1,9 @@ +// run-rustfix + +fn main() { + let a = Some(42); + println!( + "The value is {}.", + a.unwrap() //~ERROR [E0615] + ); +} diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.rs b/src/test/ui/typeck/issue-88803-call-expr-method.rs index fba233eec9b00..a061994663749 100644 --- a/src/test/ui/typeck/issue-88803-call-expr-method.rs +++ b/src/test/ui/typeck/issue-88803-call-expr-method.rs @@ -1,3 +1,5 @@ +// run-rustfix + fn main() { let a = Some(42); println!( diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.stderr b/src/test/ui/typeck/issue-88803-call-expr-method.stderr index 9383848db941f..4b7ea95dee2a7 100644 --- a/src/test/ui/typeck/issue-88803-call-expr-method.stderr +++ b/src/test/ui/typeck/issue-88803-call-expr-method.stderr @@ -1,5 +1,5 @@ error[E0615]: attempted to take value of method `unwrap` on type `Option<{integer}>` - --> $DIR/issue-88803-call-expr-method.rs:5:12 + --> $DIR/issue-88803-call-expr-method.rs:7:12 | LL | (a.unwrap)() | ---^^^^^^- From d98892b67f9b1f04c8c3c90cd99cd24738fd30ba Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 10 Sep 2021 18:48:25 -0700 Subject: [PATCH 3/4] Make sure the call span parens check only fires on the callee, not args --- compiler/rustc_typeck/src/check/expr.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 8513659344018..61d5b6985f1bf 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1842,13 +1842,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_t ); err.span_label(field.span, "method, not a field"); - let expr_is_call = if let hir::Node::Expr(parent_expr) = - self.tcx.hir().get(self.tcx.hir().get_parent_node(expr.hir_id)) - { - matches!(parent_expr.kind, ExprKind::Call(..)) - } else { - false - }; + let expr_is_call = + if let hir::Node::Expr(hir::Expr { kind: ExprKind::Call(callee, _args), .. }) = + self.tcx.hir().get(self.tcx.hir().get_parent_node(expr.hir_id)) + { + expr.hir_id == callee.hir_id + } else { + false + }; let expr_snippet = self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap_or(String::new()); if expr_is_call && expr_snippet.starts_with("(") && expr_snippet.ends_with(")") { From 8be729cdd6473859f4fb54aaf74dce56f0775ef1 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 12 Sep 2021 19:51:09 -0700 Subject: [PATCH 4/4] chore: convert to a multi-part suggestion --- compiler/rustc_typeck/src/check/expr.rs | 10 +++++++--- .../ui/typeck/issue-88803-call-expr-method.stderr | 11 +++++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 61d5b6985f1bf..f4e3c8e0d9f7f 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1853,10 +1853,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expr_snippet = self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap_or(String::new()); if expr_is_call && expr_snippet.starts_with("(") && expr_snippet.ends_with(")") { - err.span_suggestion_short( - expr.span, + let after_open = expr.span.lo() + rustc_span::BytePos(1); + let before_close = expr.span.hi() - rustc_span::BytePos(1); + err.multipart_suggestion( "remove wrapping parentheses to call the method", - expr_snippet[1..expr_snippet.len() - 1].to_owned(), + vec![ + (expr.span.with_hi(after_open), String::new()), + (expr.span.with_lo(before_close), String::new()), + ], Applicability::MachineApplicable, ); } else if !self.expr_in_place(expr.hir_id) { diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.stderr b/src/test/ui/typeck/issue-88803-call-expr-method.stderr index 4b7ea95dee2a7..dd717ed9416d3 100644 --- a/src/test/ui/typeck/issue-88803-call-expr-method.stderr +++ b/src/test/ui/typeck/issue-88803-call-expr-method.stderr @@ -2,10 +2,13 @@ error[E0615]: attempted to take value of method `unwrap` on type `Option<{intege --> $DIR/issue-88803-call-expr-method.rs:7:12 | LL | (a.unwrap)() - | ---^^^^^^- - | | | - | | method, not a field - | help: remove wrapping parentheses to call the method + | ^^^^^^ method, not a field + | +help: remove wrapping parentheses to call the method + | +LL - (a.unwrap)() +LL + a.unwrap() + | error: aborting due to previous error