@@ -4796,20 +4796,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
47964796 // `consider_hint_about_removing_semicolon` will point at the last expression
47974797 // if it were a relevant part of the error. This improves usability in editors
47984798 // that highlight errors inline.
4799- let ( sp, fn_span) = if let Some ( ( decl, ident) ) = self . get_parent_fn_decl ( blk. id ) {
4800- ( decl. output . span ( ) , Some ( ident. span ) )
4801- } else {
4802- ( blk. span , None )
4803- } ;
4799+ let mut sp = blk. span ;
4800+ let mut fn_span = None ;
4801+ if let Some ( ( decl, ident) ) = self . get_parent_fn_decl ( blk. id ) {
4802+ let ret_sp = decl. output . span ( ) ;
4803+ if let Some ( block_sp) = self . parent_item_span ( blk. id ) {
4804+ // HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
4805+ // output would otherwise be incorrect and even misleading. Make sure
4806+ // the span we're aiming at correspond to a `fn` body.
4807+ if block_sp == blk. span {
4808+ sp = ret_sp;
4809+ fn_span = Some ( ident. span ) ;
4810+ }
4811+ }
4812+ }
48044813 coerce. coerce_forced_unit ( self , & self . misc ( sp) , & mut |err| {
48054814 if let Some ( expected_ty) = expected. only_has_type ( self ) {
48064815 self . consider_hint_about_removing_semicolon ( blk, expected_ty, err) ;
48074816 }
48084817 if let Some ( fn_span) = fn_span {
4809- err. span_label (
4810- fn_span,
4811- "this function's body doesn't return the expected type" ,
4812- ) ;
4818+ err. span_label ( fn_span, "this function's body doesn't return" ) ;
48134819 }
48144820 } , false ) ;
48154821 }
@@ -4834,6 +4840,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
48344840 ty
48354841 }
48364842
4843+ fn parent_item_span ( & self , id : ast:: NodeId ) -> Option < Span > {
4844+ let node = self . tcx . hir ( ) . get ( self . tcx . hir ( ) . get_parent ( id) ) ;
4845+ match node {
4846+ Node :: Item ( & hir:: Item {
4847+ node : hir:: ItemKind :: Fn ( _, _, _, body_id) , ..
4848+ } ) |
4849+ Node :: ImplItem ( & hir:: ImplItem {
4850+ node : hir:: ImplItemKind :: Method ( _, body_id) , ..
4851+ } ) => {
4852+ let body = self . tcx . hir ( ) . body ( body_id) ;
4853+ if let ExprKind :: Block ( block, _) = & body. value . node {
4854+ return Some ( block. span ) ;
4855+ }
4856+ }
4857+ _ => { }
4858+ }
4859+ None
4860+ }
4861+
48374862 /// Given a function block's `NodeId`, return its `FnDecl` , `None` otherwise.
48384863 fn get_parent_fn_decl ( & self , blk_id : ast:: NodeId ) -> Option < ( hir:: FnDecl , ast:: Ident ) > {
48394864 let parent = self . tcx . hir ( ) . get ( self . tcx . hir ( ) . get_parent ( blk_id) ) ;
@@ -4842,33 +4867,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
48424867
48434868 /// Given a function `Node`, return its `FnDecl` , `None` otherwise.
48444869 fn get_node_fn_decl ( & self , node : Node ) -> Option < ( hir:: FnDecl , ast:: Ident , bool ) > {
4845- if let Node :: Item ( & hir :: Item {
4846- ident , node : hir:: ItemKind :: Fn ( ref decl , .. ) , ..
4847- } ) = node {
4848- decl. clone ( ) . and_then ( |decl| {
4870+ match node {
4871+ Node :: Item ( & hir:: Item {
4872+ ident , node : hir :: ItemKind :: Fn ( ref decl , .. ) , ..
4873+ } ) => decl. clone ( ) . and_then ( |decl| {
48494874 // This is less than ideal, it will not suggest a return type span on any
48504875 // method called `main`, regardless of whether it is actually the entry point,
48514876 // but it will still present it as the reason for the expected type.
48524877 Some ( ( decl, ident, ident. name != Symbol :: intern ( "main" ) ) )
4853- } )
4854- } else if let Node :: TraitItem ( & hir:: TraitItem {
4855- ident, node : hir:: TraitItemKind :: Method ( hir:: MethodSig {
4856- ref decl, ..
4857- } , ..) , ..
4858- } ) = node {
4859- decl. clone ( ) . and_then ( |decl| {
4860- Some ( ( decl, ident, true ) )
4861- } )
4862- } else if let Node :: ImplItem ( & hir:: ImplItem {
4863- ident, node : hir:: ImplItemKind :: Method ( hir:: MethodSig {
4864- ref decl, ..
4865- } , ..) , ..
4866- } ) = node {
4867- decl. clone ( ) . and_then ( |decl| {
4868- Some ( ( decl, ident, false ) )
4869- } )
4870- } else {
4871- None
4878+ } ) ,
4879+ Node :: TraitItem ( & hir:: TraitItem {
4880+ ident, node : hir:: TraitItemKind :: Method ( hir:: MethodSig {
4881+ ref decl, ..
4882+ } , ..) , ..
4883+ } ) => decl. clone ( ) . and_then ( |decl| Some ( ( decl, ident, true ) ) ) ,
4884+ Node :: ImplItem ( & hir:: ImplItem {
4885+ ident, node : hir:: ImplItemKind :: Method ( hir:: MethodSig {
4886+ ref decl, ..
4887+ } , ..) , ..
4888+ } ) => decl. clone ( ) . and_then ( |decl| Some ( ( decl, ident, false ) ) ) ,
4889+ _ => None ,
48724890 }
48734891 }
48744892
0 commit comments