@@ -124,6 +124,7 @@ use rustc::hir::intravisit::{self, Visitor};
124124use rustc:: hir:: itemlikevisit:: ItemLikeVisitor ;
125125use rustc:: hir:: { self , PatKind } ;
126126use rustc:: hir:: print as pprust;
127+ use rustc:: hir:: map:: Node ;
127128use rustc_back:: slice;
128129use rustc_const_eval:: eval_length;
129130
@@ -3666,7 +3667,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
36663667 self . check_expr_closure ( expr, capture, & decl, & body, expected)
36673668 }
36683669 hir:: ExprBlock ( ref b) => {
3669- self . check_block_with_expected ( & b, expected)
3670+ self . check_block_with_expected ( & b, expected)
36703671 }
36713672 hir:: ExprCall ( ref callee, ref args) => {
36723673 self . check_call ( expr, & callee, & args[ ..] , expected)
@@ -4085,7 +4086,57 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
40854086 } else if let ExpectHasType ( ety) = expected {
40864087 if let Some ( ref e) = blk. expr {
40874088 // Coerce the tail expression to the right type.
4088- self . demand_coerce ( e, ty, ety) ;
4089+ if let Some ( mut err) = self . demand_coerce_diag ( e, ty, ety) {
4090+ // Be helpful when the user wrote `{... expr}` and
4091+ // adding a `;` is enough to fix the error.
4092+ if ety. is_nil ( ) {
4093+ let span = Span {
4094+ lo : e. span . hi ,
4095+ hi : e. span . hi + BytePos ( 1 ) ,
4096+ expn_id : e. span . expn_id
4097+ } ;
4098+ err. span_label ( span, & "consider adding a semicolon here" ) ;
4099+ }
4100+
4101+ // Is the block part of a fn?
4102+ let parent = self . tcx . map . get ( self . tcx . map . get_parent ( blk. id ) ) ;
4103+ let fn_decl = if let Node :: NodeItem ( & hir:: Item {
4104+ name, node : hir:: ItemFn ( ref decl, ..) , ..
4105+ } ) = parent {
4106+ // `fn main` must return `()`
4107+ if name. as_str ( ) != "main" {
4108+ decl. clone ( ) . and_then ( |decl| {
4109+ Some ( decl)
4110+ } )
4111+ } else {
4112+ None
4113+ }
4114+ } else if let Node :: NodeTraitItem ( & hir:: TraitItem {
4115+ node : hir:: TraitItem_ :: MethodTraitItem ( hir:: MethodSig {
4116+ ref decl, ..
4117+ } , ..) , ..
4118+ } ) = parent {
4119+ decl. clone ( ) . and_then ( |decl| {
4120+ Some ( decl)
4121+ } )
4122+ } else {
4123+ // Do not recomend changing return type of `ImplItemKind::Method`
4124+ None
4125+ } ;
4126+
4127+ // Only recommend changing the return type for methods that
4128+ // haven't set a return type at all.
4129+ if let Some ( hir:: FnDecl {
4130+ output : hir:: FunctionRetTy :: DefaultReturn ( span) ,
4131+ ..
4132+ } ) = fn_decl {
4133+ err. span_label ( span,
4134+ & format ! ( "possibly return type `{}` \
4135+ missing here",
4136+ ty) ) ;
4137+ }
4138+ err. emit ( ) ;
4139+ }
40894140 } else {
40904141 // We're not diverging and there's an expected type, which,
40914142 // in case it's not `()`, could result in an error higher-up.
@@ -4118,9 +4169,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
41184169 hi : original_span. hi ,
41194170 expn_id : original_span. expn_id
41204171 } ;
4121- err. span_help ( span_semi, "consider removing this semicolon: " ) ;
4172+ err. span_label ( span_semi, & "consider removing this semicolon" ) ;
41224173 }
4123-
41244174 err. emit ( ) ;
41254175 }
41264176 }
0 commit comments