| 800 | } |
| 801 | |
| 802 | fn found_in_inner_scope( |
| 803 | &self, |
| 804 | sub_tables: &[SymbolTable], |
| 805 | name: &str, |
| 806 | st_typ: CompilerScope, |
| 807 | ) -> Option<SymbolScope> { |
| 808 | sub_tables.iter().find_map(|st| { |
| 809 | // PEP 709: For inlined comprehensions, check their children |
| 810 | // instead of the comp itself (its symbols are merged into parent). |
| 811 | if st.comp_inlined { |
| 812 | return self.found_in_inner_scope(&st.sub_tables, name, st_typ); |
| 813 | } |
| 814 | let sym = st.symbols.get(name)?; |
| 815 | if sym.scope == SymbolScope::Free || sym.flags.contains(SymbolFlags::FREE_CLASS) { |
| 816 | if st_typ == CompilerScope::Class && name != "__class__" { |
| 817 | None |
| 818 | } else { |
| 819 | Some(SymbolScope::Cell) |
| 820 | } |
| 821 | } else if sym.scope == SymbolScope::GlobalExplicit && self.tables.is_empty() { |
| 822 | // the symbol is defined on the module level, and an inner scope declares |
| 823 | // a global that points to it |
| 824 | Some(SymbolScope::GlobalExplicit) |
| 825 | } else { |
| 826 | None |
| 827 | } |
| 828 | }) |
| 829 | } |
| 830 | |
| 831 | // Implements the symbol analysis and scope extension for names |
| 832 | // assigned by a named expression in a comprehension. See: |