From 8e11189cbb129b5df33e27d21c077da6cfc5926f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 23 Jun 2017 17:43:35 -0700 Subject: [PATCH 1/6] Move tests to `ui` --- .../block-must-not-have-result-do.rs | 0 .../block-must-not-have-result-do.stderr | 11 +++++ .../block-must-not-have-result-res.rs | 0 .../block-must-not-have-result-res.stderr | 11 +++++ .../block-must-not-have-result-while.rs | 0 .../block-must-not-have-result-while.stderr | 11 +++++ .../consider-removing-last-semi.rs | 0 .../consider-removing-last-semi.stderr | 38 +++++++++++++++++ .../expected-return-on-unit.stderr | 4 ++ .../block-result}/issue-11714.rs | 0 src/test/ui/block-result/issue-11714.stderr | 21 ++++++++++ .../block-result}/issue-13428.rs | 0 src/test/ui/block-result/issue-13428.stderr | 41 +++++++++++++++++++ .../block-result}/issue-13624.rs | 0 src/test/ui/block-result/issue-13624.stderr | 20 +++++++++ .../block-result}/issue-20862.rs | 0 src/test/ui/block-result/issue-20862.stderr | 17 ++++++++ .../block-result}/issue-22645.rs | 0 src/test/ui/block-result/issue-22645.stderr | 21 ++++++++++ .../block-result}/issue-3563.rs | 0 src/test/ui/block-result/issue-3563.stderr | 17 ++++++++ .../block-result}/issue-5500.rs | 0 src/test/ui/block-result/issue-5500.stderr | 11 +++++ .../block-result/unexpected-return-on-unit.rs | 24 +++++++++++ .../unexpected-return-on-unit.stderr | 11 +++++ .../for-loop-has-unit-body.rs | 0 .../for-loop-has-unit-body.stderr | 11 +++++ 27 files changed, 269 insertions(+) rename src/test/{compile-fail => ui/block-result}/block-must-not-have-result-do.rs (100%) create mode 100644 src/test/ui/block-result/block-must-not-have-result-do.stderr rename src/test/{compile-fail => ui/block-result}/block-must-not-have-result-res.rs (100%) create mode 100644 src/test/ui/block-result/block-must-not-have-result-res.stderr rename src/test/{compile-fail => ui/block-result}/block-must-not-have-result-while.rs (100%) create mode 100644 src/test/ui/block-result/block-must-not-have-result-while.stderr rename src/test/{compile-fail => ui/block-result}/consider-removing-last-semi.rs (100%) create mode 100644 src/test/ui/block-result/consider-removing-last-semi.stderr create mode 100644 src/test/ui/block-result/expected-return-on-unit.stderr rename src/test/{compile-fail => ui/block-result}/issue-11714.rs (100%) create mode 100644 src/test/ui/block-result/issue-11714.stderr rename src/test/{compile-fail => ui/block-result}/issue-13428.rs (100%) create mode 100644 src/test/ui/block-result/issue-13428.stderr rename src/test/{compile-fail => ui/block-result}/issue-13624.rs (100%) create mode 100644 src/test/ui/block-result/issue-13624.stderr rename src/test/{compile-fail => ui/block-result}/issue-20862.rs (100%) create mode 100644 src/test/ui/block-result/issue-20862.stderr rename src/test/{compile-fail => ui/block-result}/issue-22645.rs (100%) create mode 100644 src/test/ui/block-result/issue-22645.stderr rename src/test/{compile-fail => ui/block-result}/issue-3563.rs (100%) create mode 100644 src/test/ui/block-result/issue-3563.stderr rename src/test/{compile-fail => ui/block-result}/issue-5500.rs (100%) create mode 100644 src/test/ui/block-result/issue-5500.stderr create mode 100644 src/test/ui/block-result/unexpected-return-on-unit.rs create mode 100644 src/test/ui/block-result/unexpected-return-on-unit.stderr rename src/test/{compile-fail => ui/mismatched_types}/for-loop-has-unit-body.rs (100%) create mode 100644 src/test/ui/mismatched_types/for-loop-has-unit-body.stderr diff --git a/src/test/compile-fail/block-must-not-have-result-do.rs b/src/test/ui/block-result/block-must-not-have-result-do.rs similarity index 100% rename from src/test/compile-fail/block-must-not-have-result-do.rs rename to src/test/ui/block-result/block-must-not-have-result-do.rs diff --git a/src/test/ui/block-result/block-must-not-have-result-do.stderr b/src/test/ui/block-result/block-must-not-have-result-do.stderr new file mode 100644 index 0000000000000..a770ebeab35a7 --- /dev/null +++ b/src/test/ui/block-result/block-must-not-have-result-do.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-do.rs:13:9 + | +13 | true //~ ERROR mismatched types + | ^^^^ expected (), found bool + | + = note: expected type `()` + found type `bool` + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/block-must-not-have-result-res.rs b/src/test/ui/block-result/block-must-not-have-result-res.rs similarity index 100% rename from src/test/compile-fail/block-must-not-have-result-res.rs rename to src/test/ui/block-result/block-must-not-have-result-res.rs diff --git a/src/test/ui/block-result/block-must-not-have-result-res.stderr b/src/test/ui/block-result/block-must-not-have-result-res.stderr new file mode 100644 index 0000000000000..b1146864566e3 --- /dev/null +++ b/src/test/ui/block-result/block-must-not-have-result-res.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-res.rs:15:9 + | +15 | true //~ ERROR mismatched types + | ^^^^ expected (), found bool + | + = note: expected type `()` + found type `bool` + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/block-must-not-have-result-while.rs b/src/test/ui/block-result/block-must-not-have-result-while.rs similarity index 100% rename from src/test/compile-fail/block-must-not-have-result-while.rs rename to src/test/ui/block-result/block-must-not-have-result-while.rs diff --git a/src/test/ui/block-result/block-must-not-have-result-while.stderr b/src/test/ui/block-result/block-must-not-have-result-while.stderr new file mode 100644 index 0000000000000..31ec7cdd3c5ab --- /dev/null +++ b/src/test/ui/block-result/block-must-not-have-result-while.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/block-must-not-have-result-while.rs:13:9 + | +13 | true //~ ERROR mismatched types + | ^^^^ expected (), found bool + | + = note: expected type `()` + found type `bool` + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/consider-removing-last-semi.rs b/src/test/ui/block-result/consider-removing-last-semi.rs similarity index 100% rename from src/test/compile-fail/consider-removing-last-semi.rs rename to src/test/ui/block-result/consider-removing-last-semi.rs diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr new file mode 100644 index 0000000000000..944c9d6c42794 --- /dev/null +++ b/src/test/ui/block-result/consider-removing-last-semi.stderr @@ -0,0 +1,38 @@ +error[E0308]: mismatched types + --> $DIR/consider-removing-last-semi.rs:11:18 + | +11 | fn f() -> String { //~ ERROR mismatched types + | __________________^ +12 | | 0u8; +13 | | "bla".to_string(); //~ HELP consider removing this semicolon +14 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` +help: consider removing this semicolon: + --> $DIR/consider-removing-last-semi.rs:13:22 + | +13 | "bla".to_string(); //~ HELP consider removing this semicolon + | ^ + +error[E0308]: mismatched types + --> $DIR/consider-removing-last-semi.rs:16:18 + | +16 | fn g() -> String { //~ ERROR mismatched types + | __________________^ +17 | | "this won't work".to_string(); +18 | | "removeme".to_string(); //~ HELP consider removing this semicolon +19 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` +help: consider removing this semicolon: + --> $DIR/consider-removing-last-semi.rs:18:27 + | +18 | "removeme".to_string(); //~ HELP consider removing this semicolon + | ^ + +error: aborting due to previous error(s) + diff --git a/src/test/ui/block-result/expected-return-on-unit.stderr b/src/test/ui/block-result/expected-return-on-unit.stderr new file mode 100644 index 0000000000000..8a0d7a335d6af --- /dev/null +++ b/src/test/ui/block-result/expected-return-on-unit.stderr @@ -0,0 +1,4 @@ +error[E0601]: main function not found + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/issue-11714.rs b/src/test/ui/block-result/issue-11714.rs similarity index 100% rename from src/test/compile-fail/issue-11714.rs rename to src/test/ui/block-result/issue-11714.rs diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr new file mode 100644 index 0000000000000..cba9c3f51d7e3 --- /dev/null +++ b/src/test/ui/block-result/issue-11714.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-11714.rs:11:18 + | +11 | fn blah() -> i32 { //~ ERROR mismatched types + | __________________^ +12 | | 1 +13 | | +14 | | ; //~ HELP consider removing this semicolon: +15 | | } + | |_^ expected i32, found () + | + = note: expected type `i32` + found type `()` +help: consider removing this semicolon: + --> $DIR/issue-11714.rs:14:5 + | +14 | ; //~ HELP consider removing this semicolon: + | ^ + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/issue-13428.rs b/src/test/ui/block-result/issue-13428.rs similarity index 100% rename from src/test/compile-fail/issue-13428.rs rename to src/test/ui/block-result/issue-13428.rs diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr new file mode 100644 index 0000000000000..d0ed8935cd775 --- /dev/null +++ b/src/test/ui/block-result/issue-13428.stderr @@ -0,0 +1,41 @@ +error[E0308]: mismatched types + --> $DIR/issue-13428.rs:13:20 + | +13 | fn foo() -> String { //~ ERROR mismatched types + | ____________________^ +14 | | format!("Hello {}", +15 | | "world") +16 | | // Put the trailing semicolon on its own line to test that the +17 | | // note message gets the offending semicolon exactly +18 | | ; //~ HELP consider removing this semicolon +19 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` +help: consider removing this semicolon: + --> $DIR/issue-13428.rs:18:5 + | +18 | ; //~ HELP consider removing this semicolon + | ^ + +error[E0308]: mismatched types + --> $DIR/issue-13428.rs:21:20 + | +21 | fn bar() -> String { //~ ERROR mismatched types + | ____________________^ +22 | | "foobar".to_string() +23 | | ; //~ HELP consider removing this semicolon +24 | | } + | |_^ expected struct `std::string::String`, found () + | + = note: expected type `std::string::String` + found type `()` +help: consider removing this semicolon: + --> $DIR/issue-13428.rs:23:5 + | +23 | ; //~ HELP consider removing this semicolon + | ^ + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/issue-13624.rs b/src/test/ui/block-result/issue-13624.rs similarity index 100% rename from src/test/compile-fail/issue-13624.rs rename to src/test/ui/block-result/issue-13624.rs diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr new file mode 100644 index 0000000000000..72ff859d7e93a --- /dev/null +++ b/src/test/ui/block-result/issue-13624.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/issue-13624.rs:17:5 + | +17 | Enum::EnumStructVariant { x: 1, y: 2, z: 3 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` + | + = note: expected type `()` + found type `a::Enum` + +error[E0308]: mismatched types + --> $DIR/issue-13624.rs:32:9 + | +32 | a::Enum::EnumStructVariant { x, y, z } => { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` + | + = note: expected type `()` + found type `a::Enum` + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/issue-20862.rs b/src/test/ui/block-result/issue-20862.rs similarity index 100% rename from src/test/compile-fail/issue-20862.rs rename to src/test/ui/block-result/issue-20862.rs diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr new file mode 100644 index 0000000000000..757fe1666c35c --- /dev/null +++ b/src/test/ui/block-result/issue-20862.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/issue-20862.rs:12:5 + | +12 | |y| x + y + | ^^^^^^^^^ expected (), found closure + | + = note: expected type `()` + found type `[closure@$DIR/issue-20862.rs:12:5: 12:14 x:_]` + +error[E0618]: expected function, found `()` + --> $DIR/issue-20862.rs:17:13 + | +17 | let x = foo(5)(2); + | ^^^^^^^^^ + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/issue-22645.rs b/src/test/ui/block-result/issue-22645.rs similarity index 100% rename from src/test/compile-fail/issue-22645.rs rename to src/test/ui/block-result/issue-22645.rs diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr new file mode 100644 index 0000000000000..3921a301c9223 --- /dev/null +++ b/src/test/ui/block-result/issue-22645.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `{integer}: Scalar` is not satisfied + --> $DIR/issue-22645.rs:25:5 + | +25 | b + 3 //~ ERROR E0277 + | ^ the trait `Scalar` is not implemented for `{integer}` + | + = help: the following implementations were found: + + = note: required because of the requirements on the impl of `std::ops::Add<{integer}>` for `Bob` + +error[E0308]: mismatched types + --> $DIR/issue-22645.rs:25:3 + | +25 | b + 3 //~ ERROR E0277 + | ^^^^^ expected (), found struct `Bob` + | + = note: expected type `()` + found type `Bob` + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/issue-3563.rs b/src/test/ui/block-result/issue-3563.rs similarity index 100% rename from src/test/compile-fail/issue-3563.rs rename to src/test/ui/block-result/issue-3563.rs diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr new file mode 100644 index 0000000000000..9b403bcd93db7 --- /dev/null +++ b/src/test/ui/block-result/issue-3563.stderr @@ -0,0 +1,17 @@ +error[E0599]: no method named `b` found for type `&Self` in the current scope + --> $DIR/issue-3563.rs:13:17 + | +13 | || self.b() + | ^ + +error[E0308]: mismatched types + --> $DIR/issue-3563.rs:13:9 + | +13 | || self.b() + | ^^^^^^^^^^^ expected (), found closure + | + = note: expected type `()` + found type `[closure@$DIR/issue-3563.rs:13:9: 13:20 self:_]` + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/issue-5500.rs b/src/test/ui/block-result/issue-5500.rs similarity index 100% rename from src/test/compile-fail/issue-5500.rs rename to src/test/ui/block-result/issue-5500.rs diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr new file mode 100644 index 0000000000000..bffe2a82ca8d7 --- /dev/null +++ b/src/test/ui/block-result/issue-5500.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/issue-5500.rs:12:5 + | +12 | &panic!() + | ^^^^^^^^^ expected (), found reference + | + = note: expected type `()` + found type `&_` + +error: aborting due to previous error(s) + diff --git a/src/test/ui/block-result/unexpected-return-on-unit.rs b/src/test/ui/block-result/unexpected-return-on-unit.rs new file mode 100644 index 0000000000000..291b7a16f141b --- /dev/null +++ b/src/test/ui/block-result/unexpected-return-on-unit.rs @@ -0,0 +1,24 @@ +// 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. + +// Test that we do some basic error correcton in the tokeniser (and don't spew +// too many bogus errors). + +fn foo() -> usize { + 3 +} + +fn bar() { + foo() +} + +fn main() { + bar() +} diff --git a/src/test/ui/block-result/unexpected-return-on-unit.stderr b/src/test/ui/block-result/unexpected-return-on-unit.stderr new file mode 100644 index 0000000000000..ad10312d064de --- /dev/null +++ b/src/test/ui/block-result/unexpected-return-on-unit.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/unexpected-return-on-unit.rs:19:5 + | +19 | foo() + | ^^^^^ expected (), found usize + | + = note: expected type `()` + found type `usize` + +error: aborting due to previous error(s) + diff --git a/src/test/compile-fail/for-loop-has-unit-body.rs b/src/test/ui/mismatched_types/for-loop-has-unit-body.rs similarity index 100% rename from src/test/compile-fail/for-loop-has-unit-body.rs rename to src/test/ui/mismatched_types/for-loop-has-unit-body.rs diff --git a/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr new file mode 100644 index 0000000000000..6787fe91bf308 --- /dev/null +++ b/src/test/ui/mismatched_types/for-loop-has-unit-body.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/for-loop-has-unit-body.rs:13:9 + | +13 | x //~ ERROR mismatched types + | ^ expected (), found integral variable + | + = note: expected type `()` + found type `{integer}` + +error: aborting due to previous error(s) + From c023856b38c847731720fa8e26f3e1b9062bc946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 24 Jun 2017 00:57:39 -0700 Subject: [PATCH 2/6] Detect missing `;` on methods with return type `()` - Point out the origin of a type requirement when it is the return type of a method - Point out possibly missing semicolon when the return type is () and the implicit return makes sense as a statement - Suggest changing the return type of methods with default return type - Don't suggest changing the return type on fn main() - Don't suggest changing the return type on impl fn --- src/librustc/hir/map/mod.rs | 44 ++++- src/librustc/traits/error_reporting.rs | 4 +- src/librustc/traits/mod.rs | 53 +++--- src/librustc/traits/structural_impls.rs | 44 ++--- src/librustc_typeck/check/coercion.rs | 18 ++ src/librustc_typeck/check/demand.rs | 17 +- src/librustc_typeck/check/mod.rs | 156 +++++++++++++++++- src/test/ui/block-result/issue-13624.stderr | 2 + src/test/ui/block-result/issue-20862.stderr | 5 + src/test/ui/block-result/issue-22645.stderr | 3 + src/test/ui/block-result/issue-3563.stderr | 5 + src/test/ui/block-result/issue-5500.stderr | 2 + .../unexpected-return-on-unit.stderr | 6 + src/test/ui/impl-trait/equality.stderr | 3 + src/test/ui/mismatched_types/abridged.stderr | 12 ++ .../ui/mismatched_types/issue-19109.stderr | 5 + .../ui/resolve/token-error-correct-3.stderr | 7 +- 17 files changed, 321 insertions(+), 65 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index a1875cd46a0cb..ddcc2c0885085 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -594,8 +594,12 @@ impl<'hir> Map<'hir> { /// last good node id we found. Note that reaching the crate root (id == 0), /// is not an error, since items in the crate module have the crate root as /// parent. - fn walk_parent_nodes(&self, start_id: NodeId, found: F) -> Result - where F: Fn(&Node<'hir>) -> bool + fn walk_parent_nodes(&self, + start_id: NodeId, + found: F, + bail_early: F2) + -> Result + where F: Fn(&Node<'hir>) -> bool, F2: Fn(&Node<'hir>) -> bool { let mut id = start_id; loop { @@ -616,6 +620,8 @@ impl<'hir> Map<'hir> { Some(ref node) => { if found(node) { return Ok(parent_node); + } else if bail_early(node) { + return Err(parent_node); } } None => { @@ -626,6 +632,34 @@ impl<'hir> Map<'hir> { } } + pub fn get_return_block(&self, id: NodeId) -> Option { + let match_fn = |node: &Node| { + match *node { + NodeItem(_) | + NodeForeignItem(_) | + NodeTraitItem(_) | + NodeImplItem(_) => true, + _ => false, + } + }; + let match_non_returning_block = |node: &Node| { + match *node { + NodeExpr(ref expr) => { + match expr.node { + ExprWhile(..) | ExprLoop(..) => true, + _ => false, + } + } + _ => false, + } + }; + + match self.walk_parent_nodes(id, match_fn, match_non_returning_block) { + Ok(id) => Some(id), + Err(_) => None, + } + } + /// Retrieve the NodeId for `id`'s parent item, or `id` itself if no /// parent item is in this map. The "parent item" is the closest parent node /// in the AST which is recorded by the map and is an item, either an item @@ -637,7 +671,7 @@ impl<'hir> Map<'hir> { NodeTraitItem(_) | NodeImplItem(_) => true, _ => false, - }) { + }, |_| false) { Ok(id) => id, Err(id) => id, } @@ -649,7 +683,7 @@ impl<'hir> Map<'hir> { let id = match self.walk_parent_nodes(id, |node| match *node { NodeItem(&Item { node: Item_::ItemMod(_), .. }) => true, _ => false, - }) { + }, |_| false) { Ok(id) => id, Err(id) => id, }; @@ -668,7 +702,7 @@ impl<'hir> Map<'hir> { NodeImplItem(_) | NodeBlock(_) => true, _ => false, - }) { + }, |_| false) { Ok(id) => Some(id), Err(_) => None, } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 247fb079fe7ee..2f260b0b9ee1f 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1088,7 +1088,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ObligationCauseCode::VariableType(_) => { err.note("all local variables must have a statically known size"); } - ObligationCauseCode::ReturnType => { + ObligationCauseCode::SizedReturnType => { err.note("the return type of a function must have a \ statically known size"); } @@ -1133,6 +1133,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { but not on the corresponding trait method", predicate)); } + ObligationCauseCode::ReturnType(_) | + ObligationCauseCode::BlockTailExpression(_) => (), } } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index e9196cd12431b..a98be90e3a0f1 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -118,27 +118,32 @@ pub enum ObligationCauseCode<'tcx> { /// Obligation incurred due to an object cast. ObjectCastObligation(/* Object type */ Ty<'tcx>), - /// Various cases where expressions must be sized/copy/etc: - AssignmentLhsSized, // L = X implies that L is Sized - StructInitializerSized, // S { ... } must be Sized - VariableType(ast::NodeId), // Type of each variable must be Sized - ReturnType, // Return type must be Sized - RepeatVec, // [T,..n] --> T must be Copy - - // Types of fields (other than the last) in a struct must be sized. + // Various cases where expressions must be sized/copy/etc: + /// L = X implies that L is Sized + AssignmentLhsSized, + /// S { ... } must be Sized + StructInitializerSized, + /// Type of each variable must be Sized + VariableType(ast::NodeId), + /// Return type must be Sized + SizedReturnType, + /// [T,..n] --> T must be Copy + RepeatVec, + + /// Types of fields (other than the last) in a struct must be sized. FieldSized, - // Constant expressions must be sized. + /// Constant expressions must be sized. ConstSized, - // static items must have `Sync` type + /// static items must have `Sync` type SharedStatic, BuiltinDerivedObligation(DerivedObligationCause<'tcx>), ImplDerivedObligation(DerivedObligationCause<'tcx>), - // error derived when matching traits/impls; see ObligationCause for more details + /// error derived when matching traits/impls; see ObligationCause for more details CompareImplMethodObligation { item_name: ast::Name, impl_item_def_id: DefId, @@ -146,37 +151,43 @@ pub enum ObligationCauseCode<'tcx> { lint_id: Option, }, - // Checking that this expression can be assigned where it needs to be + /// Checking that this expression can be assigned where it needs to be // FIXME(eddyb) #11161 is the original Expr required? ExprAssignable, - // Computing common supertype in the arms of a match expression + /// Computing common supertype in the arms of a match expression MatchExpressionArm { arm_span: Span, source: hir::MatchSource }, - // Computing common supertype in an if expression + /// Computing common supertype in an if expression IfExpression, - // Computing common supertype of an if expression with no else counter-part + /// Computing common supertype of an if expression with no else counter-part IfExpressionWithNoElse, - // `where a == b` + /// `where a == b` EquatePredicate, - // `main` has wrong type + /// `main` has wrong type MainFunctionType, - // `start` has wrong type + /// `start` has wrong type StartFunctionType, - // intrinsic has wrong type + /// intrinsic has wrong type IntrinsicType, - // method receiver + /// method receiver MethodReceiver, - // `return` with no expression + /// `return` with no expression ReturnNoExpression, + + /// `return` with an expression + ReturnType(ast::NodeId), + + /// Block implicit return + BlockTailExpression(ast::NodeId), } #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 4abb0cb549db4..0d6df78c2ac5b 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -191,7 +191,8 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::AssignmentLhsSized => Some(super::AssignmentLhsSized), super::StructInitializerSized => Some(super::StructInitializerSized), super::VariableType(id) => Some(super::VariableType(id)), - super::ReturnType => Some(super::ReturnType), + super::ReturnType(id) => Some(super::ReturnType(id)), + super::SizedReturnType => Some(super::SizedReturnType), super::RepeatVec => Some(super::RepeatVec), super::FieldSized => Some(super::FieldSized), super::ConstSized => Some(super::ConstSized), @@ -213,34 +214,19 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { lint_id: lint_id, }) } - super::ExprAssignable => { - Some(super::ExprAssignable) - } + super::ExprAssignable => Some(super::ExprAssignable), super::MatchExpressionArm { arm_span, source } => { Some(super::MatchExpressionArm { arm_span: arm_span, source: source }) } - super::IfExpression => { - Some(super::IfExpression) - } - super::IfExpressionWithNoElse => { - Some(super::IfExpressionWithNoElse) - } - super::EquatePredicate => { - Some(super::EquatePredicate) - } - super::MainFunctionType => { - Some(super::MainFunctionType) - } - super::StartFunctionType => { - Some(super::StartFunctionType) - } - super::IntrinsicType => { - Some(super::IntrinsicType) - } - super::MethodReceiver => { - Some(super::MethodReceiver) - } + super::IfExpression => Some(super::IfExpression), + super::IfExpressionWithNoElse => Some(super::IfExpressionWithNoElse), + super::EquatePredicate => Some(super::EquatePredicate), + super::MainFunctionType => Some(super::MainFunctionType), + super::StartFunctionType => Some(super::StartFunctionType), + super::IntrinsicType => Some(super::IntrinsicType), + super::MethodReceiver => Some(super::MethodReceiver), + super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)), } } } @@ -492,12 +478,14 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::AssignmentLhsSized | super::StructInitializerSized | super::VariableType(_) | - super::ReturnType | + super::ReturnType(_) | + super::SizedReturnType | super::ReturnNoExpression | super::RepeatVec | super::FieldSized | super::ConstSized | super::SharedStatic | + super::BlockTailExpression(_) | super::CompareImplMethodObligation { .. } => self.clone(), super::ProjectionWf(proj) => super::ProjectionWf(proj.fold_with(folder)), @@ -537,12 +525,14 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::AssignmentLhsSized | super::StructInitializerSized | super::VariableType(_) | - super::ReturnType | + super::ReturnType(_) | + super::SizedReturnType | super::ReturnNoExpression | super::RepeatVec | super::FieldSized | super::ConstSized | super::SharedStatic | + super::BlockTailExpression(_) | super::CompareImplMethodObligation { .. } => false, super::ProjectionWf(proj) => proj.visit_with(visitor), diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 30ac7b4bfb9be..660f6c5a093f3 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1162,6 +1162,24 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> "`return;` in a function whose return type is not `()`"); db.span_label(cause.span, "return type is not ()"); } + ObligationCauseCode::BlockTailExpression(blk_id) => { + db = fcx.report_mismatched_types(cause, expected, found, err); + + let expr = expression.unwrap_or_else(|| { + span_bug!(cause.span, + "supposed to be part of a block tail expression, but the \ + expression is empty"); + }); + fcx.suggest_mismatched_types_on_tail(&mut db, expr, + expected, found, + cause.span, blk_id); + } + ObligationCauseCode::ReturnType(ret_id) => { + db = fcx.report_mismatched_types(cause, expected, found, err); + if let Some((fn_decl, _)) = fcx.get_fn_decl(ret_id) { + fcx.point_to_type_requirement(&mut db, &fn_decl, expected); + } + } _ => { db = fcx.report_mismatched_types(cause, expected, found, err); } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 1b6f96cf65137..1edb141c2afef 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -73,15 +73,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } + pub fn demand_coerce(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, expected: Ty<'tcx>) { + if let Some(mut err) = self.demand_coerce_diag(expr, checked_ty, expected) { + err.emit(); + } + } + // Checks that the type of `expr` can be coerced to `expected`. // // NB: This code relies on `self.diverges` to be accurate. In // particular, assignments to `!` will be permitted if the // diverges flag is currently "always". - pub fn demand_coerce(&self, - expr: &hir::Expr, - checked_ty: Ty<'tcx>, - expected: Ty<'tcx>) { + pub fn demand_coerce_diag(&self, + expr: &hir::Expr, + checked_ty: Ty<'tcx>, + expected: Ty<'tcx>) -> Option> { let expected = self.resolve_type_vars_with_obligations(expected); if let Err(e) = self.try_coerce(expr, checked_ty, self.diverges.get(), expected) { @@ -105,8 +111,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.get_best_match(&suggestions).join("\n"))); } } - err.emit(); + return Some(err); } + None } fn format_method_suggestion(&self, method: &AssociatedItem) -> String { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2bf24d5b3504c..684e5a66fc51b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -124,6 +124,7 @@ use syntax_pos::{self, BytePos, Span}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::hir::map::Node; use rustc::hir::{self, PatKind}; use rustc::middle::lang_items; use rustc_back::slice; @@ -985,7 +986,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id); let ret_ty = fn_sig.output(); - fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType); + fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::SizedReturnType); let ret_ty = fcx.instantiate_anon_types(&ret_ty); fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty))); fn_sig = fcx.tcx.mk_fn_sig( @@ -1908,7 +1909,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Require that the predicate holds for the concrete type. let cause = traits::ObligationCause::new(span, self.body_id, - traits::ReturnType); + traits::SizedReturnType); self.register_predicate(traits::Obligation::new(cause, self.param_env, predicate)); @@ -2848,10 +2849,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "check_return_expr called outside fn body")); let ret_ty = ret_coercion.borrow().expected_ty(); - let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty); + let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty.clone()); ret_coercion.borrow_mut() .coerce(self, - &self.misc(return_expr.span), + &self.cause(return_expr.span, + ObligationCauseCode::ReturnType(return_expr.id)), return_expr, return_expr_ty, self.diverges.get()); @@ -4170,8 +4172,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut coerce = ctxt.coerce.as_mut().unwrap(); if let Some(tail_expr_ty) = tail_expr_ty { let tail_expr = tail_expr.unwrap(); + let cause = self.cause(tail_expr.span, + ObligationCauseCode::BlockTailExpression(blk.id)); coerce.coerce(self, - &self.misc(tail_expr.span), + &cause, tail_expr, tail_expr_ty, self.diverges.get()); @@ -4210,6 +4214,148 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty } + /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and wether it is + /// `fn main` if it is a method, `None` otherwise. + pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> { + // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or + // `while` before reaching it, as block tail returns are not available in them. + if let Some(fn_id) = self.tcx.hir.get_return_block(blk_id) { + let parent = self.tcx.hir.get(fn_id); + + if let Node::NodeItem(&hir::Item { + name, node: hir::ItemFn(ref decl, ..), .. + }) = parent { + decl.clone().and_then(|decl| { + // This is less than ideal, it will not present the return type span on any + // method called `main`, regardless of wether it is actually the entry point. + Some((decl, name == Symbol::intern("main"))) + }) + } else if let Node::NodeTraitItem(&hir::TraitItem { + node: hir::TraitItemKind::Method(hir::MethodSig { + ref decl, .. + }, ..), .. + }) = parent { + decl.clone().and_then(|decl| { + Some((decl, false)) + }) + } else { + None + } + } else { + None + } + } + + /// On implicit return expressions with mismatched types, provide the following suggestions: + /// + /// - Point out the method's return type as the reason for the expected type + /// - Possible missing semicolon + /// - Possible missing return type if the return type is the default, and not `fn main()` + pub fn suggest_mismatched_types_on_tail(&self, + err: &mut DiagnosticBuilder<'tcx>, + expression: &'gcx hir::Expr, + expected: Ty<'tcx>, + found: Ty<'tcx>, + cause_span: Span, + blk_id: ast::NodeId) { + self.suggest_missing_semicolon(err, expression, expected, cause_span); + + if let Some((fn_decl, is_main)) = self.get_fn_decl(blk_id) { + self.point_to_type_requirement(err, &fn_decl, expected); + // `fn main()` must return `()`, do not suggest changing return type + if !is_main { + self.suggest_missing_return_type(err, &fn_decl, found); + } + } + } + + pub fn point_to_type_requirement(&self, + err: &mut DiagnosticBuilder<'tcx>, + fn_decl: &hir::FnDecl, + ty: Ty<'tcx>) { + let msg = if let &hir::FnDecl { + output: hir::FunctionRetTy::DefaultReturn(_), .. + } = fn_decl { + "default " + } else { + "" + }; + let ty = self.resolve_type_vars_if_possible(&ty); + if ty.to_string().len() < 10 { + err.span_label(fn_decl.output.span(), + format!("expected `{}` because of this {}return type", ty, msg)); + } else { + err.span_label(fn_decl.output.span(), + format!("expected because of this {}return type", msg)); + } + } + + /// A common error is to forget to add a semicolon at the end of a block: + /// + /// ``` + /// fn foo() { + /// bar_that_returns_u32() + /// } + /// ``` + /// + /// This routine checks if the return expression in a block would make sense on its own as a + /// statement and the return type has been left as defaultor has been specified as `()`. If so, + /// it suggests adding a semicolon. + fn suggest_missing_semicolon(&self, + err: &mut DiagnosticBuilder<'tcx>, + expression: &'gcx hir::Expr, + expected: Ty<'tcx>, + cause_span: Span) { + if expected.is_nil() { + // `BlockTailExpression` only relevant if the tail expr would be + // useful on its own. + match expression.node { + hir::ExprCall(..) | + hir::ExprMethodCall(..) | + hir::ExprIf(..) | + hir::ExprWhile(..) | + hir::ExprLoop(..) | + hir::ExprMatch(..) | + hir::ExprBlock(..) => { + let sp = cause_span.next_point(); + err.span_suggestion(sp, + "did you mean to add a semicolon here?", + ";".to_string()); + } + _ => (), + } + } + } + + + /// A possible error is to forget to add a return type that is needed: + /// + /// ``` + /// fn foo() { + /// bar_that_returns_u32() + /// } + /// ``` + /// + /// This routine checks if the return type is left as default, the method is not part of an + /// `impl` block and that it isn't the `main` method. If so, it suggests setting the return + /// type. + fn suggest_missing_return_type(&self, + err: &mut DiagnosticBuilder<'tcx>, + fn_decl: &hir::FnDecl, + ty: Ty<'tcx>) { + + // Only recommend changing the return type for methods that + // haven't set a return type at all (and aren't `fn main()` or an impl). + if let &hir::FnDecl { + output: hir::FunctionRetTy::DefaultReturn(span), .. + } = fn_decl { + err.span_suggestion(span, + "possibly return type missing here?", + format!("-> {} ", ty)); + } + } + + /// A common error is to add an extra semicolon: /// /// ``` diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr index 72ff859d7e93a..69c6e647cfc24 100644 --- a/src/test/ui/block-result/issue-13624.stderr +++ b/src/test/ui/block-result/issue-13624.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-13624.rs:17:5 | +16 | pub fn get_enum_struct_variant() -> () { + | -- expected `()` because of this return type 17 | Enum::EnumStructVariant { x: 1, y: 2, z: 3 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` | diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr index 757fe1666c35c..0d88a44d6b9b2 100644 --- a/src/test/ui/block-result/issue-20862.stderr +++ b/src/test/ui/block-result/issue-20862.stderr @@ -1,6 +1,11 @@ error[E0308]: mismatched types --> $DIR/issue-20862.rs:12:5 | +11 | fn foo(x: i32) { + | - + | | + | help: possibly return type missing here? `-> [closure@$DIR/issue-20862.rs:12:5: 12:14 x:_] ` + | expected `()` because of this default return type 12 | |y| x + y | ^^^^^^^^^ expected (), found closure | diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr index 3921a301c9223..93da3c6a48932 100644 --- a/src/test/ui/block-result/issue-22645.stderr +++ b/src/test/ui/block-result/issue-22645.stderr @@ -11,6 +11,9 @@ error[E0277]: the trait bound `{integer}: Scalar` is not satisfied error[E0308]: mismatched types --> $DIR/issue-22645.rs:25:3 | +23 | fn main() { + | - expected `()` because of this default return type +24 | let b = Bob + 3.5; 25 | b + 3 //~ ERROR E0277 | ^^^^^ expected (), found struct `Bob` | diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr index 9b403bcd93db7..e9ace85c1d91d 100644 --- a/src/test/ui/block-result/issue-3563.stderr +++ b/src/test/ui/block-result/issue-3563.stderr @@ -7,6 +7,11 @@ error[E0599]: no method named `b` found for type `&Self` in the current scope error[E0308]: mismatched types --> $DIR/issue-3563.rs:13:9 | +12 | fn a(&self) { + | - + | | + | help: possibly return type missing here? `-> [closure@$DIR/issue-3563.rs:13:9: 13:20 self:_] ` + | expected `()` because of this default return type 13 | || self.b() | ^^^^^^^^^^^ expected (), found closure | diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr index bffe2a82ca8d7..6fda2aa00ffb3 100644 --- a/src/test/ui/block-result/issue-5500.stderr +++ b/src/test/ui/block-result/issue-5500.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-5500.rs:12:5 | +11 | fn main() { + | - expected `()` because of this default return type 12 | &panic!() | ^^^^^^^^^ expected (), found reference | diff --git a/src/test/ui/block-result/unexpected-return-on-unit.stderr b/src/test/ui/block-result/unexpected-return-on-unit.stderr index ad10312d064de..e5481ffd31669 100644 --- a/src/test/ui/block-result/unexpected-return-on-unit.stderr +++ b/src/test/ui/block-result/unexpected-return-on-unit.stderr @@ -1,11 +1,17 @@ error[E0308]: mismatched types --> $DIR/unexpected-return-on-unit.rs:19:5 | +18 | fn bar() { + | - expected `()` because of this default return type 19 | foo() | ^^^^^ expected (), found usize | = note: expected type `()` found type `usize` +help: did you mean to add a semicolon here? + | foo(); +help: possibly return type missing here? + | fn bar() -> usize { error: aborting due to previous error(s) diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index 2206234b77744..ca37596f1b963 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/equality.rs:25:5 | +21 | fn two(x: bool) -> impl Foo { + | -------- expected `i32` because of this return type +... 25 | 0_u32 | ^^^^^ expected i32, found u32 | diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index 78b5dcda1d9d2..6282541ba0e41 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/abridged.rs:26:5 | +25 | fn a() -> Foo { + | --- expected `Foo` because of this return type 26 | Some(Foo { bar: 1 }) | ^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::option::Option` | @@ -10,6 +12,8 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:30:5 | +29 | fn a2() -> Foo { + | --- expected `Foo` because of this return type 30 | Ok(Foo { bar: 1}) | ^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::result::Result` | @@ -19,6 +23,8 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:34:5 | +33 | fn b() -> Option { + | ----------- expected because of this return type 34 | Foo { bar: 1 } | ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `Foo` | @@ -28,6 +34,8 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:38:5 | +37 | fn c() -> Result { + | ---------------- expected because of this return type 38 | Foo { bar: 1 } | ^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `Foo` | @@ -37,6 +45,8 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:42:5 | +41 | fn d() -> X, String> { + | ---------------------------- expected because of this return type 42 | / X { 43 | | x: X { 44 | | x: "".to_string(), @@ -52,6 +62,8 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:52:5 | +51 | fn e() -> X, String> { + | ---------------------------- expected because of this return type 52 | / X { 53 | | x: X { 54 | | x: "".to_string(), diff --git a/src/test/ui/mismatched_types/issue-19109.stderr b/src/test/ui/mismatched_types/issue-19109.stderr index cbce4f810c531..5efa3fa6a1d5b 100644 --- a/src/test/ui/mismatched_types/issue-19109.stderr +++ b/src/test/ui/mismatched_types/issue-19109.stderr @@ -1,6 +1,11 @@ error[E0308]: mismatched types --> $DIR/issue-19109.rs:14:5 | +13 | fn function(t: &mut Trait) { + | - + | | + | help: possibly return type missing here? `-> *mut Trait ` + | expected `()` because of this default return type 14 | t as *mut Trait | ^^^^^^^^^^^^^^^ expected (), found *-ptr | diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index d234c8538fe27..2a50428dbb9f9 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -34,8 +34,13 @@ error[E0425]: cannot find function `is_directory` in this scope error[E0308]: mismatched types --> $DIR/token-error-correct-3.rs:25:13 | +20 | -> io::Result { + | ---------------- expected `()` because of this return type +... 25 | fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `std::result::Result` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: did you mean to add a semicolon here? `;` + | | + | expected (), found enum `std::result::Result` | = note: expected type `()` found type `std::result::Result` From ecde91a69d8414113b71bf2f5c79e607861dba23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 24 Jun 2017 01:09:57 -0700 Subject: [PATCH 3/6] Suggest removal of semicolon (instead of being help) --- src/librustc_errors/emitter.rs | 7 ++++++- src/librustc_typeck/check/mod.rs | 2 +- .../block-result/consider-removing-last-semi.stderr | 12 ++---------- src/test/ui/block-result/issue-11714.stderr | 6 +----- src/test/ui/block-result/issue-13428.stderr | 12 ++---------- .../ui/coercion-missing-tail-expected-type.stderr | 12 ++---------- 6 files changed, 14 insertions(+), 37 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 2d25d12d3a96e..4b71aa6b85f1c 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -47,7 +47,12 @@ impl Emitter for EmitterWriter { // don't display multiline suggestions as labels sugg.substitution_parts[0].substitutions[0].find('\n').is_none() { let substitution = &sugg.substitution_parts[0].substitutions[0]; - let msg = format!("help: {} `{}`", sugg.msg, substitution); + let msg = if substitution.len() == 0 { + // This substitution is only removal, don't show it + format!("help: {}", sugg.msg) + } else { + format!("help: {} `{}`", sugg.msg, substitution) + }; primary_span.push_span_label(sugg.substitution_spans().next().unwrap(), msg); } else { // if there are multiple suggestions, print them all in full diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 684e5a66fc51b..0467f24948e75 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4391,7 +4391,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { hi: original_span.hi, ctxt: original_span.ctxt, }; - err.span_help(span_semi, "consider removing this semicolon:"); + err.span_suggestion(span_semi, "consider removing this semicolon", "".to_string()); } // Instantiates the given path, which must refer to an item with the given diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr index 944c9d6c42794..282583d32a665 100644 --- a/src/test/ui/block-result/consider-removing-last-semi.stderr +++ b/src/test/ui/block-result/consider-removing-last-semi.stderr @@ -5,16 +5,12 @@ error[E0308]: mismatched types | __________________^ 12 | | 0u8; 13 | | "bla".to_string(); //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon 14 | | } | |_^ expected struct `std::string::String`, found () | = note: expected type `std::string::String` found type `()` -help: consider removing this semicolon: - --> $DIR/consider-removing-last-semi.rs:13:22 - | -13 | "bla".to_string(); //~ HELP consider removing this semicolon - | ^ error[E0308]: mismatched types --> $DIR/consider-removing-last-semi.rs:16:18 @@ -23,16 +19,12 @@ error[E0308]: mismatched types | __________________^ 17 | | "this won't work".to_string(); 18 | | "removeme".to_string(); //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon 19 | | } | |_^ expected struct `std::string::String`, found () | = note: expected type `std::string::String` found type `()` -help: consider removing this semicolon: - --> $DIR/consider-removing-last-semi.rs:18:27 - | -18 | "removeme".to_string(); //~ HELP consider removing this semicolon - | ^ error: aborting due to previous error(s) diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr index cba9c3f51d7e3..ed61ec6ca291f 100644 --- a/src/test/ui/block-result/issue-11714.stderr +++ b/src/test/ui/block-result/issue-11714.stderr @@ -6,16 +6,12 @@ error[E0308]: mismatched types 12 | | 1 13 | | 14 | | ; //~ HELP consider removing this semicolon: + | | - help: consider removing this semicolon 15 | | } | |_^ expected i32, found () | = note: expected type `i32` found type `()` -help: consider removing this semicolon: - --> $DIR/issue-11714.rs:14:5 - | -14 | ; //~ HELP consider removing this semicolon: - | ^ error: aborting due to previous error(s) diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr index d0ed8935cd775..5e8d92f64e293 100644 --- a/src/test/ui/block-result/issue-13428.stderr +++ b/src/test/ui/block-result/issue-13428.stderr @@ -8,16 +8,12 @@ error[E0308]: mismatched types 16 | | // Put the trailing semicolon on its own line to test that the 17 | | // note message gets the offending semicolon exactly 18 | | ; //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon 19 | | } | |_^ expected struct `std::string::String`, found () | = note: expected type `std::string::String` found type `()` -help: consider removing this semicolon: - --> $DIR/issue-13428.rs:18:5 - | -18 | ; //~ HELP consider removing this semicolon - | ^ error[E0308]: mismatched types --> $DIR/issue-13428.rs:21:20 @@ -26,16 +22,12 @@ error[E0308]: mismatched types | ____________________^ 22 | | "foobar".to_string() 23 | | ; //~ HELP consider removing this semicolon + | | - help: consider removing this semicolon 24 | | } | |_^ expected struct `std::string::String`, found () | = note: expected type `std::string::String` found type `()` -help: consider removing this semicolon: - --> $DIR/issue-13428.rs:23:5 - | -23 | ; //~ HELP consider removing this semicolon - | ^ error: aborting due to previous error(s) diff --git a/src/test/ui/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion-missing-tail-expected-type.stderr index e96bc425e0b45..49e8b9febc2bb 100644 --- a/src/test/ui/coercion-missing-tail-expected-type.stderr +++ b/src/test/ui/coercion-missing-tail-expected-type.stderr @@ -4,16 +4,12 @@ error[E0308]: mismatched types 13 | fn plus_one(x: i32) -> i32 { | ____________________________^ 14 | | x + 1; + | | - help: consider removing this semicolon 15 | | } | |_^ expected i32, found () | = note: expected type `i32` found type `()` -help: consider removing this semicolon: - --> $DIR/coercion-missing-tail-expected-type.rs:14:10 - | -14 | x + 1; - | ^ error[E0308]: mismatched types --> $DIR/coercion-missing-tail-expected-type.rs:17:29 @@ -21,16 +17,12 @@ error[E0308]: mismatched types 17 | fn foo() -> Result { | _____________________________^ 18 | | Ok(1); + | | - help: consider removing this semicolon 19 | | } | |_^ expected enum `std::result::Result`, found () | = note: expected type `std::result::Result` found type `()` -help: consider removing this semicolon: - --> $DIR/coercion-missing-tail-expected-type.rs:18:10 - | -18 | Ok(1); - | ^ error: aborting due to previous error(s) From 27d4b314c5b663a8382a33bd69cb8b27134fb3f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 24 Jun 2017 12:16:20 -0700 Subject: [PATCH 4/6] Do not specify return type in suggestion for some `Ty`s Don't specify a suggested return type for `TyAnon`, `TyFnDef`, `TyFnPtr`, `TyDynamic`, `TyClosure` and `TyProjection`. --- src/librustc/ty/mod.rs | 12 ++++++++++++ src/librustc_typeck/check/mod.rs | 10 +++++++--- src/test/ui/block-result/issue-20862.stderr | 2 +- src/test/ui/block-result/issue-3563.stderr | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 13e46a265c695..65dd11bbc625f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -481,6 +481,18 @@ impl<'tcx> TyS<'tcx> { _ => false, } } + + pub fn is_suggestable(&self) -> bool { + match self.sty { + TypeVariants::TyAnon(..) | + TypeVariants::TyFnDef(..) | + TypeVariants::TyFnPtr(..) | + TypeVariants::TyDynamic(..) | + TypeVariants::TyClosure(..) | + TypeVariants::TyProjection(..) => false, + _ => true, + } + } } impl<'a, 'gcx, 'tcx> HashStable> for ty::TyS<'tcx> { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 0467f24948e75..50e2e390d020b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4349,9 +4349,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let &hir::FnDecl { output: hir::FunctionRetTy::DefaultReturn(span), .. } = fn_decl { - err.span_suggestion(span, - "possibly return type missing here?", - format!("-> {} ", ty)); + if ty.is_suggestable() { + err.span_suggestion(span, + "possibly return type missing here?", + format!("-> {} ", ty)); + } else { + err.span_label(span, "possibly return type missing here?"); + } } } diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr index 0d88a44d6b9b2..57cee8f7aca45 100644 --- a/src/test/ui/block-result/issue-20862.stderr +++ b/src/test/ui/block-result/issue-20862.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types 11 | fn foo(x: i32) { | - | | - | help: possibly return type missing here? `-> [closure@$DIR/issue-20862.rs:12:5: 12:14 x:_] ` + | possibly return type missing here? | expected `()` because of this default return type 12 | |y| x + y | ^^^^^^^^^ expected (), found closure diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr index e9ace85c1d91d..d995dee3827b1 100644 --- a/src/test/ui/block-result/issue-3563.stderr +++ b/src/test/ui/block-result/issue-3563.stderr @@ -10,7 +10,7 @@ error[E0308]: mismatched types 12 | fn a(&self) { | - | | - | help: possibly return type missing here? `-> [closure@$DIR/issue-3563.rs:13:9: 13:20 self:_] ` + | possibly return type missing here? | expected `()` because of this default return type 13 | || self.b() | ^^^^^^^^^^^ expected (), found closure From c13a913e5b4136ecb81ec835586e596ecef1a4b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 24 Jun 2017 19:28:43 -0700 Subject: [PATCH 5/6] Don't naively point to return type on type error --- src/librustc_typeck/check/coercion.rs | 6 ----- src/librustc_typeck/check/mod.rs | 22 ------------------- src/test/ui/block-result/issue-13624.stderr | 2 -- src/test/ui/block-result/issue-20862.stderr | 5 +---- src/test/ui/block-result/issue-22645.stderr | 3 --- src/test/ui/block-result/issue-3563.stderr | 5 +---- src/test/ui/block-result/issue-5500.stderr | 2 -- .../unexpected-return-on-unit.stderr | 2 -- src/test/ui/impl-trait/equality.stderr | 3 --- src/test/ui/mismatched_types/abridged.stderr | 12 ---------- .../ui/mismatched_types/issue-19109.stderr | 5 +---- .../ui/resolve/token-error-correct-3.stderr | 3 --- 12 files changed, 3 insertions(+), 67 deletions(-) diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 660f6c5a093f3..4b5d02f999551 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1174,12 +1174,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E> expected, found, cause.span, blk_id); } - ObligationCauseCode::ReturnType(ret_id) => { - db = fcx.report_mismatched_types(cause, expected, found, err); - if let Some((fn_decl, _)) = fcx.get_fn_decl(ret_id) { - fcx.point_to_type_requirement(&mut db, &fn_decl, expected); - } - } _ => { db = fcx.report_mismatched_types(cause, expected, found, err); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 50e2e390d020b..7c4b6a858d957 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4261,7 +4261,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.suggest_missing_semicolon(err, expression, expected, cause_span); if let Some((fn_decl, is_main)) = self.get_fn_decl(blk_id) { - self.point_to_type_requirement(err, &fn_decl, expected); // `fn main()` must return `()`, do not suggest changing return type if !is_main { self.suggest_missing_return_type(err, &fn_decl, found); @@ -4269,27 +4268,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - pub fn point_to_type_requirement(&self, - err: &mut DiagnosticBuilder<'tcx>, - fn_decl: &hir::FnDecl, - ty: Ty<'tcx>) { - let msg = if let &hir::FnDecl { - output: hir::FunctionRetTy::DefaultReturn(_), .. - } = fn_decl { - "default " - } else { - "" - }; - let ty = self.resolve_type_vars_if_possible(&ty); - if ty.to_string().len() < 10 { - err.span_label(fn_decl.output.span(), - format!("expected `{}` because of this {}return type", ty, msg)); - } else { - err.span_label(fn_decl.output.span(), - format!("expected because of this {}return type", msg)); - } - } - /// A common error is to forget to add a semicolon at the end of a block: /// /// ``` diff --git a/src/test/ui/block-result/issue-13624.stderr b/src/test/ui/block-result/issue-13624.stderr index 69c6e647cfc24..72ff859d7e93a 100644 --- a/src/test/ui/block-result/issue-13624.stderr +++ b/src/test/ui/block-result/issue-13624.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/issue-13624.rs:17:5 | -16 | pub fn get_enum_struct_variant() -> () { - | -- expected `()` because of this return type 17 | Enum::EnumStructVariant { x: 1, y: 2, z: 3 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found enum `a::Enum` | diff --git a/src/test/ui/block-result/issue-20862.stderr b/src/test/ui/block-result/issue-20862.stderr index 57cee8f7aca45..e4367f170ce18 100644 --- a/src/test/ui/block-result/issue-20862.stderr +++ b/src/test/ui/block-result/issue-20862.stderr @@ -2,10 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-20862.rs:12:5 | 11 | fn foo(x: i32) { - | - - | | - | possibly return type missing here? - | expected `()` because of this default return type + | - possibly return type missing here? 12 | |y| x + y | ^^^^^^^^^ expected (), found closure | diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr index 93da3c6a48932..3921a301c9223 100644 --- a/src/test/ui/block-result/issue-22645.stderr +++ b/src/test/ui/block-result/issue-22645.stderr @@ -11,9 +11,6 @@ error[E0277]: the trait bound `{integer}: Scalar` is not satisfied error[E0308]: mismatched types --> $DIR/issue-22645.rs:25:3 | -23 | fn main() { - | - expected `()` because of this default return type -24 | let b = Bob + 3.5; 25 | b + 3 //~ ERROR E0277 | ^^^^^ expected (), found struct `Bob` | diff --git a/src/test/ui/block-result/issue-3563.stderr b/src/test/ui/block-result/issue-3563.stderr index d995dee3827b1..c6ab4cbb2a7c5 100644 --- a/src/test/ui/block-result/issue-3563.stderr +++ b/src/test/ui/block-result/issue-3563.stderr @@ -8,10 +8,7 @@ error[E0308]: mismatched types --> $DIR/issue-3563.rs:13:9 | 12 | fn a(&self) { - | - - | | - | possibly return type missing here? - | expected `()` because of this default return type + | - possibly return type missing here? 13 | || self.b() | ^^^^^^^^^^^ expected (), found closure | diff --git a/src/test/ui/block-result/issue-5500.stderr b/src/test/ui/block-result/issue-5500.stderr index 6fda2aa00ffb3..bffe2a82ca8d7 100644 --- a/src/test/ui/block-result/issue-5500.stderr +++ b/src/test/ui/block-result/issue-5500.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/issue-5500.rs:12:5 | -11 | fn main() { - | - expected `()` because of this default return type 12 | &panic!() | ^^^^^^^^^ expected (), found reference | diff --git a/src/test/ui/block-result/unexpected-return-on-unit.stderr b/src/test/ui/block-result/unexpected-return-on-unit.stderr index e5481ffd31669..18d0cc4814056 100644 --- a/src/test/ui/block-result/unexpected-return-on-unit.stderr +++ b/src/test/ui/block-result/unexpected-return-on-unit.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/unexpected-return-on-unit.rs:19:5 | -18 | fn bar() { - | - expected `()` because of this default return type 19 | foo() | ^^^^^ expected (), found usize | diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr index ca37596f1b963..2206234b77744 100644 --- a/src/test/ui/impl-trait/equality.stderr +++ b/src/test/ui/impl-trait/equality.stderr @@ -1,9 +1,6 @@ error[E0308]: mismatched types --> $DIR/equality.rs:25:5 | -21 | fn two(x: bool) -> impl Foo { - | -------- expected `i32` because of this return type -... 25 | 0_u32 | ^^^^^ expected i32, found u32 | diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index 6282541ba0e41..78b5dcda1d9d2 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/abridged.rs:26:5 | -25 | fn a() -> Foo { - | --- expected `Foo` because of this return type 26 | Some(Foo { bar: 1 }) | ^^^^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::option::Option` | @@ -12,8 +10,6 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:30:5 | -29 | fn a2() -> Foo { - | --- expected `Foo` because of this return type 30 | Ok(Foo { bar: 1}) | ^^^^^^^^^^^^^^^^^ expected struct `Foo`, found enum `std::result::Result` | @@ -23,8 +19,6 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:34:5 | -33 | fn b() -> Option { - | ----------- expected because of this return type 34 | Foo { bar: 1 } | ^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `Foo` | @@ -34,8 +28,6 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:38:5 | -37 | fn c() -> Result { - | ---------------- expected because of this return type 38 | Foo { bar: 1 } | ^^^^^^^^^^^^^^ expected enum `std::result::Result`, found struct `Foo` | @@ -45,8 +37,6 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:42:5 | -41 | fn d() -> X, String> { - | ---------------------------- expected because of this return type 42 | / X { 43 | | x: X { 44 | | x: "".to_string(), @@ -62,8 +52,6 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/abridged.rs:52:5 | -51 | fn e() -> X, String> { - | ---------------------------- expected because of this return type 52 | / X { 53 | | x: X { 54 | | x: "".to_string(), diff --git a/src/test/ui/mismatched_types/issue-19109.stderr b/src/test/ui/mismatched_types/issue-19109.stderr index 5efa3fa6a1d5b..083c1f953330c 100644 --- a/src/test/ui/mismatched_types/issue-19109.stderr +++ b/src/test/ui/mismatched_types/issue-19109.stderr @@ -2,10 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-19109.rs:14:5 | 13 | fn function(t: &mut Trait) { - | - - | | - | help: possibly return type missing here? `-> *mut Trait ` - | expected `()` because of this default return type + | - help: possibly return type missing here? `-> *mut Trait ` 14 | t as *mut Trait | ^^^^^^^^^^^^^^^ expected (), found *-ptr | diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index 2a50428dbb9f9..53e9cb2177892 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -34,9 +34,6 @@ error[E0425]: cannot find function `is_directory` in this scope error[E0308]: mismatched types --> $DIR/token-error-correct-3.rs:25:13 | -20 | -> io::Result { - | ---------------- expected `()` because of this return type -... 25 | fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- help: did you mean to add a semicolon here? `;` | | From 7dad2958be59801881fb3db7544de423420dabd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 27 Jun 2017 13:34:56 -0700 Subject: [PATCH 6/6] Review comments - Fix typo - Add docstring - Remove spurious test output file --- src/librustc/hir/map/mod.rs | 22 +++++++++++++++++++ src/librustc_typeck/check/mod.rs | 4 ++-- .../expected-return-on-unit.stderr | 4 ---- 3 files changed, 24 insertions(+), 6 deletions(-) delete mode 100644 src/test/ui/block-result/expected-return-on-unit.stderr diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index ddcc2c0885085..02a36a372d9ef 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -632,6 +632,28 @@ impl<'hir> Map<'hir> { } } + /// Retrieve the NodeId for `id`'s enclosing method, unless there's a + /// `while` or `loop` before reacing it, as block tail returns are not + /// available in them. + /// + /// ``` + /// fn foo(x: usize) -> bool { + /// if x == 1 { + /// true // `get_return_block` gets passed the `id` corresponding + /// } else { // to this, it will return `foo`'s `NodeId`. + /// false + /// } + /// } + /// ``` + /// + /// ``` + /// fn foo(x: usize) -> bool { + /// loop { + /// true // `get_return_block` gets passed the `id` corresponding + /// } // to this, it will return `None`. + /// false + /// } + /// ``` pub fn get_return_block(&self, id: NodeId) -> Option { let match_fn = |node: &Node| { match *node { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7c4b6a858d957..cba930d312f8e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4214,7 +4214,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty } - /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and wether it is + /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether it is /// `fn main` if it is a method, `None` otherwise. pub fn get_fn_decl(&self, blk_id: ast::NodeId) -> Option<(hir::FnDecl, bool)> { // Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or @@ -4227,7 +4227,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }) = parent { decl.clone().and_then(|decl| { // This is less than ideal, it will not present the return type span on any - // method called `main`, regardless of wether it is actually the entry point. + // method called `main`, regardless of whether it is actually the entry point. Some((decl, name == Symbol::intern("main"))) }) } else if let Node::NodeTraitItem(&hir::TraitItem { diff --git a/src/test/ui/block-result/expected-return-on-unit.stderr b/src/test/ui/block-result/expected-return-on-unit.stderr deleted file mode 100644 index 8a0d7a335d6af..0000000000000 --- a/src/test/ui/block-result/expected-return-on-unit.stderr +++ /dev/null @@ -1,4 +0,0 @@ -error[E0601]: main function not found - -error: aborting due to previous error(s) -