37
37
38
38
use crate :: errors:: SuggestBoxingForReturnImplTrait ;
39
39
use crate :: FnCtxt ;
40
- use rustc_errors:: { codes:: * , struct_span_code_err, Applicability , Diag , MultiSpan } ;
40
+ use rustc_errors:: { codes:: * , struct_span_code_err, Diag } ;
41
41
use rustc_hir as hir;
42
42
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
43
- use rustc_hir:: intravisit:: { self , Visitor } ;
44
- use rustc_hir:: Expr ;
45
43
use rustc_hir_analysis:: hir_ty_lowering:: HirTyLowerer ;
46
44
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
47
45
use rustc_infer:: infer:: { Coercion , DefineOpaqueTypes , InferOk , InferResult } ;
@@ -56,7 +54,7 @@ use rustc_middle::ty::adjustment::{
56
54
use rustc_middle:: ty:: error:: TypeError ;
57
55
use rustc_middle:: ty:: relate:: RelateResult ;
58
56
use rustc_middle:: ty:: visit:: TypeVisitableExt ;
59
- use rustc_middle:: ty:: { self , GenericArgsRef , Ty , TyCtxt } ;
57
+ use rustc_middle:: ty:: { self , GenericArgsRef , Ty } ;
60
58
use rustc_session:: parse:: feature_err;
61
59
use rustc_span:: symbol:: sym;
62
60
use rustc_span:: DesugaringKind ;
@@ -95,22 +93,6 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
95
93
96
94
type CoerceResult < ' tcx > = InferResult < ' tcx , ( Vec < Adjustment < ' tcx > > , Ty < ' tcx > ) > ;
97
95
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
-
114
96
/// Coercing a mutable reference to an immutable works, while
115
97
/// coercing `&T` to `&mut T` should be forbidden.
116
98
fn coerce_mutbls < ' tcx > (
@@ -1593,7 +1575,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
1593
1575
1594
1576
let mut err;
1595
1577
let mut unsized_return = false ;
1596
- let mut visitor = CollectRetsVisitor { ret_exprs : vec ! [ ] } ;
1597
1578
match * cause. code ( ) {
1598
1579
ObligationCauseCode :: ReturnNoExpression => {
1599
1580
err = struct_span_code_err ! (
@@ -1619,11 +1600,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
1619
1600
if !fcx. tcx . features ( ) . unsized_locals {
1620
1601
unsized_return = self . is_return_ty_definitely_unsized ( fcx) ;
1621
1602
}
1622
- if let Some ( expression) = expression
1623
- && let hir:: ExprKind :: Loop ( loop_blk, ..) = expression. kind
1624
- {
1625
- intravisit:: walk_block ( & mut visitor, loop_blk) ;
1626
- }
1627
1603
}
1628
1604
ObligationCauseCode :: ReturnValue ( id) => {
1629
1605
err = self . report_return_mismatched_types (
@@ -1724,6 +1700,22 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
1724
1700
augment_error ( & mut err) ;
1725
1701
1726
1702
if let Some ( expr) = expression {
1703
+ if let hir:: ExprKind :: Loop (
1704
+ _,
1705
+ _,
1706
+ loop_src @ ( hir:: LoopSource :: While | hir:: LoopSource :: ForLoop ) ,
1707
+ _,
1708
+ ) = expr. kind
1709
+ {
1710
+ let loop_type = if loop_src == hir:: LoopSource :: While {
1711
+ "`while` loops"
1712
+ } else {
1713
+ "`for` loops"
1714
+ } ;
1715
+
1716
+ err. note ( format ! ( "{loop_type} evaluate to unit type `()`" ) ) ;
1717
+ }
1718
+
1727
1719
fcx. emit_coerce_suggestions (
1728
1720
& mut err,
1729
1721
expr,
@@ -1732,15 +1724,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
1732
1724
None ,
1733
1725
Some ( coercion_error) ,
1734
1726
) ;
1735
- if visitor. ret_exprs . len ( ) > 0 {
1736
- self . note_unreachable_loop_return (
1737
- & mut err,
1738
- fcx. tcx ,
1739
- & expr,
1740
- & visitor. ret_exprs ,
1741
- expected,
1742
- ) ;
1743
- }
1744
1727
}
1745
1728
1746
1729
let reported = err. emit_unless ( unsized_return) ;
@@ -1814,110 +1797,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
1814
1797
) ;
1815
1798
}
1816
1799
1817
- fn note_unreachable_loop_return (
1818
- & self ,
1819
- err : & mut Diag < ' _ > ,
1820
- tcx : TyCtxt < ' tcx > ,
1821
- expr : & hir:: Expr < ' tcx > ,
1822
- ret_exprs : & Vec < & ' tcx hir:: Expr < ' tcx > > ,
1823
- ty : Ty < ' tcx > ,
1824
- ) {
1825
- let hir:: ExprKind :: Loop ( _, _, _, loop_span) = expr. kind else {
1826
- return ;
1827
- } ;
1828
- let mut span: MultiSpan = vec ! [ loop_span] . into ( ) ;
1829
- span. push_span_label ( loop_span, "this might have zero elements to iterate on" ) ;
1830
- const MAXITER : usize = 3 ;
1831
- let iter = ret_exprs. iter ( ) . take ( MAXITER ) ;
1832
- for ret_expr in iter {
1833
- span. push_span_label (
1834
- ret_expr. span ,
1835
- "if the loop doesn't execute, this value would never get returned" ,
1836
- ) ;
1837
- }
1838
- err. span_note (
1839
- span,
1840
- "the function expects a value to always be returned, but loops might run zero times" ,
1841
- ) ;
1842
- if MAXITER < ret_exprs. len ( ) {
1843
- err. note ( format ! (
1844
- "if the loop doesn't execute, {} other values would never get returned" ,
1845
- ret_exprs. len( ) - MAXITER
1846
- ) ) ;
1847
- }
1848
- let hir = tcx. hir ( ) ;
1849
- let item = hir. get_parent_item ( expr. hir_id ) ;
1850
- let ret_msg = "return a value for the case when the loop has zero elements to iterate on" ;
1851
- let ret_ty_msg =
1852
- "otherwise consider changing the return type to account for that possibility" ;
1853
- let node = tcx. hir_node ( item. into ( ) ) ;
1854
- if let Some ( body_id) = node. body_id ( )
1855
- && let Some ( sig) = node. fn_sig ( )
1856
- && let hir:: ExprKind :: Block ( block, _) = hir. body ( body_id) . value . kind
1857
- && !ty. is_never ( )
1858
- {
1859
- let indentation = if let None = block. expr
1860
- && let [ .., last] = & block. stmts
1861
- {
1862
- tcx. sess . source_map ( ) . indentation_before ( last. span ) . unwrap_or_else ( String :: new)
1863
- } else if let Some ( expr) = block. expr {
1864
- tcx. sess . source_map ( ) . indentation_before ( expr. span ) . unwrap_or_else ( String :: new)
1865
- } else {
1866
- String :: new ( )
1867
- } ;
1868
- if let None = block. expr
1869
- && let [ .., last] = & block. stmts
1870
- {
1871
- err. span_suggestion_verbose (
1872
- last. span . shrink_to_hi ( ) ,
1873
- ret_msg,
1874
- format ! ( "\n {indentation}/* `{ty}` value */" ) ,
1875
- Applicability :: MaybeIncorrect ,
1876
- ) ;
1877
- } else if let Some ( expr) = block. expr {
1878
- err. span_suggestion_verbose (
1879
- expr. span . shrink_to_hi ( ) ,
1880
- ret_msg,
1881
- format ! ( "\n {indentation}/* `{ty}` value */" ) ,
1882
- Applicability :: MaybeIncorrect ,
1883
- ) ;
1884
- }
1885
- let mut sugg = match sig. decl . output {
1886
- hir:: FnRetTy :: DefaultReturn ( span) => {
1887
- vec ! [ ( span, " -> Option<()>" . to_string( ) ) ]
1888
- }
1889
- hir:: FnRetTy :: Return ( ty) => {
1890
- vec ! [
1891
- ( ty. span. shrink_to_lo( ) , "Option<" . to_string( ) ) ,
1892
- ( ty. span. shrink_to_hi( ) , ">" . to_string( ) ) ,
1893
- ]
1894
- }
1895
- } ;
1896
- for ret_expr in ret_exprs {
1897
- match ret_expr. kind {
1898
- hir:: ExprKind :: Ret ( Some ( expr) ) => {
1899
- sugg. push ( ( expr. span . shrink_to_lo ( ) , "Some(" . to_string ( ) ) ) ;
1900
- sugg. push ( ( expr. span . shrink_to_hi ( ) , ")" . to_string ( ) ) ) ;
1901
- }
1902
- hir:: ExprKind :: Ret ( None ) => {
1903
- sugg. push ( ( ret_expr. span . shrink_to_hi ( ) , " Some(())" . to_string ( ) ) ) ;
1904
- }
1905
- _ => { }
1906
- }
1907
- }
1908
- if let None = block. expr
1909
- && let [ .., last] = & block. stmts
1910
- {
1911
- sugg. push ( ( last. span . shrink_to_hi ( ) , format ! ( "\n {indentation}None" ) ) ) ;
1912
- } else if let Some ( expr) = block. expr {
1913
- sugg. push ( ( expr. span . shrink_to_hi ( ) , format ! ( "\n {indentation}None" ) ) ) ;
1914
- }
1915
- err. multipart_suggestion ( ret_ty_msg, sugg, Applicability :: MaybeIncorrect ) ;
1916
- } else {
1917
- err. help ( format ! ( "{ret_msg}, {ret_ty_msg}" ) ) ;
1918
- }
1919
- }
1920
-
1921
1800
fn report_return_mismatched_types < ' a > (
1922
1801
& self ,
1923
1802
cause : & ObligationCause < ' tcx > ,
0 commit comments