(
&mut self,
scope_name: &str,
elt1: &ast::Expr,
elt2: Option<&ast::Expr>,
generators: &[ast::Comprehension],
range: TextRange,
is_generator: bo
| 2138 | } |
| 2139 | |
| 2140 | fn scan_comprehension( |
| 2141 | &mut self, |
| 2142 | scope_name: &str, |
| 2143 | elt1: &ast::Expr, |
| 2144 | elt2: Option<&ast::Expr>, |
| 2145 | generators: &[ast::Comprehension], |
| 2146 | range: TextRange, |
| 2147 | is_generator: bool, |
| 2148 | ) -> SymbolTableResult { |
| 2149 | // Check for async comprehension outside async function |
| 2150 | // (list/set/dict comprehensions only, not generator expressions) |
| 2151 | let has_async_gen = generators.iter().any(|g| g.is_async); |
| 2152 | if has_async_gen && !is_generator && !self.is_in_async_context() { |
| 2153 | return Err(SymbolTableError { |
| 2154 | error: "asynchronous comprehension outside of an asynchronous function".to_owned(), |
| 2155 | location: Some( |
| 2156 | self.source_file |
| 2157 | .to_source_code() |
| 2158 | .source_location(range.start(), PositionEncoding::Utf8), |
| 2159 | ), |
| 2160 | }); |
| 2161 | } |
| 2162 | |
| 2163 | // Comprehensions are compiled as functions, so create a scope for them: |
| 2164 | self.enter_scope( |
| 2165 | scope_name, |
| 2166 | CompilerScope::Comprehension, |
| 2167 | self.line_index_start(range), |
| 2168 | ); |
| 2169 | // Generator expressions need the is_generator flag |
| 2170 | self.tables.last_mut().unwrap().is_generator = is_generator; |
| 2171 | |
| 2172 | // PEP 709: Mark non-generator comprehensions for inlining. |
| 2173 | // Only in function-like scopes for now. Module/class scope inlining |
| 2174 | // needs more work (Cell name resolution, __class__ handling). |
| 2175 | // Also excluded: generator expressions, async comprehensions, |
| 2176 | // and annotation scopes nested in classes (can_see_class_scope). |
| 2177 | let element_has_await = expr_contains_await(elt1) || elt2.is_some_and(expr_contains_await); |
| 2178 | if !is_generator && !has_async_gen && !element_has_await { |
| 2179 | let parent = self.tables.iter().rev().nth(1); |
| 2180 | let parent_can_see_class = parent.is_some_and(|t| t.can_see_class_scope); |
| 2181 | let parent_is_func = parent.is_some_and(|t| { |
| 2182 | matches!( |
| 2183 | t.typ, |
| 2184 | CompilerScope::Function |
| 2185 | | CompilerScope::AsyncFunction |
| 2186 | | CompilerScope::Lambda |
| 2187 | | CompilerScope::Comprehension |
| 2188 | ) |
| 2189 | }); |
| 2190 | if !parent_can_see_class && parent_is_func { |
| 2191 | self.tables.last_mut().unwrap().comp_inlined = true; |
| 2192 | } |
| 2193 | } |
| 2194 | |
| 2195 | // Register the passed argument to the generator function as the name ".0" |
| 2196 | self.register_name(".0", SymbolUsage::Parameter, range)?; |
| 2197 |
no test coverage detected