3737
3838use  crate :: errors:: SuggestBoxingForReturnImplTrait ; 
3939use  crate :: FnCtxt ; 
40- use  rustc_errors:: { codes:: * ,  struct_span_code_err,  Applicability ,  Diag ,   MultiSpan } ; 
40+ use  rustc_errors:: { codes:: * ,  struct_span_code_err,  Applicability ,  Diag } ; 
4141use  rustc_hir as  hir; 
4242use  rustc_hir:: def_id:: { DefId ,  LocalDefId } ; 
43- use  rustc_hir:: intravisit:: { self ,  Visitor } ; 
44- use  rustc_hir:: Expr ; 
4543use  rustc_hir_analysis:: hir_ty_lowering:: HirTyLowerer ; 
4644use  rustc_infer:: infer:: type_variable:: TypeVariableOrigin ; 
4745use  rustc_infer:: infer:: { Coercion ,  DefineOpaqueTypes ,  InferOk ,  InferResult } ; 
@@ -95,22 +93,6 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
9593
9694type  CoerceResult < ' tcx >  = InferResult < ' tcx ,  ( Vec < Adjustment < ' tcx > > ,  Ty < ' tcx > ) > ; 
9795
98- struct  CollectRetsVisitor < ' tcx >  { 
99-     ret_exprs :  Vec < & ' tcx  hir:: Expr < ' tcx > > , 
100- } 
101- 
102- impl < ' tcx >  Visitor < ' tcx >  for  CollectRetsVisitor < ' tcx >  { 
103-     fn  visit_expr ( & mut  self ,  expr :  & ' tcx  Expr < ' tcx > )  { 
104-         match  expr. kind  { 
105-             hir:: ExprKind :: Ret ( _)  => self . ret_exprs . push ( expr) , 
106-             // `return` in closures does not return from the outer function 
107-             hir:: ExprKind :: Closure ( _)  => return , 
108-             _ => { } 
109-         } 
110-         intravisit:: walk_expr ( self ,  expr) ; 
111-     } 
112- } 
113- 
11496/// Coercing a mutable reference to an immutable works, while 
11597/// coercing `&T` to `&mut T` should be forbidden. 
11698fn  coerce_mutbls < ' tcx > ( 
@@ -1601,7 +1583,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
16011583
16021584                let  mut  err; 
16031585                let  mut  unsized_return = false ; 
1604-                 let  mut  visitor = CollectRetsVisitor  {  ret_exprs :  vec ! [ ]  } ; 
16051586                match  * cause. code ( )  { 
16061587                    ObligationCauseCode :: ReturnNoExpression  => { 
16071588                        err = struct_span_code_err ! ( 
@@ -1636,11 +1617,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
16361617                        if  !fcx. tcx . features ( ) . unsized_locals  { 
16371618                            unsized_return = self . is_return_ty_definitely_unsized ( fcx) ; 
16381619                        } 
1639-                         if  let  Some ( expression)  = expression
1640-                             && let  hir:: ExprKind :: Loop ( loop_blk,  ..)  = expression. kind 
1641-                         { 
1642-                             intravisit:: walk_block ( & mut  visitor,  loop_blk) ; 
1643-                         } 
16441620                    } 
16451621                    ObligationCauseCode :: ReturnValue ( id)  => { 
16461622                        err = self . report_return_mismatched_types ( 
@@ -1741,6 +1717,22 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17411717                augment_error ( & mut  err) ; 
17421718
17431719                if  let  Some ( expr)  = expression { 
1720+                     if  let  hir:: ExprKind :: Loop ( 
1721+                         _, 
1722+                         _, 
1723+                         loop_src @ ( hir:: LoopSource :: While  | hir:: LoopSource :: ForLoop ) , 
1724+                         _, 
1725+                     )  = expr. kind 
1726+                     { 
1727+                         let  loop_type = if  loop_src == hir:: LoopSource :: While  { 
1728+                             "`while` loops" 
1729+                         }  else  { 
1730+                             "`for` loops" 
1731+                         } ; 
1732+ 
1733+                         err. note ( format ! ( "{loop_type} evaluate to unit type `()`" ) ) ; 
1734+                     } 
1735+ 
17441736                    fcx. emit_coerce_suggestions ( 
17451737                        & mut  err, 
17461738                        expr, 
@@ -1749,15 +1741,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17491741                        None , 
17501742                        Some ( coercion_error) , 
17511743                    ) ; 
1752-                     if  visitor. ret_exprs . len ( )  > 0  { 
1753-                         self . note_unreachable_loop_return ( 
1754-                             & mut  err, 
1755-                             fcx. tcx , 
1756-                             & expr, 
1757-                             & visitor. ret_exprs , 
1758-                             expected, 
1759-                         ) ; 
1760-                     } 
17611744                } 
17621745
17631746                let  reported = err. emit_unless ( unsized_return) ; 
@@ -1831,110 +1814,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
18311814        ) ; 
18321815    } 
18331816
1834-     fn  note_unreachable_loop_return ( 
1835-         & self , 
1836-         err :  & mut  Diag < ' _ > , 
1837-         tcx :  TyCtxt < ' tcx > , 
1838-         expr :  & hir:: Expr < ' tcx > , 
1839-         ret_exprs :  & Vec < & ' tcx  hir:: Expr < ' tcx > > , 
1840-         ty :  Ty < ' tcx > , 
1841-     )  { 
1842-         let  hir:: ExprKind :: Loop ( _,  _,  _,  loop_span)  = expr. kind  else  { 
1843-             return ; 
1844-         } ; 
1845-         let  mut  span:  MultiSpan  = vec ! [ loop_span] . into ( ) ; 
1846-         span. push_span_label ( loop_span,  "this might have zero elements to iterate on" ) ; 
1847-         const  MAXITER :  usize  = 3 ; 
1848-         let  iter = ret_exprs. iter ( ) . take ( MAXITER ) ; 
1849-         for  ret_expr in  iter { 
1850-             span. push_span_label ( 
1851-                 ret_expr. span , 
1852-                 "if the loop doesn't execute, this value would never get returned" , 
1853-             ) ; 
1854-         } 
1855-         err. span_note ( 
1856-             span, 
1857-             "the function expects a value to always be returned, but loops might run zero times" , 
1858-         ) ; 
1859-         if  MAXITER  < ret_exprs. len ( )  { 
1860-             err. note ( format ! ( 
1861-                 "if the loop doesn't execute, {} other values would never get returned" , 
1862-                 ret_exprs. len( )  - MAXITER 
1863-             ) ) ; 
1864-         } 
1865-         let  hir = tcx. hir ( ) ; 
1866-         let  item = hir. get_parent_item ( expr. hir_id ) ; 
1867-         let  ret_msg = "return a value for the case when the loop has zero elements to iterate on" ; 
1868-         let  ret_ty_msg =
1869-             "otherwise consider changing the return type to account for that possibility" ; 
1870-         let  node = tcx. hir_node ( item. into ( ) ) ; 
1871-         if  let  Some ( body_id)  = node. body_id ( ) 
1872-             && let  Some ( sig)  = node. fn_sig ( ) 
1873-             && let  hir:: ExprKind :: Block ( block,  _)  = hir. body ( body_id) . value . kind 
1874-             && !ty. is_never ( ) 
1875-         { 
1876-             let  indentation = if  let  None  = block. expr 
1877-                 && let  [ ..,  last]  = & block. stmts 
1878-             { 
1879-                 tcx. sess . source_map ( ) . indentation_before ( last. span ) . unwrap_or_else ( String :: new) 
1880-             }  else  if  let  Some ( expr)  = block. expr  { 
1881-                 tcx. sess . source_map ( ) . indentation_before ( expr. span ) . unwrap_or_else ( String :: new) 
1882-             }  else  { 
1883-                 String :: new ( ) 
1884-             } ; 
1885-             if  let  None  = block. expr 
1886-                 && let  [ ..,  last]  = & block. stmts 
1887-             { 
1888-                 err. span_suggestion_verbose ( 
1889-                     last. span . shrink_to_hi ( ) , 
1890-                     ret_msg, 
1891-                     format ! ( "\n {indentation}/* `{ty}` value */" ) , 
1892-                     Applicability :: MaybeIncorrect , 
1893-                 ) ; 
1894-             }  else  if  let  Some ( expr)  = block. expr  { 
1895-                 err. span_suggestion_verbose ( 
1896-                     expr. span . shrink_to_hi ( ) , 
1897-                     ret_msg, 
1898-                     format ! ( "\n {indentation}/* `{ty}` value */" ) , 
1899-                     Applicability :: MaybeIncorrect , 
1900-                 ) ; 
1901-             } 
1902-             let  mut  sugg = match  sig. decl . output  { 
1903-                 hir:: FnRetTy :: DefaultReturn ( span)  => { 
1904-                     vec ! [ ( span,  " -> Option<()>" . to_string( ) ) ] 
1905-                 } 
1906-                 hir:: FnRetTy :: Return ( ty)  => { 
1907-                     vec ! [ 
1908-                         ( ty. span. shrink_to_lo( ) ,  "Option<" . to_string( ) ) , 
1909-                         ( ty. span. shrink_to_hi( ) ,  ">" . to_string( ) ) , 
1910-                     ] 
1911-                 } 
1912-             } ; 
1913-             for  ret_expr in  ret_exprs { 
1914-                 match  ret_expr. kind  { 
1915-                     hir:: ExprKind :: Ret ( Some ( expr) )  => { 
1916-                         sugg. push ( ( expr. span . shrink_to_lo ( ) ,  "Some(" . to_string ( ) ) ) ; 
1917-                         sugg. push ( ( expr. span . shrink_to_hi ( ) ,  ")" . to_string ( ) ) ) ; 
1918-                     } 
1919-                     hir:: ExprKind :: Ret ( None )  => { 
1920-                         sugg. push ( ( ret_expr. span . shrink_to_hi ( ) ,  " Some(())" . to_string ( ) ) ) ; 
1921-                     } 
1922-                     _ => { } 
1923-                 } 
1924-             } 
1925-             if  let  None  = block. expr 
1926-                 && let  [ ..,  last]  = & block. stmts 
1927-             { 
1928-                 sugg. push ( ( last. span . shrink_to_hi ( ) ,  format ! ( "\n {indentation}None" ) ) ) ; 
1929-             }  else  if  let  Some ( expr)  = block. expr  { 
1930-                 sugg. push ( ( expr. span . shrink_to_hi ( ) ,  format ! ( "\n {indentation}None" ) ) ) ; 
1931-             } 
1932-             err. multipart_suggestion ( ret_ty_msg,  sugg,  Applicability :: MaybeIncorrect ) ; 
1933-         }  else  { 
1934-             err. help ( format ! ( "{ret_msg}, {ret_ty_msg}" ) ) ; 
1935-         } 
1936-     } 
1937- 
19381817    fn  report_return_mismatched_types < ' a > ( 
19391818        & self , 
19401819        cause :  & ObligationCause < ' tcx > , 
0 commit comments