From edbeef851858c25fc9249d050c65808dcc121069 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Fri, 25 May 2018 00:51:14 -0700 Subject: [PATCH] =?UTF-8?q?diagnostics:=20for=20want=20of=20a=20semicolon,?= =?UTF-8?q?=20the=20program=20was=20lost=E2=80=94but=20not=20today?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves #51055. --- src/librustc_typeck/check/callee.rs | 35 +++++++++++++++---- src/test/ui/block-result/issue-20862.stderr | 4 ++- ...issing-semicolon-between-call-and-tuple.rs | 18 ++++++++++ ...ng-semicolon-between-call-and-tuple.stderr | 13 +++++++ 4 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs create mode 100644 src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index b0f9a4c8b85ad..2c5d8d1224455 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -12,6 +12,7 @@ use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag}; use super::autoderef::Autoderef; use super::method::MethodCallee; +use errors::Applicability; use hir::def::Def; use hir::def_id::{DefId, LOCAL_CRATE}; use rustc::{infer, traits}; @@ -231,8 +232,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None => format!("`{}`", callee_ty), }); - err.span_label(call_expr.span, "not a function"); - if let Some(ref path) = unit_variant { err.span_suggestion(call_expr.span, &format!("`{}` is a unit variant, you need to write it \ @@ -240,12 +239,34 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { path.to_string()); } - if let hir::ExprCall(ref expr, _) = call_expr.node { - let def = if let hir::ExprPath(ref qpath) = expr.node { - self.tables.borrow().qpath_def(qpath, expr.hir_id) - } else { - Def::Err + if let hir::ExprCall(ref callee, _) = call_expr.node { + let (def, label_not_a_fn) = match callee.node { + hir::ExprPath(ref qpath) => { + (self.tables.borrow().qpath_def(qpath, callee.hir_id), true) + }, + hir::ExprCall(..) => { + // If the callee kind is itself another `ExprCall`, that's a clue + // that we might just be missing a semicolon (Issue #51055) + let span = self.tcx.sess.codemap().next_point(callee.span); + err.span_suggestion_with_applicability( + span, + "try adding a semicolon", + ";".to_string(), + // test/ui/block-result/issue-20862.rs is an example of a + // false-positive where the real problem lies elsewhere + Applicability::MaybeIncorrect + ); + (Def::Err, + // It'd be confusing to say `not a function` while pointing to a + // function call, even with technical justification (it's the + // non-function-ness of the value that's at issue) + false) + }, + _ => (Def::Err, true) }; + if label_not_a_fn { + err.span_label(call_expr.span, "not a function"); + } let def_span = match def { Def::Err => None, Def::Local(id) | Def::Upvar(id, ..) => { diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr index 990fb404c9466..4f5e6f1ba7c30 100644 --- a/src/test/ui/block-result/issue-20862.stderr +++ b/src/test/ui/block-result/issue-20862.stderr @@ -13,7 +13,9 @@ error[E0618]: expected function, found `()` --> $DIR/issue-20862.rs:17:13 | LL | let x = foo(5)(2); - | ^^^^^^^^^ not a function + | ^^^^^^-^^ + | | + | help: try adding a semicolon: `;` error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs new file mode 100644 index 0000000000000..cc6f58f4fff3d --- /dev/null +++ b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.rs @@ -0,0 +1,18 @@ +// 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. + +fn vindictive() -> bool { true } + +fn perfidy() -> (i32, i32) { + vindictive() //~ ERROR expected function, found `bool` + (1, 2) +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr new file mode 100644 index 0000000000000..3947307cdc6fe --- /dev/null +++ b/src/test/ui/suggestions/issue-51055-missing-semicolon-between-call-and-tuple.stderr @@ -0,0 +1,13 @@ +error[E0618]: expected function, found `bool` + --> $DIR/issue-51055-missing-semicolon-between-call-and-tuple.rs:14:5 + | +LL | vindictive() //~ ERROR expected function, found `bool` + | ^ - help: try adding a semicolon: `;` + | _____| + | | +LL | | (1, 2) + | |__________^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0618`.