@@ -4187,8 +4187,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4187
4187
ty
4188
4188
}
4189
4189
4190
- /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether it is
4191
- /// `fn main` if it is a method , `None` otherwise.
4190
+ /// Given a `NodeId`, return the `FnDecl` of the method it is enclosed by and whether a
4191
+ /// suggetion can be made , `None` otherwise.
4192
4192
pub fn get_fn_decl ( & self , blk_id : ast:: NodeId ) -> Option < ( hir:: FnDecl , bool ) > {
4193
4193
// Get enclosing Fn, if it is a function or a trait method, unless there's a `loop` or
4194
4194
// `while` before reaching it, as block tail returns are not available in them.
@@ -4199,14 +4199,23 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4199
4199
name, node : hir:: ItemFn ( ref decl, ..) , ..
4200
4200
} ) = parent {
4201
4201
decl. clone ( ) . and_then ( |decl| {
4202
- // This is less than ideal, it will not present the return type span on any
4203
- // method called `main`, regardless of whether it is actually the entry point.
4204
- Some ( ( decl, name == Symbol :: intern ( "main" ) ) )
4202
+ // This is less than ideal, it will not suggest a return type span on any
4203
+ // method called `main`, regardless of whether it is actually the entry point,
4204
+ // but it will still present it as the reason for the expected type.
4205
+ Some ( ( decl, name != Symbol :: intern ( "main" ) ) )
4205
4206
} )
4206
4207
} else if let Node :: NodeTraitItem ( & hir:: TraitItem {
4207
4208
node : hir:: TraitItemKind :: Method ( hir:: MethodSig {
4208
4209
ref decl, ..
4209
4210
} , ..) , ..
4211
+ } ) = parent {
4212
+ decl. clone ( ) . and_then ( |decl| {
4213
+ Some ( ( decl, true ) )
4214
+ } )
4215
+ } else if let Node :: NodeImplItem ( & hir:: ImplItem {
4216
+ node : hir:: ImplItemKind :: Method ( hir:: MethodSig {
4217
+ ref decl, ..
4218
+ } , ..) , ..
4210
4219
} ) = parent {
4211
4220
decl. clone ( ) . and_then ( |decl| {
4212
4221
Some ( ( decl, false ) )
@@ -4233,11 +4242,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4233
4242
blk_id : ast:: NodeId ) {
4234
4243
self . suggest_missing_semicolon ( err, expression, expected, cause_span) ;
4235
4244
4236
- if let Some ( ( fn_decl, is_main) ) = self . get_fn_decl ( blk_id) {
4237
- // `fn main()` must return `()`, do not suggest changing return type
4238
- if !is_main {
4239
- self . suggest_missing_return_type ( err, & fn_decl, found) ;
4240
- }
4245
+ if let Some ( ( fn_decl, can_suggest) ) = self . get_fn_decl ( blk_id) {
4246
+ self . suggest_missing_return_type ( err, & fn_decl, expected, found, can_suggest) ;
4241
4247
}
4242
4248
}
4243
4249
@@ -4293,20 +4299,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4293
4299
fn suggest_missing_return_type ( & self ,
4294
4300
err : & mut DiagnosticBuilder < ' tcx > ,
4295
4301
fn_decl : & hir:: FnDecl ,
4296
- ty : Ty < ' tcx > ) {
4302
+ expected : Ty < ' tcx > ,
4303
+ found : Ty < ' tcx > ,
4304
+ can_suggest : bool ) {
4297
4305
4298
- // Only recommend changing the return type for methods that
4306
+ // Only suggest changing the return type for methods that
4299
4307
// haven't set a return type at all (and aren't `fn main()` or an impl).
4300
- if let & hir:: FnDecl {
4301
- output : hir:: FunctionRetTy :: DefaultReturn ( span) , ..
4302
- } = fn_decl {
4303
- if ty. is_suggestable ( ) {
4308
+ match ( & fn_decl. output , found. is_suggestable ( ) , can_suggest) {
4309
+ ( & hir:: FunctionRetTy :: DefaultReturn ( span) , true , true ) => {
4304
4310
err. span_suggestion ( span,
4305
4311
"try adding a return type" ,
4306
- format ! ( "-> {} " , ty) ) ;
4307
- } else {
4312
+ format ! ( "-> {} " , found) ) ;
4313
+ }
4314
+ ( & hir:: FunctionRetTy :: DefaultReturn ( span) , false , true ) => {
4308
4315
err. span_label ( span, "possibly return type missing here?" ) ;
4309
4316
}
4317
+ ( & hir:: FunctionRetTy :: DefaultReturn ( span) , _, _) => {
4318
+ // `fn main()` must return `()`, do not suggest changing return type
4319
+ err. span_label ( span, "expected `()` because of default return type" ) ;
4320
+ }
4321
+ ( & hir:: FunctionRetTy :: Return ( ref ty) , _, _) => {
4322
+ // Only point to return type if the expected type is the return type, as if they
4323
+ // are not, the expectation must have been caused by something else.
4324
+ err. span_label ( ty. span ,
4325
+ format ! ( "expected `{}` because of return type" , expected) ) ;
4326
+ }
4310
4327
}
4311
4328
}
4312
4329
0 commit comments