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 } ;
@@ -93,22 +91,6 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
9391
9492type CoerceResult < ' tcx > = InferResult < ' tcx , ( Vec < Adjustment < ' tcx > > , Ty < ' tcx > ) > ;
9593
96- struct CollectRetsVisitor < ' tcx > {
97- ret_exprs : Vec < & ' tcx hir:: Expr < ' tcx > > ,
98- }
99-
100- impl < ' tcx > Visitor < ' tcx > for CollectRetsVisitor < ' tcx > {
101- fn visit_expr ( & mut self , expr : & ' tcx Expr < ' tcx > ) {
102- match expr. kind {
103- hir:: ExprKind :: Ret ( _) => self . ret_exprs . push ( expr) ,
104- // `return` in closures does not return from the outer function
105- hir:: ExprKind :: Closure ( _) => return ,
106- _ => { }
107- }
108- intravisit:: walk_expr ( self , expr) ;
109- }
110- }
111-
11294/// Coercing a mutable reference to an immutable works, while
11395/// coercing `&T` to `&mut T` should be forbidden.
11496fn coerce_mutbls < ' tcx > (
@@ -1597,7 +1579,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
15971579
15981580 let mut err;
15991581 let mut unsized_return = false ;
1600- let mut visitor = CollectRetsVisitor { ret_exprs : vec ! [ ] } ;
16011582 match * cause. code ( ) {
16021583 ObligationCauseCode :: ReturnNoExpression => {
16031584 err = struct_span_code_err ! (
@@ -1632,11 +1613,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
16321613 if !fcx. tcx . features ( ) . unsized_locals {
16331614 unsized_return = self . is_return_ty_definitely_unsized ( fcx) ;
16341615 }
1635- if let Some ( expression) = expression
1636- && let hir:: ExprKind :: Loop ( loop_blk, ..) = expression. kind
1637- {
1638- intravisit:: walk_block ( & mut visitor, loop_blk) ;
1639- }
16401616 }
16411617 ObligationCauseCode :: ReturnValue ( id) => {
16421618 err = self . report_return_mismatched_types (
@@ -1737,6 +1713,22 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17371713 augment_error ( & mut err) ;
17381714
17391715 if let Some ( expr) = expression {
1716+ if let hir:: ExprKind :: Loop (
1717+ _,
1718+ _,
1719+ loop_src @ ( hir:: LoopSource :: While | hir:: LoopSource :: ForLoop ) ,
1720+ _,
1721+ ) = expr. kind
1722+ {
1723+ let loop_type = if loop_src == hir:: LoopSource :: While {
1724+ "`while` loops"
1725+ } else {
1726+ "`for` loops"
1727+ } ;
1728+
1729+ err. note ( format ! ( "{loop_type} evaluate to unit type `()`" ) ) ;
1730+ }
1731+
17401732 fcx. emit_coerce_suggestions (
17411733 & mut err,
17421734 expr,
@@ -1745,15 +1737,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17451737 None ,
17461738 Some ( coercion_error) ,
17471739 ) ;
1748- if visitor. ret_exprs . len ( ) > 0 {
1749- self . note_unreachable_loop_return (
1750- & mut err,
1751- fcx. tcx ,
1752- & expr,
1753- & visitor. ret_exprs ,
1754- expected,
1755- ) ;
1756- }
17571740 }
17581741
17591742 let reported = err. emit_unless ( unsized_return) ;
@@ -1827,110 +1810,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
18271810 ) ;
18281811 }
18291812
1830- fn note_unreachable_loop_return (
1831- & self ,
1832- err : & mut Diag < ' _ > ,
1833- tcx : TyCtxt < ' tcx > ,
1834- expr : & hir:: Expr < ' tcx > ,
1835- ret_exprs : & Vec < & ' tcx hir:: Expr < ' tcx > > ,
1836- ty : Ty < ' tcx > ,
1837- ) {
1838- let hir:: ExprKind :: Loop ( _, _, _, loop_span) = expr. kind else {
1839- return ;
1840- } ;
1841- let mut span: MultiSpan = vec ! [ loop_span] . into ( ) ;
1842- span. push_span_label ( loop_span, "this might have zero elements to iterate on" ) ;
1843- const MAXITER : usize = 3 ;
1844- let iter = ret_exprs. iter ( ) . take ( MAXITER ) ;
1845- for ret_expr in iter {
1846- span. push_span_label (
1847- ret_expr. span ,
1848- "if the loop doesn't execute, this value would never get returned" ,
1849- ) ;
1850- }
1851- err. span_note (
1852- span,
1853- "the function expects a value to always be returned, but loops might run zero times" ,
1854- ) ;
1855- if MAXITER < ret_exprs. len ( ) {
1856- err. note ( format ! (
1857- "if the loop doesn't execute, {} other values would never get returned" ,
1858- ret_exprs. len( ) - MAXITER
1859- ) ) ;
1860- }
1861- let hir = tcx. hir ( ) ;
1862- let item = hir. get_parent_item ( expr. hir_id ) ;
1863- let ret_msg = "return a value for the case when the loop has zero elements to iterate on" ;
1864- let ret_ty_msg =
1865- "otherwise consider changing the return type to account for that possibility" ;
1866- let node = tcx. hir_node ( item. into ( ) ) ;
1867- if let Some ( body_id) = node. body_id ( )
1868- && let Some ( sig) = node. fn_sig ( )
1869- && let hir:: ExprKind :: Block ( block, _) = hir. body ( body_id) . value . kind
1870- && !ty. is_never ( )
1871- {
1872- let indentation = if let None = block. expr
1873- && let [ .., last] = & block. stmts
1874- {
1875- tcx. sess . source_map ( ) . indentation_before ( last. span ) . unwrap_or_else ( String :: new)
1876- } else if let Some ( expr) = block. expr {
1877- tcx. sess . source_map ( ) . indentation_before ( expr. span ) . unwrap_or_else ( String :: new)
1878- } else {
1879- String :: new ( )
1880- } ;
1881- if let None = block. expr
1882- && let [ .., last] = & block. stmts
1883- {
1884- err. span_suggestion_verbose (
1885- last. span . shrink_to_hi ( ) ,
1886- ret_msg,
1887- format ! ( "\n {indentation}/* `{ty}` value */" ) ,
1888- Applicability :: MaybeIncorrect ,
1889- ) ;
1890- } else if let Some ( expr) = block. expr {
1891- err. span_suggestion_verbose (
1892- expr. span . shrink_to_hi ( ) ,
1893- ret_msg,
1894- format ! ( "\n {indentation}/* `{ty}` value */" ) ,
1895- Applicability :: MaybeIncorrect ,
1896- ) ;
1897- }
1898- let mut sugg = match sig. decl . output {
1899- hir:: FnRetTy :: DefaultReturn ( span) => {
1900- vec ! [ ( span, " -> Option<()>" . to_string( ) ) ]
1901- }
1902- hir:: FnRetTy :: Return ( ty) => {
1903- vec ! [
1904- ( ty. span. shrink_to_lo( ) , "Option<" . to_string( ) ) ,
1905- ( ty. span. shrink_to_hi( ) , ">" . to_string( ) ) ,
1906- ]
1907- }
1908- } ;
1909- for ret_expr in ret_exprs {
1910- match ret_expr. kind {
1911- hir:: ExprKind :: Ret ( Some ( expr) ) => {
1912- sugg. push ( ( expr. span . shrink_to_lo ( ) , "Some(" . to_string ( ) ) ) ;
1913- sugg. push ( ( expr. span . shrink_to_hi ( ) , ")" . to_string ( ) ) ) ;
1914- }
1915- hir:: ExprKind :: Ret ( None ) => {
1916- sugg. push ( ( ret_expr. span . shrink_to_hi ( ) , " Some(())" . to_string ( ) ) ) ;
1917- }
1918- _ => { }
1919- }
1920- }
1921- if let None = block. expr
1922- && let [ .., last] = & block. stmts
1923- {
1924- sugg. push ( ( last. span . shrink_to_hi ( ) , format ! ( "\n {indentation}None" ) ) ) ;
1925- } else if let Some ( expr) = block. expr {
1926- sugg. push ( ( expr. span . shrink_to_hi ( ) , format ! ( "\n {indentation}None" ) ) ) ;
1927- }
1928- err. multipart_suggestion ( ret_ty_msg, sugg, Applicability :: MaybeIncorrect ) ;
1929- } else {
1930- err. help ( format ! ( "{ret_msg}, {ret_ty_msg}" ) ) ;
1931- }
1932- }
1933-
19341813 fn report_return_mismatched_types < ' a > (
19351814 & self ,
19361815 cause : & ObligationCause < ' tcx > ,
0 commit comments