@@ -124,6 +124,7 @@ use rustc::hir::intravisit::{self, Visitor};
124
124
use rustc:: hir:: itemlikevisit:: ItemLikeVisitor ;
125
125
use rustc:: hir:: { self , PatKind } ;
126
126
use rustc:: hir:: print as pprust;
127
+ use rustc:: hir:: map:: Node ;
127
128
use rustc_back:: slice;
128
129
use rustc_const_eval:: eval_length;
129
130
@@ -3666,7 +3667,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3666
3667
self . check_expr_closure ( expr, capture, & decl, & body, expected)
3667
3668
}
3668
3669
hir:: ExprBlock ( ref b) => {
3669
- self . check_block_with_expected ( & b, expected)
3670
+ self . check_block_with_expected ( & b, expected)
3670
3671
}
3671
3672
hir:: ExprCall ( ref callee, ref args) => {
3672
3673
self . check_call ( expr, & callee, & args[ ..] , expected)
@@ -4085,7 +4086,57 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4085
4086
} else if let ExpectHasType ( ety) = expected {
4086
4087
if let Some ( ref e) = blk. expr {
4087
4088
// 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
+ }
4089
4140
} else {
4090
4141
// We're not diverging and there's an expected type, which,
4091
4142
// in case it's not `()`, could result in an error higher-up.
@@ -4118,9 +4169,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4118
4169
hi : original_span. hi ,
4119
4170
expn_id : original_span. expn_id
4120
4171
} ;
4121
- err. span_help ( span_semi, "consider removing this semicolon: " ) ;
4172
+ err. span_label ( span_semi, & "consider removing this semicolon" ) ;
4122
4173
}
4123
-
4124
4174
err. emit ( ) ;
4125
4175
}
4126
4176
}
0 commit comments