Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

suggest semicolon on double-call that doesn't typecheck as callable #51098

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions src/librustc_typeck/check/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -231,21 +232,41 @@ 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 \
without the parenthesis", path),
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, ..) => {
Expand Down
4 changes: 3 additions & 1 deletion src/test/ui/block-result/issue-20862.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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: `;`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can check wether the spans are in different lines and only suggest then.


error: aborting due to 2 previous errors

Expand Down
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
Original file line number Diff line number Diff line change
@@ -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`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be nice if the main span here pointed at only vindictive(), given that that's where a function was expected (while also pointing at the entire span or the arguments, to make it clear what is happening.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, although I think this will require a bit of restructuring (need to assert that the expression is an ExprCall before you can get the callee span).

(regretfully, I'm out of rustc-dev time for at least a few days)

| ^ - help: try adding a semicolon: `;`
| _____|
| |
LL | | (1, 2)
| |__________^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0618`.