Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 555fb3a

Browse files
committedNov 21, 2016
Detect missing ; on methods with return type ()
On a given file `foo.rs`: ```rust fn foo() { return 1; } fn main() { 3 } ``` Provide the following output: ```bash error[E0308]: mismatched types --> foo.rs:2:12 | 1 | fn foo() { | ^ possibly return type `{integer}` missing in this fn? 2 | return 1; | ^ expected (), found integral variable | = note: expected type `()` = note: found type `{integer}` error[E0308]: mismatched types --> foo.rs:6:5 | 6 | 3 | ^ | | | possibly `;` missing here? | expected (), found integral variable | = note: expected type `()` = note: found type `{integer}` error: aborting due to 2 previous errors ```
1 parent fb12219 commit 555fb3a

14 files changed

+193
-32
lines changed
 

‎src/librustc_typeck/check/demand.rs

+45-3
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010

1111

1212
use check::FnCtxt;
13-
use rustc::ty::Ty;
14-
use rustc::infer::{InferOk};
13+
use hir::map::Node;
14+
use rustc::infer::{InferOk, TypeTrace};
1515
use rustc::traits::ObligationCause;
16+
use rustc::ty::Ty;
17+
use rustc::ty::error::TypeError;
1618

1719
use syntax_pos::Span;
1820
use rustc::hir;
@@ -57,7 +59,47 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
5759
if let Err(e) = self.try_coerce(expr, checked_ty, expected) {
5860
let cause = self.misc(expr.span);
5961
let expr_ty = self.resolve_type_vars_with_obligations(checked_ty);
60-
self.report_mismatched_types(&cause, expected, expr_ty, e);
62+
let trace = TypeTrace::types(&cause, true, expected, expr_ty);
63+
let mut diag = self.report_and_explain_type_error(trace, &e);
64+
65+
if let Node::NodeBlock(block) = self.tcx.map
66+
.get(self.tcx.map.get_parent_node(expr.id))
67+
{
68+
if let TypeError::Sorts(ref values) = e {
69+
if values.expected.is_nil() {
70+
// An implicit return to a method with return type `()`
71+
diag.span_label(expr.span,
72+
&"possibly missing `;` here?");
73+
// Get the current node's method definition
74+
if let Node::NodeExpr(item) = self.tcx.map
75+
.get(self.tcx.map.get_parent_node(block.id))
76+
{
77+
// The fn has a default return type of ()
78+
if let Node::NodeItem(&hir::Item {
79+
name,
80+
node: hir::ItemFn(ref decl, ..),
81+
..
82+
}) = self.tcx.map.get(self.tcx.map.get_parent_node(item.id)) {
83+
// `main` *must* have return type ()
84+
if name.as_str() != "main" {
85+
decl.clone().and_then(|decl| {
86+
if let hir::FnDecl {
87+
output: hir::FunctionRetTy::DefaultReturn(span),
88+
..
89+
} = decl {
90+
diag.span_label(span,
91+
&format!("possibly return type `{}` \
92+
missing in this fn?",
93+
values.found));
94+
}
95+
});
96+
}
97+
}
98+
}
99+
}
100+
}
101+
};
102+
diag.emit();
61103
}
62104
}
63105
}

‎src/test/compile-fail/block-must-not-have-result-do.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010

1111
fn main() {
1212
loop {
13-
true //~ ERROR mismatched types
13+
true
14+
//~^ ERROR mismatched types
15+
//~| ERROR mismatched types
16+
//~| NOTE: possibly missing `;` here?
17+
//~| NOTE: expected (), found bool
18+
//~| NOTE: expected type `()`
19+
//~| NOTE: expected type `()`
20+
//~| NOTE: found type `bool`
21+
//~| NOTE: found type `bool`
1422
}
1523
}

‎src/test/compile-fail/block-must-not-have-result-res.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,15 @@ struct r;
1212

1313
impl Drop for r {
1414
fn drop(&mut self) {
15-
true //~ ERROR mismatched types
15+
true
16+
//~^ ERROR: mismatched types
17+
//~| ERROR: mismatched types
18+
//~| NOTE: possibly missing `;` here?
19+
//~| NOTE: expected (), found bool
20+
//~| NOTE: expected type `()`
21+
//~| NOTE: expected type `()`
22+
//~| NOTE: found type `bool`
23+
//~| NOTE: found type `bool`
1624
}
1725
}
1826

