diff options
| author | Fabian Wolff <fabian.wolff@alumni.ethz.ch> | 2021-06-11 01:20:00 +0200 |
|---|---|---|
| committer | Fabian Wolff <fabian.wolff@alumni.ethz.ch> | 2021-06-11 01:20:00 +0200 |
| commit | bdddaebd76cba207b67141e2c362a4fe117bbd34 (patch) | |
| tree | 1ecd5fe6a4cffb808b9a7256c00e058f48477301 /compiler | |
| parent | 40c1623b16fb28f7625cab13570752d04513815c (diff) | |
| download | rust-bdddaebd76cba207b67141e2c362a4fe117bbd34.tar.gz rust-bdddaebd76cba207b67141e2c362a4fe117bbd34.zip | |
Fix type checking of return expressions outside fn bodies
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_typeck/src/check/expr.rs | 34 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/errors.rs | 4 |
2 files changed, 37 insertions, 1 deletions
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index d0cbb58fb10..e9bb2b1c914 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -674,7 +674,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { if self.ret_coercion.is_none() { - self.tcx.sess.emit_err(ReturnStmtOutsideOfFnBody { span: expr.span }); + let mut err = ReturnStmtOutsideOfFnBody { + span: expr.span, + encl_body_span: None, + encl_fn_span: None, + }; + + let encl_item_id = self.tcx.hir().get_parent_item(expr.hir_id); + let encl_item = self.tcx.hir().expect_item(encl_item_id); + + if let hir::ItemKind::Fn(..) = encl_item.kind { + // We are inside a function body, so reporting "return statement + // outside of function body" needs an explanation. + + let encl_body_owner_id = self.tcx.hir().enclosing_body_owner(expr.hir_id); + + // If this didn't hold, we would not have to report an error in + // the first place. + assert_ne!(encl_item_id, encl_body_owner_id); + + let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id); + let encl_body = self.tcx.hir().body(encl_body_id); + + err.encl_body_span = Some(encl_body.value.span); + err.encl_fn_span = Some(encl_item.span); + } + + self.tcx.sess.emit_err(err); + + if let Some(e) = expr_opt { + // We still have to type-check `e` (issue #86188), but calling + // `check_return_expr` only works inside fn bodies. + self.check_expr(e); + } } else if let Some(e) = expr_opt { if self.ret_coercion_span.get().is_none() { self.ret_coercion_span.set(Some(e.span)); diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs index 5068242692a..1a21c085d53 100644 --- a/compiler/rustc_typeck/src/errors.rs +++ b/compiler/rustc_typeck/src/errors.rs @@ -147,6 +147,10 @@ pub struct TypeofReservedKeywordUsed { pub struct ReturnStmtOutsideOfFnBody { #[message = "return statement outside of function body"] pub span: Span, + #[label = "the return is part of this body..."] + pub encl_body_span: Option<Span>, + #[label = "...not the enclosing function body"] + pub encl_fn_span: Option<Span>, } #[derive(SessionDiagnostic)] |
