Skip to content

Commit 576a361

Browse files
committed
Auto merge of #37780 - GuillaumeGomez:E0571, r=nikomatsakis
Add checkup for return statement outside of a function Fixes #37778. r? @eddyb (don't know who is in charge. Don't hesitate to set another one) cc @jonathandturner
2 parents 39c9f18 + ed3c483 commit 576a361

File tree

5 files changed

+59
-15
lines changed

5 files changed

+59
-15
lines changed

src/librustc_typeck/check/compare_method.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
376376
&infcx.parameter_environment.caller_bounds);
377377
infcx.resolve_regions_and_report_errors(&free_regions, impl_m_body_id);
378378
} else {
379-
let fcx = FnCtxt::new(&inh, tcx.types.err, impl_m_body_id);
379+
let fcx = FnCtxt::new(&inh, Some(tcx.types.err), impl_m_body_id);
380380
fcx.regionck_item(impl_m_body_id, impl_m_span, &[]);
381381
}
382382

src/librustc_typeck/check/mod.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
451451
// expects the types within the function to be consistent.
452452
err_count_on_creation: usize,
453453

454-
ret_ty: Ty<'tcx>,
454+
ret_ty: Option<Ty<'tcx>>,
455455

456456
ps: RefCell<UnsafetyState>,
457457

@@ -785,12 +785,14 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
785785

786786
// Create the function context. This is either derived from scratch or,
787787
// in the case of function expressions, based on the outer context.
788-
let mut fcx = FnCtxt::new(inherited, fn_sig.output(), body.id);
788+
let mut fcx = FnCtxt::new(inherited, None, body.id);
789+
let ret_ty = fn_sig.output();
789790
*fcx.ps.borrow_mut() = UnsafetyState::function(unsafety, unsafety_id);
790791

791-
fcx.require_type_is_sized(fcx.ret_ty, decl.output.span(), traits::ReturnType);
792-
fcx.ret_ty = fcx.instantiate_anon_types(&fcx.ret_ty);
793-
fn_sig = fcx.tcx.mk_fn_sig(fn_sig.inputs().iter().cloned(), &fcx.ret_ty, fn_sig.variadic);
792+
fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
793+
fcx.ret_ty = fcx.instantiate_anon_types(&Some(ret_ty));
794+
fn_sig = fcx.tcx.mk_fn_sig(fn_sig.inputs().iter().cloned(), &fcx.ret_ty.unwrap(),
795+
fn_sig.variadic);
794796

795797
{
796798
let mut visit = GatherLocalsVisitor { fcx: &fcx, };
@@ -821,7 +823,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
821823

822824
inherited.tables.borrow_mut().liberated_fn_sigs.insert(fn_id, fn_sig);
823825

824-
fcx.check_expr_coercable_to_type(body, fcx.ret_ty);
826+
fcx.check_expr_coercable_to_type(body, fcx.ret_ty.unwrap());
825827

826828
fcx
827829
}
@@ -1245,7 +1247,7 @@ fn check_const_with_type<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
12451247
expected_type: Ty<'tcx>,
12461248
id: ast::NodeId) {
12471249
ccx.inherited(id).enter(|inh| {
1248-
let fcx = FnCtxt::new(&inh, expected_type, expr.id);
1250+
let fcx = FnCtxt::new(&inh, None, expr.id);
12491251
fcx.require_type_is_sized(expected_type, expr.span, traits::ConstSized);
12501252

12511253
// Gather locals in statics (because of block expressions).
@@ -1530,7 +1532,7 @@ enum TupleArgumentsFlag {
15301532

15311533
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
15321534
pub fn new(inh: &'a Inherited<'a, 'gcx, 'tcx>,
1533-
rty: Ty<'tcx>,
1535+
rty: Option<Ty<'tcx>>,
15341536
body_id: ast::NodeId)
15351537
-> FnCtxt<'a, 'gcx, 'tcx> {
15361538
FnCtxt {
@@ -3705,14 +3707,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
37053707
}
37063708
hir::ExprAgain(_) => { tcx.types.never }
37073709
hir::ExprRet(ref expr_opt) => {
3708-
if let Some(ref e) = *expr_opt {
3709-
self.check_expr_coercable_to_type(&e, self.ret_ty);
3710+
if self.ret_ty.is_none() {
3711+
struct_span_err!(self.tcx.sess, expr.span, E0572,
3712+
"return statement outside of function body").emit();
3713+
} else if let Some(ref e) = *expr_opt {
3714+
self.check_expr_coercable_to_type(&e, self.ret_ty.unwrap());
37103715
} else {
37113716
match self.eq_types(false,
37123717
&self.misc(expr.span),
3713-
self.ret_ty,
3714-
tcx.mk_nil())
3715-
{
3718+
self.ret_ty.unwrap(),
3719+
tcx.mk_nil()) {
37163720
Ok(ok) => self.register_infer_ok_obligations(ok),
37173721
Err(_) => {
37183722
struct_span_err!(tcx.sess, expr.span, E0069,

src/librustc_typeck/check/wfcheck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> {
5151
let id = self.id;
5252
let span = self.span;
5353
self.inherited.enter(|inh| {
54-
let fcx = FnCtxt::new(&inh, inh.ccx.tcx.types.never, id);
54+
let fcx = FnCtxt::new(&inh, Some(inh.ccx.tcx.types.never), id);
5555
let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor {
5656
ccx: fcx.ccx,
5757
code: code

src/librustc_typeck/diagnostics.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4164,6 +4164,33 @@ target / ABI combination is currently unsupported by llvm.
41644164
If necessary, you can circumvent this check using custom target specifications.
41654165
"##,
41664166

4167+
E0572: r##"
4168+
A return statement was found outside of a function body.
4169+
4170+
Erroneous code example:
4171+
4172+
```compile_fail,E0572
4173+
const FOO: u32 = return 0; // error: return statement outside of function body
4174+
4175+
fn main() {}
4176+
```
4177+
4178+
To fix this issue, just remove the return keyword or move the expression into a
4179+
function. Example:
4180+
4181+
```
4182+
const FOO: u32 = 0;
4183+
4184+
fn some_fn() -> u32 {
4185+
return FOO;
4186+
}
4187+
4188+
fn main() {
4189+
some_fn();
4190+
}
4191+
```
4192+
"##,
4193+
41674194
}
41684195

41694196
register_diagnostics! {

src/test/compile-fail/E0572.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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+
const FOO: u32 = return 0; //~ ERROR E0572
12+
13+
fn main() {}

0 commit comments

Comments
 (0)