@@ -4796,20 +4796,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4796
4796
// `consider_hint_about_removing_semicolon` will point at the last expression
4797
4797
// if it were a relevant part of the error. This improves usability in editors
4798
4798
// 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
+ }
4804
4813
coerce. coerce_forced_unit ( self , & self . misc ( sp) , & mut |err| {
4805
4814
if let Some ( expected_ty) = expected. only_has_type ( self ) {
4806
4815
self . consider_hint_about_removing_semicolon ( blk, expected_ty, err) ;
4807
4816
}
4808
4817
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" ) ;
4813
4819
}
4814
4820
} , false ) ;
4815
4821
}
@@ -4834,6 +4840,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
4834
4840
ty
4835
4841
}
4836
4842
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
+
4837
4862
/// Given a function block's `NodeId`, return its `FnDecl` , `None` otherwise.
4838
4863
fn get_parent_fn_decl ( & self , blk_id : ast:: NodeId ) -> Option < ( hir:: FnDecl , ast:: Ident ) > {
4839
4864
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> {
4842
4867
4843
4868
/// Given a function `Node`, return its `FnDecl` , `None` otherwise.
4844
4869
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| {
4849
4874
// This is less than ideal, it will not suggest a return type span on any
4850
4875
// method called `main`, regardless of whether it is actually the entry point,
4851
4876
// but it will still present it as the reason for the expected type.
4852
4877
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 ,
4872
4890
}
4873
4891
}
4874
4892
0 commit comments