@@ -7,10 +7,12 @@ use core::ops::ControlFlow;
77use rustc_errors:: Applicability ;
88use rustc_hir:: intravisit:: FnKind ;
99use rustc_hir:: {
10- Block , Body , Expr , ExprKind , FnDecl , ItemKind , LangItem , MatchSource , OwnerNode , PatKind , QPath , Stmt , StmtKind ,
10+ Block , Body , Expr , ExprKind , FnDecl , HirId , ItemKind , LangItem , MatchSource , Node , OwnerNode , PatKind , QPath , Stmt ,
11+ StmtKind ,
1112} ;
1213use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
1314use rustc_middle:: lint:: in_external_macro;
15+ use rustc_middle:: ty:: adjustment:: Adjust ;
1416use rustc_middle:: ty:: { self , GenericArgKind , Ty } ;
1517use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
1618use rustc_span:: def_id:: LocalDefId ;
@@ -158,6 +160,22 @@ impl<'tcx> ToString for RetReplacement<'tcx> {
158160
159161declare_lint_pass ! ( Return => [ LET_AND_RETURN , NEEDLESS_RETURN , NEEDLESS_RETURN_WITH_QUESTION_MARK ] ) ;
160162
163+ /// Checks if a return statement is "needed" in the middle of a block, or if it can be removed. This
164+ /// is the case when the enclosing block expression is coerced to some other type, which only works
165+ /// because of the never-ness of `return` expressions
166+ fn stmt_needs_never_type ( cx : & LateContext < ' _ > , stmt_hir_id : HirId ) -> bool {
167+ cx. tcx
168+ . hir ( )
169+ . parent_iter ( stmt_hir_id)
170+ . find_map ( |( _, node) | if let Node :: Expr ( expr) = node { Some ( expr) } else { None } )
171+ . is_some_and ( |e| {
172+ cx. typeck_results ( )
173+ . expr_adjustments ( e)
174+ . iter ( )
175+ . any ( |adjust| adjust. target != cx. tcx . types . unit && matches ! ( adjust. kind, Adjust :: NeverToAny ) )
176+ } )
177+ }
178+
161179impl < ' tcx > LateLintPass < ' tcx > for Return {
162180 fn check_stmt ( & mut self , cx : & LateContext < ' tcx > , stmt : & ' tcx Stmt < ' _ > ) {
163181 if !in_external_macro ( cx. sess ( ) , stmt. span )
@@ -173,6 +191,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
173191 && let [ .., final_stmt] = block. stmts
174192 && final_stmt. hir_id != stmt. hir_id
175193 && !is_from_proc_macro ( cx, expr)
194+ && !stmt_needs_never_type ( cx, stmt. hir_id )
176195 {
177196 span_lint_and_sugg (
178197 cx,
0 commit comments