(
&mut self,
target: &ast::Expr,
annotation: &ast::Expr,
value: Option<&ast::Expr>,
simple: bool,
)
| 7098 | } |
| 7099 | |
| 7100 | fn compile_annotated_assign( |
| 7101 | &mut self, |
| 7102 | target: &ast::Expr, |
| 7103 | annotation: &ast::Expr, |
| 7104 | value: Option<&ast::Expr>, |
| 7105 | simple: bool, |
| 7106 | ) -> CompileResult<()> { |
| 7107 | // Perform the actual assignment first |
| 7108 | if let Some(value) = value { |
| 7109 | self.compile_expression(value)?; |
| 7110 | self.compile_store(target)?; |
| 7111 | } |
| 7112 | |
| 7113 | // If we have a simple name in module or class scope, store annotation |
| 7114 | if simple |
| 7115 | && !self.ctx.in_func() |
| 7116 | && let ast::Expr::Name(ast::ExprName { id, .. }) = target |
| 7117 | { |
| 7118 | if self.future_annotations { |
| 7119 | // PEP 563: Store stringified annotation directly to __annotations__ |
| 7120 | // Compile annotation as string |
| 7121 | self.compile_annotation(annotation)?; |
| 7122 | // Load __annotations__ |
| 7123 | let annotations_name = self.name("__annotations__"); |
| 7124 | emit!( |
| 7125 | self, |
| 7126 | Instruction::LoadName { |
| 7127 | namei: annotations_name |
| 7128 | } |
| 7129 | ); |
| 7130 | // Load the variable name |
| 7131 | self.emit_load_const(ConstantData::Str { |
| 7132 | value: self.mangle(id.as_str()).into_owned().into(), |
| 7133 | }); |
| 7134 | // Store: __annotations__[name] = annotation |
| 7135 | emit!(self, Instruction::StoreSubscr); |
| 7136 | } else { |
| 7137 | // PEP 649: Handle conditional annotations |
| 7138 | if self.current_symbol_table().has_conditional_annotations { |
| 7139 | // Allocate an index for every annotation when has_conditional_annotations |
| 7140 | // This keeps indices aligned with compile_module_annotate's enumeration |
| 7141 | let code_info = self.current_code_info(); |
| 7142 | let annotation_index = code_info.next_conditional_annotation_index; |
| 7143 | code_info.next_conditional_annotation_index += 1; |
| 7144 | |
| 7145 | // Determine if this annotation is conditional |
| 7146 | // Module and Class scopes both need all annotations tracked |
| 7147 | let scope_type = self.current_symbol_table().typ; |
| 7148 | let in_conditional_block = self.current_code_info().in_conditional_block > 0; |
| 7149 | let is_conditional = |
| 7150 | matches!(scope_type, CompilerScope::Module | CompilerScope::Class) |
| 7151 | || in_conditional_block; |
| 7152 | |
| 7153 | // Only add to __conditional_annotations__ set if actually conditional |
| 7154 | if is_conditional { |
| 7155 | self.load_name("__conditional_annotations__")?; |
| 7156 | self.emit_load_const(ConstantData::Integer { |
| 7157 | value: annotation_index.into(), |
no test coverage detected