(
&mut self,
name: &str,
init_collection: Option<AnyInstruction>,
generators: &[ast::Comprehension],
compile_element: &dyn Fn(&mut Self) -> CompileResult<()>,
| 8815 | } |
| 8816 | |
| 8817 | fn compile_comprehension( |
| 8818 | &mut self, |
| 8819 | name: &str, |
| 8820 | init_collection: Option<AnyInstruction>, |
| 8821 | generators: &[ast::Comprehension], |
| 8822 | compile_element: &dyn Fn(&mut Self) -> CompileResult<()>, |
| 8823 | comprehension_type: ComprehensionType, |
| 8824 | element_contains_await: bool, |
| 8825 | ) -> CompileResult<()> { |
| 8826 | let prev_ctx = self.ctx; |
| 8827 | let has_an_async_gen = generators.iter().any(|g| g.is_async); |
| 8828 | |
| 8829 | // Check for async comprehension outside async function (list/set/dict only, not generator expressions) |
| 8830 | // Use in_async_scope to allow nested async comprehensions inside an async function |
| 8831 | if comprehension_type != ComprehensionType::Generator |
| 8832 | && (has_an_async_gen || element_contains_await) |
| 8833 | && !prev_ctx.in_async_scope |
| 8834 | { |
| 8835 | return Err(self.error(CodegenErrorType::InvalidAsyncComprehension)); |
| 8836 | } |
| 8837 | |
| 8838 | // Check if this comprehension should be inlined (PEP 709) |
| 8839 | let is_inlined = self.is_inlined_comprehension_context(comprehension_type); |
| 8840 | |
| 8841 | // async comprehensions are allowed in various contexts: |
| 8842 | // - list/set/dict comprehensions in async functions (or nested within) |
| 8843 | // - always for generator expressions |
| 8844 | let is_async_list_set_dict_comprehension = comprehension_type |
| 8845 | != ComprehensionType::Generator |
| 8846 | && (has_an_async_gen || element_contains_await) |
| 8847 | && prev_ctx.in_async_scope; |
| 8848 | |
| 8849 | let is_async_generator_comprehension = comprehension_type == ComprehensionType::Generator |
| 8850 | && (has_an_async_gen || element_contains_await); |
| 8851 | |
| 8852 | debug_assert!(!(is_async_list_set_dict_comprehension && is_async_generator_comprehension)); |
| 8853 | |
| 8854 | let is_async = is_async_list_set_dict_comprehension || is_async_generator_comprehension; |
| 8855 | |
| 8856 | // We must have at least one generator: |
| 8857 | assert!(!generators.is_empty()); |
| 8858 | |
| 8859 | if is_inlined && !has_an_async_gen && !element_contains_await { |
| 8860 | // PEP 709: Inlined comprehension - compile inline without new scope |
| 8861 | let was_in_inlined_comp = self.current_code_info().in_inlined_comp; |
| 8862 | self.current_code_info().in_inlined_comp = true; |
| 8863 | let result = self.compile_inlined_comprehension( |
| 8864 | init_collection, |
| 8865 | generators, |
| 8866 | compile_element, |
| 8867 | has_an_async_gen, |
| 8868 | ); |
| 8869 | self.current_code_info().in_inlined_comp = was_in_inlined_comp; |
| 8870 | return result; |
| 8871 | } |
| 8872 | |
| 8873 | // Non-inlined path: create a new code object (generator expressions, etc.) |
| 8874 | self.ctx = CompileContext { |
no test coverage detected