‎src/test/compile-fail/block-must-not-have-result-while.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@
1010

1111
fn main() {
1212
while true {
13-
true //~ ERROR mismatched types
14-
//~| expected type `()`
15-
//~| found type `bool`
16-
//~| expected (), found bool
13+
true
14+
//~^ ERROR: mismatched types
15+
//~| ERROR: mismatched types
16+
//~| NOTE: possibly missing `;` here?
17+
//~| NOTE: expected (), found bool
18+
//~| NOTE: expected type `()`
19+
//~| NOTE: expected type `()`
20+
//~| NOTE: found type `bool`
21+
//~| NOTE: found type `bool`
1722
}
1823
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that we do some basic error correcton in the tokeniser (and don't spew
12+
// too many bogus errors).
13+
14+
fn main() {
15+
return 1;
16+
//~^ mismatched types
17+
//~| expected type `()`
18+
//~| found type `{integer}`
19+
}

‎src/test/compile-fail/issue-13624.rs

+12-8
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@ mod a {
1515

1616
pub fn get_enum_struct_variant() -> () {
1717
Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
18-
//~^ ERROR mismatched types
19-
//~| expected type `()`
20-
//~| found type `a::Enum`
21-
//~| expected (), found enum `a::Enum`
18+
//~^ ERROR: mismatched types
19+
//~| ERROR: mismatched types
20+
//~| NOTE: possibly missing `;` here?
21+
//~| NOTE: expected (), found enum `a::Enum`
22+
//~| NOTE: expected type `()`
23+
//~| NOTE: expected type `()`
24+
//~| NOTE: found type `a::Enum`
25+
//~| NOTE: found type `a::Enum`
2226
}
2327
}
2428

@@ -30,10 +34,10 @@ mod b {
3034
let enum_struct_variant = ::a::get_enum_struct_variant();
3135
match enum_struct_variant {
3236
a::Enum::EnumStructVariant { x, y, z } => {
33-
//~^ ERROR mismatched types
34-
//~| expected type `()`
35-
//~| found type `a::Enum`
36-
//~| expected (), found enum `a::Enum`
37+
//~^ ERROR: mismatched types
38+
//~| NOTE: expected (), found enum `a::Enum`
39+
//~| NOTE: expected type `()`
40+
//~| NOTE: found type `a::Enum`
3741
}
3842
}
3943
}

‎src/test/compile-fail/issue-19109.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,16 @@
1111
trait Trait { }
1212

1313
fn function(t: &mut Trait) {
14+
//~^ NOTE: possibly return type `*mut Trait` missing in this fn?
1415
t as *mut Trait
15-
//~^ ERROR: mismatched types
16-
//~| NOTE: expected type `()`
17-
//~| NOTE: found type `*mut Trait`
18-
//~| NOTE: expected (), found *-ptr
16+
//~^ ERROR: mismatched types
17+
//~| ERROR: mismatched types
18+
//~| NOTE: possibly missing `;` here?
19+
//~| NOTE: expected (), found *-ptr
20+
//~| NOTE: expected type `()`
21+
//~| NOTE: expected type `()`
22+
//~| NOTE: found type `*mut Trait`
23+
//~| NOTE: found type `*mut Trait`
1924
}
2025

2126
fn main() { }

‎src/test/compile-fail/issue-20862.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,20 @@
99
// except according to those terms.
1010

1111
fn foo(x: i32) {
12+
//~^ NOTE: possibly return type
1213
|y| x + y
13-
//~^ ERROR: mismatched types
14+
//~^ ERROR: mismatched types
15+
//~| ERROR: mismatched types
16+
//~| NOTE: possibly missing `;` here?
17+
//~| NOTE: expected (), found closure
18+
//~| NOTE: expected type `()`
19+
//~| NOTE: expected type `()`
20+
//~| NOTE: found type
21+
//~| NOTE: found type
1422
}
1523

24+
1625
fn main() {
1726
let x = foo(5)(2);
18-
//~^ ERROR: expected function, found `()`
27+
//~^ ERROR: expected function, found `()`
1928
}

‎src/test/compile-fail/issue-22645.rs

+9
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,13 @@ fn main() {
2424
let b = Bob + 3.5;
2525
b + 3 //~ ERROR E0277
2626
//~^ ERROR: mismatched types
27+
//~| ERROR: mismatched types
28+
//~| NOTE: possibly missing `;` here?
29+
//~| NOTE: expected (), found
30+
//~| NOTE: expected type `()`
31+
//~| NOTE: expected type `()`
32+
//~| NOTE: found type
33+
//~| NOTE: found type
34+
//~| NOTE: the trait `Scalar` is not implemented for `{integer}`
35+
//~| NOTE: required because of the requirements on the impl of `std::ops::Add<{integer}>`
2736
}

‎src/test/compile-fail/issue-3563.rs

+7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ trait A {
1313
|| self.b()
1414
//~^ ERROR no method named `b` found for type `&Self` in the current scope
1515
//~| ERROR mismatched types
16+
//~| ERROR mismatched types
17+
//~| NOTE: possibly missing `;` here?
18+
//~| NOTE: expected (), found closure
19+
//~| NOTE: expected type `()`
20+
//~| NOTE: expected type `()`
21+
//~| NOTE: found type
22+
//~| NOTE: found type
1623
}
1724
}
1825
fn main() {}

‎src/test/compile-fail/issue-5500.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111
fn main() {
1212
&panic!()
1313
//~^ ERROR mismatched types
14-
//~| expected type `()`
15-
//~| found type `&_`
16-
//~| expected (), found reference
14+
//~| ERROR mismatched types
15+
//~| NOTE: possibly missing `;` here?
16+
//~| NOTE: expected (), found reference
17+
//~| NOTE: expected type `()`
18+
//~| NOTE: expected type `()`
19+
//~| NOTE: found type `&_`
20+
//~| NOTE: found type `&_`
1721
}

‎src/test/compile-fail/specialization/specialization-default-projection.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,26 @@ fn generic<T>() -> <T as Foo>::Assoc {
2828
// `T` could be some downstream crate type that specializes (or,
2929
// for that matter, `u8`).
3030

31-
() //~ ERROR mismatched types
31+
()
32+
//~^ ERROR mismatched types
33+
//~| NOTE: expected associated type, found ()
34+
//~| NOTE: expected type `<T as Foo>::Assoc`
35+
//~| NOTE: found type `()`
3236
}
3337

3438
fn monomorphic() -> () {
3539
// Even though we know that `()` is not specialized in a
3640
// downstream crate, typeck refuses to project here.
3741

38-
generic::<()>() //~ ERROR mismatched types
42+
generic::<()>()
43+
//~^ ERROR mismatched types
44+
//~| ERROR mismatched types
45+
//~| NOTE: possibly missing `;` here?
46+
//~| NOTE: expected (), found associated type
47+
//~| NOTE: expected type `()`
48+
//~| NOTE: expected type `()`
49+
//~| NOTE: found type
50+
//~| NOTE: found type
3951
}
4052

4153
fn main() {

‎src/test/compile-fail/token-error-correct-3.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,15 @@ pub mod raw {
2222
//~| NOTE unresolved name
2323
callback(path.as_ref(); //~ NOTE: unclosed delimiter
2424
//~^ ERROR: expected one of
25-
fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types
26-
//~^ expected (), found enum `std::result::Result`
27-
//~| expected type `()`
28-
//~| found type `std::result::Result<bool, std::io::Error>`
25+
fs::create_dir_all(path.as_ref()).map(|()| true)
26+
//~^ ERROR mismatched types
27+
//~| ERROR mismatched types
28+
//~| NOTE: possibly missing `;` here?
29+
//~| NOTE: expected (), found enum `std::result::Result`
30+
//~| NOTE: expected type `()`
31+
//~| NOTE: expected type `()`
32+
//~| NOTE: found type `std::result::Result<bool, std::io::Error>`
33+
//~| NOTE: found type `std::result::Result<bool, std::io::Error>`
2934
} else { //~ ERROR: incorrect close delimiter: `}`
3035
//~^ ERROR: expected one of
3136
Ok(false);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that we do some basic error correcton in the tokeniser (and don't spew
12+
// too many bogus errors).
13+
14+
fn main() {
15+
1
16+
//~^ ERROR mismatched types
17+
//~| ERROR mismatched types
18+
//~| NOTE: possibly missing `;` here?
19+
//~| NOTE: expected (), found integral variable
20+
//~| NOTE: expected type `()`
21+
//~| NOTE: expected type `()`
22+
//~| NOTE: found type `{integer}`
23+
//~| NOTE: found type `{integer}`
24+
}

0 commit comments

Comments
 (0)
Please sign in to comment.