@@ -78,39 +78,38 @@ fn contains_yield_statement(body: &[ast::Stmt]) -> bool {
7878
7979/// PLR1708
8080pub ( crate ) fn stop_iteration_return ( checker : & Checker , raise_stmt : & ast:: StmtRaise ) {
81- // Check if we're in a generator function (function that contains yield statements)
82- let mut in_generator_function = false ;
83- for scope in checker. semantic ( ) . current_scopes ( ) {
84- if let ruff_python_semantic:: ScopeKind :: Function ( function_def) = scope. kind {
85- // Check if this function contains any yield statements by traversing its body
86- if contains_yield_statement ( & function_def. body ) {
87- in_generator_function = true ;
88- break ;
89- }
81+ // Fast-path: only continue if this is `raise StopIteration` (with or without args)
82+ let Some ( exc) = & raise_stmt. exc else {
83+ return ;
84+ } ;
85+
86+ let is_stop_iteration = match exc. as_ref ( ) {
87+ ast:: Expr :: Call ( ast:: ExprCall { func, .. } ) => {
88+ checker. semantic ( ) . match_builtin_expr ( func, "StopIteration" )
9089 }
91- }
90+ expr => checker. semantic ( ) . match_builtin_expr ( expr, "StopIteration" ) ,
91+ } ;
9292
93- if !in_generator_function {
93+ if !is_stop_iteration {
9494 return ;
9595 }
9696
97- // Check if the raise statement is raising StopIteration
98- let Some ( exc ) = & raise_stmt . exc else {
97+ // Now check the (more expensive) generator context
98+ if ! in_generator_context ( checker ) {
9999 return ;
100- } ;
100+ }
101101
102- // Check if it's a StopIteration exception (could be with or without a value)
103- match exc. as_ref ( ) {
104- // `raise StopIteration(...)`
105- ast:: Expr :: Call ( ast:: ExprCall { func, .. } )
106- if checker. semantic ( ) . match_builtin_expr ( func, "StopIteration" ) =>
107- {
108- checker. report_diagnostic ( StopIterationReturn , raise_stmt. range ( ) ) ;
109- }
110- // `raise StopIteration`
111- expr if checker. semantic ( ) . match_builtin_expr ( expr, "StopIteration" ) => {
112- checker. report_diagnostic ( StopIterationReturn , raise_stmt. range ( ) ) ;
102+ checker. report_diagnostic ( StopIterationReturn , raise_stmt. range ( ) ) ;
103+ }
104+
105+ /// Returns true if we're inside a function that contains any `yield`/`yield from`.
106+ fn in_generator_context ( checker : & Checker ) -> bool {
107+ for scope in checker. semantic ( ) . current_scopes ( ) {
108+ if let ruff_python_semantic:: ScopeKind :: Function ( function_def) = scope. kind {
109+ if contains_yield_statement ( & function_def. body ) {
110+ return true ;
111+ }
113112 }
114- _ => { }
115113 }
114+ false
116115}
0 commit comments