@@ -110,14 +110,6 @@ enum NameUsage {
110110 Store ,
111111 Delete ,
112112}
113-
114- fn is_forbidden_name ( name : & str ) -> bool {
115- // See https://docs.python.org/3/library/constants.html#built-in-constants
116- const BUILTIN_CONSTANTS : & [ & str ] = & [ "__debug__" ] ;
117-
118- BUILTIN_CONSTANTS . contains ( & name)
119- }
120-
121113//github.com/ Main structure holding the state of compilation.
122114struct Compiler {
123115 code_stack : Vec < ir:: CodeInfo > ,
@@ -130,10 +122,6 @@ struct Compiler {
130122 ctx : CompileContext ,
131123 opts : CompileOpts ,
132124 in_annotation : bool ,
133- // PEP 649: Track if we're inside a conditional block (if/for/while/etc.)
134- in_conditional_block : bool ,
135- // PEP 649: Next index for conditional annotation tracking
136- next_conditional_annotation_index : u32 ,
137125}
138126
139127enum DoneWithFuture {
@@ -424,6 +412,8 @@ impl Compiler {
424412 in_inlined_comp : false ,
425413 fblock : Vec :: with_capacity ( MAXBLOCKS ) ,
426414 symbol_table_index : 0 , // Module is always the first symbol table
415+ in_conditional_block : 0 ,
416+ next_conditional_annotation_index : 0 ,
427417 } ;
428418 Self {
429419 code_stack : vec ! [ module_code] ,
@@ -441,8 +431,6 @@ impl Compiler {
441431 } ,
442432 opts,
443433 in_annotation : false ,
444- in_conditional_block : false ,
445- next_conditional_annotation_index : 0 ,
446434 }
447435 }
448436
@@ -1045,6 +1033,8 @@ impl Compiler {
10451033 in_inlined_comp : false ,
10461034 fblock : Vec :: with_capacity ( MAXBLOCKS ) ,
10471035 symbol_table_index : key,
1036+ in_conditional_block : 0 ,
1037+ next_conditional_annotation_index : 0 ,
10481038 } ;
10491039
10501040 // Push the old compiler unit on the stack (like PyCapsule)
@@ -1525,11 +1515,7 @@ impl Compiler {
15251515 self . _name_inner ( name, |i| & mut i. metadata . names )
15261516 }
15271517 fn varname ( & mut self , name : & str ) -> CompileResult < bytecode:: NameIdx > {
1528- if Self :: is_forbidden_arg_name ( name) {
1529- return Err ( self . error ( CodegenErrorType :: SyntaxError ( format ! (
1530- "cannot assign to {name}" ,
1531- ) ) ) ) ;
1532- }
1518+ // Note: __debug__ checks are now handled in symboltable phase
15331519 Ok ( self . _name_inner ( name, |i| & mut i. metadata . varnames ) )
15341520 }
15351521 fn _name_inner (
@@ -1814,15 +1800,6 @@ impl Compiler {
18141800 symboltable:: mangle_name ( private, name)
18151801 }
18161802
1817- fn check_forbidden_name ( & mut self , name : & str , usage : NameUsage ) -> CompileResult < ( ) > {
1818- let msg = match usage {
1819- NameUsage :: Store if is_forbidden_name ( name) => "cannot assign to" ,
1820- NameUsage :: Delete if is_forbidden_name ( name) => "cannot delete" ,
1821- _ => return Ok ( ( ) ) ,
1822- } ;
1823- Err ( self . error ( CodegenErrorType :: SyntaxError ( format ! ( "{msg} {name}" ) ) ) )
1824- }
1825-
18261803 // = compiler_nameop
18271804 fn compile_name ( & mut self , name : & str , usage : NameUsage ) -> CompileResult < ( ) > {
18281805 enum NameOp {
@@ -1834,7 +1811,6 @@ impl Compiler {
18341811 }
18351812
18361813 let name = self . mangle ( name) ;
1837- self . check_forbidden_name ( & name, usage) ?;
18381814
18391815 // Special handling for __debug__
18401816 if NameUsage :: Load == usage && name == "__debug__" {
@@ -2135,6 +2111,7 @@ impl Compiler {
21352111 elif_else_clauses,
21362112 ..
21372113 } ) => {
2114+ self . enter_conditional_block ( ) ;
21382115 match elif_else_clauses. as_slice ( ) {
21392116 // Only if
21402117 [ ] => {
@@ -2182,6 +2159,7 @@ impl Compiler {
21822159 self . switch_to_block ( after_block) ;
21832160 }
21842161 }
2162+ self . leave_conditional_block ( ) ;
21852163 }
21862164 Stmt :: While ( StmtWhile {
21872165 test, body, orelse, ..
@@ -2228,11 +2206,13 @@ impl Compiler {
22282206 is_star,
22292207 ..
22302208 } ) => {
2209+ self . enter_conditional_block ( ) ;
22312210 if * is_star {
22322211 self . compile_try_star_except ( body, handlers, orelse, finalbody) ?
22332212 } else {
22342213 self . compile_try_statement ( body, handlers, orelse, finalbody) ?
22352214 }
2215+ self . leave_conditional_block ( ) ;
22362216 }
22372217 Stmt :: FunctionDef ( StmtFunctionDef {
22382218 name,
@@ -2432,7 +2412,6 @@ impl Compiler {
24322412 match & expression {
24332413 Expr :: Name ( ExprName { id, .. } ) => self . compile_name ( id. as_str ( ) , NameUsage :: Delete ) ?,
24342414 Expr :: Attribute ( ExprAttribute { value, attr, .. } ) => {
2435- self . check_forbidden_name ( attr. as_str ( ) , NameUsage :: Delete ) ?;
24362415 self . compile_expression ( value) ?;
24372416 let idx = self . name ( attr. as_str ( ) ) ;
24382417 emit ! ( self , Instruction :: DeleteAttr { idx } ) ;
@@ -3451,10 +3430,6 @@ impl Compiler {
34513430 Ok ( ( ) )
34523431 }
34533432
3454- fn is_forbidden_arg_name ( name : & str ) -> bool {
3455- is_forbidden_name ( name)
3456- }
3457-
34583433 //github.com/ Compile default arguments
34593434 // = compiler_default_arguments
34603435 fn compile_default_arguments (
@@ -4485,6 +4460,8 @@ impl Compiler {
44854460 }
44864461
44874462 fn compile_while ( & mut self , test : & Expr , body : & [ Stmt ] , orelse : & [ Stmt ] ) -> CompileResult < ( ) > {
4463+ self . enter_conditional_block ( ) ;
4464+
44884465 let while_block = self . new_block ( ) ;
44894466 let else_block = self . new_block ( ) ;
44904467 let after_block = self . new_block ( ) ;
@@ -4513,6 +4490,8 @@ impl Compiler {
45134490 // Note: PopBlock is no longer emitted for loops
45144491 self . compile_statements ( orelse) ?;
45154492 self . switch_to_block ( after_block) ;
4493+
4494+ self . leave_conditional_block ( ) ;
45164495 Ok ( ( ) )
45174496 }
45184497
@@ -4522,6 +4501,8 @@ impl Compiler {
45224501 body : & [ Stmt ] ,
45234502 is_async : bool ,
45244503 ) -> CompileResult < ( ) > {
4504+ self . enter_conditional_block ( ) ;
4505+
45254506 // Python 3.12+ style with statement:
45264507 //
45274508 // BEFORE_WITH # TOS: ctx_mgr -> [__exit__, __enter__ result]
@@ -4734,6 +4715,7 @@ impl Compiler {
47344715 // ===== After block =====
47354716 self . switch_to_block ( after_block) ;
47364717
4718+ self . leave_conditional_block ( ) ;
47374719 Ok ( ( ) )
47384720 }
47394721
@@ -4745,6 +4727,8 @@ impl Compiler {
47454727 orelse : & [ Stmt ] ,
47464728 is_async : bool ,
47474729 ) -> CompileResult < ( ) > {
4730+ self . enter_conditional_block ( ) ;
4731+
47484732 // Start loop
47494733 let for_block = self . new_block ( ) ;
47504734 let else_block = self . new_block ( ) ;
@@ -4812,6 +4796,7 @@ impl Compiler {
48124796
48134797 self . switch_to_block ( after_block) ;
48144798
4799+ self . leave_conditional_block ( ) ;
48154800 Ok ( ( ) )
48164801 }
48174802
@@ -5784,8 +5769,10 @@ impl Compiler {
57845769 }
57855770
57865771 fn compile_match ( & mut self , subject : & Expr , cases : & [ MatchCase ] ) -> CompileResult < ( ) > {
5772+ self . enter_conditional_block ( ) ;
57875773 let mut pattern_context = PatternContext :: new ( ) ;
57885774 self . compile_match_inner ( subject, cases, & mut pattern_context) ?;
5775+ self . leave_conditional_block ( ) ;
57895776 Ok ( ( ) )
57905777 }
57915778
@@ -5946,16 +5933,22 @@ impl Compiler {
59465933 } else {
59475934 // PEP 649: Handle conditional annotations
59485935 if self . current_symbol_table ( ) . has_conditional_annotations {
5949- // Determine if this annotation is conditional
5950- let is_module = self . current_symbol_table ( ) . typ == CompilerScope :: Module ;
5951- let is_conditional = is_module || self . in_conditional_block ;
5936+ // Allocate an index for every annotation when has_conditional_annotations
5937+ // This keeps indices aligned with compile_module_annotate's enumeration
5938+ let code_info = self . current_code_info ( ) ;
5939+ let annotation_index = code_info. next_conditional_annotation_index ;
5940+ code_info. next_conditional_annotation_index += 1 ;
59525941
5942+ // Determine if this annotation is conditional
5943+ // Module and Class scopes both need all annotations tracked
5944+ let scope_type = self . current_symbol_table ( ) . typ ;
5945+ let in_conditional_block = self . current_code_info ( ) . in_conditional_block > 0 ;
5946+ let is_conditional =
5947+ matches ! ( scope_type, CompilerScope :: Module | CompilerScope :: Class )
5948+ || in_conditional_block;
5949+
5950+ // Only add to __conditional_annotations__ set if actually conditional
59535951 if is_conditional {
5954- // Get the current annotation index and increment
5955- let annotation_index = self . next_conditional_annotation_index ;
5956- self . next_conditional_annotation_index += 1 ;
5957-
5958- // Add index to __conditional_annotations__ set
59595952 let cond_annotations_name = self . name ( "__conditional_annotations__" ) ;
59605953 emit ! ( self , Instruction :: LoadName ( cond_annotations_name) ) ;
59615954 self . emit_load_const ( ConstantData :: Integer {
@@ -5980,7 +5973,6 @@ impl Compiler {
59805973 self . compile_subscript ( value, slice, * ctx) ?;
59815974 }
59825975 Expr :: Attribute ( ExprAttribute { value, attr, .. } ) => {
5983- self . check_forbidden_name ( attr. as_str ( ) , NameUsage :: Store ) ?;
59845976 self . compile_expression ( value) ?;
59855977 let idx = self . name ( attr. as_str ( ) ) ;
59865978 emit ! ( self , Instruction :: StoreAttr { idx } ) ;
@@ -6075,7 +6067,6 @@ impl Compiler {
60756067 }
60766068 Expr :: Attribute ( ExprAttribute { value, attr, .. } ) => {
60776069 let attr = attr. as_str ( ) ;
6078- self . check_forbidden_name ( attr, NameUsage :: Store ) ?;
60796070 self . compile_expression ( value) ?;
60806071 emit ! ( self , Instruction :: Copy { index: 1_u32 } ) ;
60816072 let idx = self . name ( attr) ;
@@ -6903,12 +6894,6 @@ impl Compiler {
69036894 let ( size, unpack) = self . gather_elements ( additional_positional, & arguments. args ) ?;
69046895 let has_double_star = arguments. keywords . iter ( ) . any ( |k| k. arg . is_none ( ) ) ;
69056896
6906- for keyword in & arguments. keywords {
6907- if let Some ( name) = & keyword. arg {
6908- self . check_forbidden_name ( name. as_str ( ) , NameUsage :: Store ) ?;
6909- }
6910- }
6911-
69126897 if unpack || has_double_star {
69136898 // Create a tuple with positional args:
69146899 if unpack {
@@ -7511,6 +7496,19 @@ impl Compiler {
75117496 self . code_stack . last_mut ( ) . expect ( "no code on stack" )
75127497 }
75137498
7499+ //github.com/ Enter a conditional block (if/for/while/match/try/with)
7500+ //github.com/ PEP 649: Track conditional annotation context
7501+ fn enter_conditional_block ( & mut self ) {
7502+ self . current_code_info ( ) . in_conditional_block += 1 ;
7503+ }
7504+
7505+ //github.com/ Leave a conditional block
7506+ fn leave_conditional_block ( & mut self ) {
7507+ let code_info = self . current_code_info ( ) ;
7508+ debug_assert ! ( code_info. in_conditional_block > 0 ) ;
7509+ code_info. in_conditional_block -= 1 ;
7510+ }
7511+
75147512 //github.com/ Compile break or continue statement with proper fblock cleanup.
75157513 //github.com/ compiler_break, compiler_continue
75167514 //github.com/ This handles unwinding through With blocks and exception handlers.
0 commit comments