@@ -1249,12 +1249,35 @@ impl Compiler {
12491249
12501250 // Build freevars using dictbytype (FREE scope, offset by cellvars size)
12511251 let mut freevar_cache = IndexSet::default();
1252+ let annotation_free_names: IndexSet<String> = ste
1253+ .annotation_block
1254+ .as_ref()
1255+ .map(|annotation| {
1256+ annotation
1257+ .symbols
1258+ .iter()
1259+ .filter(|(_, s)| {
1260+ s.scope == SymbolScope::Free || s.flags.contains(SymbolFlags::FREE_CLASS)
1261+ })
1262+ .map(|(name, _)| name.clone())
1263+ .collect()
1264+ })
1265+ .unwrap_or_default();
12521266 let mut free_names: Vec<_> = ste
12531267 .symbols
12541268 .iter()
12551269 .filter(|(_, s)| {
12561270 s.scope == SymbolScope::Free || s.flags.contains(SymbolFlags::FREE_CLASS)
12571271 })
1272+ .filter(|(name, symbol)| {
1273+ if !matches!(
1274+ scope_type,
1275+ CompilerScope::Function | CompilerScope::AsyncFunction | CompilerScope::Lambda
1276+ ) {
1277+ return true;
1278+ }
1279+ !(annotation_free_names.contains(*name) && symbol.flags.is_empty())
1280+ })
12581281 .map(|(name, _)| name.clone())
12591282 .collect();
12601283 free_names.sort();
@@ -1866,9 +1889,18 @@ impl Compiler {
18661889 let mut parent_idx = stack_size - 2;
18671890 let mut parent = &self.code_stack[parent_idx];
18681891
1869- // If parent is ast::TypeParams scope, look at grandparent
1870- // Check if parent is a type params scope by name pattern
1871- if parent.metadata.name.starts_with("<generic parameters of ") {
1892+ let parent_scope = self
1893+ .symbol_table_stack
1894+ .get(parent_idx)
1895+ .map(|table| table.typ);
1896+
1897+ // CPython skips both generic-parameter scopes and annotation scopes
1898+ // when building qualnames for the contained function/class code object.
1899+ if matches!(
1900+ parent_scope,
1901+ Some(CompilerScope::TypeParams | CompilerScope::Annotation)
1902+ ) || parent.metadata.name.starts_with("<generic parameters of ")
1903+ {
18721904 if stack_size == 2 {
18731905 // If we're immediately within the module, qualname is just the name
18741906 return current_obj_name;
@@ -2294,7 +2326,13 @@ impl Compiler {
22942326 NameOp::Name
22952327 }
22962328 }
2297- SymbolScope::GlobalExplicit => NameOp::Global,
2329+ SymbolScope::GlobalExplicit => {
2330+ if can_see_class_scope {
2331+ NameOp::DictOrGlobals
2332+ } else {
2333+ NameOp::Global
2334+ }
2335+ }
22982336 SymbolScope::Unknown => {
22992337 if module_global_from_nested_scope {
23002338 NameOp::Global
@@ -2797,24 +2835,14 @@ impl Compiler {
27972835 value,
27982836 ..
27992837 }) => {
2800- // let name_string = name.to_string();
28012838 let Some(name) = name.as_name_expr() else {
2802- // FIXME: is error here?
28032839 return Err(self.error(CodegenErrorType::SyntaxError(
28042840 "type alias expect name".to_owned(),
28052841 )));
28062842 };
28072843 let name_string = name.id.to_string();
28082844
2809- // For PEP 695 syntax, we need to compile type_params first
2810- // so that they're available when compiling the value expression
2811- // Push name first
2812- self.emit_load_const(ConstantData::Str {
2813- value: name_string.clone().into(),
2814- });
2815-
28162845 if let Some(type_params) = type_params {
2817- // Outer scope for TypeParams
28182846 self.push_symbol_table()?;
28192847 let key = self.symbol_table_stack.len() - 1;
28202848 let lineno = self.get_source_line_number().get().to_u32();
@@ -2830,89 +2858,40 @@ impl Compiler {
28302858 in_async_scope: false,
28312859 };
28322860
2833- // Compile type params inside the scope
2861+ self.emit_load_const(ConstantData::Str {
2862+ value: name_string.clone().into(),
2863+ });
28342864 self.compile_type_params(type_params)?;
2835- // Stack: [type_params_tuple]
2836-
2837- // Inner closure for lazy value evaluation
2838- self.push_symbol_table()?;
2839- let inner_key = self.symbol_table_stack.len() - 1;
2840- self.enter_scope("TypeAlias", CompilerScope::TypeParams, inner_key, lineno)?;
2841- // Evaluator takes a positional-only format parameter
2842- self.current_code_info().metadata.argcount = 1;
2843- self.current_code_info().metadata.posonlyargcount = 1;
2844- self.current_code_info()
2845- .metadata
2846- .varnames
2847- .insert("format".to_owned());
2848- self.emit_format_validation()?;
2849- self.compile_expression(value)?;
2850- emit!(self, Instruction::ReturnValue);
2851- let value_code = self.exit_scope();
2852- self.make_closure(value_code, bytecode::MakeFunctionFlags::new())?;
2853- // Stack: [type_params_tuple, value_closure]
2854-
2855- // Swap so unpack_sequence reverse gives correct order
2856- emit!(self, Instruction::Swap { i: 2 });
2857- // Stack: [value_closure, type_params_tuple]
2858-
2859- // Build tuple and return from TypeParams scope
2860- emit!(self, Instruction::BuildTuple { count: 2 });
2865+ self.compile_typealias_value_closure(&name_string, value)?;
2866+ emit!(self, Instruction::BuildTuple { count: 3 });
2867+ emit!(
2868+ self,
2869+ Instruction::CallIntrinsic1 {
2870+ func: bytecode::IntrinsicFunction1::TypeAlias
2871+ }
2872+ );
28612873 emit!(self, Instruction::ReturnValue);
28622874
28632875 let code = self.exit_scope();
28642876 self.ctx = prev_ctx;
28652877 self.make_closure(code, bytecode::MakeFunctionFlags::new())?;
28662878 emit!(self, Instruction::PushNull);
28672879 emit!(self, Instruction::Call { argc: 0 });
2868-
2869- // Unpack: (value_closure, type_params_tuple)
2870- // UnpackSequence reverses → stack: [name, type_params_tuple, value_closure]
2871- emit!(self, Instruction::UnpackSequence { count: 2 });
28722880 } else {
2873- // Push None for type_params
2881+ self.emit_load_const(ConstantData::Str {
2882+ value: name_string.clone().into(),
2883+ });
28742884 self.emit_load_const(ConstantData::None);
2875- // Stack: [name, None]
2876-
2877- // Create a closure for lazy evaluation of the value
2878- self.push_symbol_table()?;
2879- let key = self.symbol_table_stack.len() - 1;
2880- let lineno = self.get_source_line_number().get().to_u32();
2881- self.enter_scope("TypeAlias", CompilerScope::TypeParams, key, lineno)?;
2882- // Evaluator takes a positional-only format parameter
2883- self.current_code_info().metadata.argcount = 1;
2884- self.current_code_info().metadata.posonlyargcount = 1;
2885- self.current_code_info()
2886- .metadata
2887- .varnames
2888- .insert("format".to_owned());
2889- self.emit_format_validation()?;
2890-
2891- let prev_ctx = self.ctx;
2892- self.ctx = CompileContext {
2893- loop_data: None,
2894- in_class: prev_ctx.in_class,
2895- func: FunctionContext::Function,
2896- in_async_scope: false,
2897- };
2898-
2899- self.compile_expression(value)?;
2900- emit!(self, Instruction::ReturnValue);
2901-
2902- let code = self.exit_scope();
2903- self.ctx = prev_ctx;
2904- self.make_closure(code, bytecode::MakeFunctionFlags::new())?;
2905- // Stack: [name, None, closure]
2885+ self.compile_typealias_value_closure(&name_string, value)?;
2886+ emit!(self, Instruction::BuildTuple { count: 3 });
2887+ emit!(
2888+ self,
2889+ Instruction::CallIntrinsic1 {
2890+ func: bytecode::IntrinsicFunction1::TypeAlias
2891+ }
2892+ );
29062893 }
29072894
2908- // Build tuple of 3 elements and call intrinsic
2909- emit!(self, Instruction::BuildTuple { count: 3 });
2910- emit!(
2911- self,
2912- Instruction::CallIntrinsic1 {
2913- func: bytecode::IntrinsicFunction1::TypeAlias
2914- }
2915- );
29162895 self.store_name(&name_string)?;
29172896 }
29182897 ast::Stmt::IpyEscapeCommand(_) => todo!(),
@@ -3015,6 +2994,10 @@ impl Compiler {
30152994 name: &str,
30162995 allow_starred: bool,
30172996 ) -> CompileResult<()> {
2997+ self.emit_load_const(ConstantData::Tuple {
2998+ elements: vec![ConstantData::Integer { value: 1.into() }],
2999+ });
3000+
30183001 // Push the next symbol table onto the stack
30193002 self.push_symbol_table()?;
30203003
@@ -3023,11 +3006,8 @@ impl Compiler {
30233006 let lineno = self.get_source_line_number().get().to_u32();
30243007
30253008 // Enter scope with the type parameter name
3026- self.enter_scope(name, CompilerScope::TypeParams , key, lineno)?;
3009+ self.enter_scope(name, CompilerScope::Annotation , key, lineno)?;
30273010
3028- // Evaluator takes a positional-only format parameter
3029- self.current_code_info().metadata.argcount = 1;
3030- self.current_code_info().metadata.posonlyargcount = 1;
30313011 self.current_code_info()
30323012 .metadata
30333013 .varnames
@@ -3061,8 +3041,50 @@ impl Compiler {
30613041 let code = self.exit_scope();
30623042 self.ctx = prev_ctx;
30633043
3064- // Create closure for lazy evaluation
3065- self.make_closure(code, bytecode::MakeFunctionFlags::new())?;
3044+ self.make_closure(
3045+ code,
3046+ bytecode::MakeFunctionFlags::from([bytecode::MakeFunctionFlag::Defaults]),
3047+ )?;
3048+
3049+ Ok(())
3050+ }
3051+
3052+ fn compile_typealias_value_closure(
3053+ &mut self,
3054+ alias_name: &str,
3055+ value: &ast::Expr,
3056+ ) -> CompileResult<()> {
3057+ self.emit_load_const(ConstantData::Tuple {
3058+ elements: vec![ConstantData::Integer { value: 1.into() }],
3059+ });
3060+
3061+ self.push_symbol_table()?;
3062+ let key = self.symbol_table_stack.len() - 1;
3063+ let lineno = self.get_source_line_number().get().to_u32();
3064+ self.enter_scope(alias_name, CompilerScope::Annotation, key, lineno)?;
3065+ self.current_code_info()
3066+ .metadata
3067+ .varnames
3068+ .insert(".format".to_owned());
3069+ self.emit_format_validation()?;
3070+
3071+ let prev_ctx = self.ctx;
3072+ self.ctx = CompileContext {
3073+ loop_data: None,
3074+ in_class: prev_ctx.in_class,
3075+ func: FunctionContext::Function,
3076+ in_async_scope: false,
3077+ };
3078+
3079+ self.compile_expression(value)?;
3080+ emit!(self, Instruction::ReturnValue);
3081+
3082+ let code = self.exit_scope();
3083+ self.ctx = prev_ctx;
3084+ self.make_closure(
3085+ code,
3086+ bytecode::MakeFunctionFlags::from([bytecode::MakeFunctionFlag::Defaults]),
3087+ )?;
30663088
30673089 Ok(())
30683090 }
@@ -3084,12 +3106,7 @@ impl Compiler {
30843106 });
30853107
30863108 if let Some(expr) = &bound {
3087- let scope_name = if expr.is_tuple_expr() {
3088- format!("<TypeVar constraint of {name}>")
3089- } else {
3090- format!("<TypeVar bound of {name}>")
3091- };
3092- self.compile_type_param_bound_or_default(expr, &scope_name, false)?;
3109+ self.compile_type_param_bound_or_default(expr, name.as_str(), false)?;
30933110
30943111 let intrinsic = if expr.is_tuple_expr() {
30953112 bytecode::IntrinsicFunction2::TypeVarWithConstraint
@@ -3107,8 +3124,11 @@ impl Compiler {
31073124 }
31083125
31093126 if let Some(default_expr) = default {
3110- let scope_name = format!("<TypeVar default of {name}>");
3111- self.compile_type_param_bound_or_default(default_expr, &scope_name, false)?;
3127+ self.compile_type_param_bound_or_default(
3128+ default_expr,
3129+ name.as_str(),
3130+ false,
3131+ )?;
31123132 emit!(
31133133 self,
31143134 Instruction::CallIntrinsic2 {
@@ -3132,8 +3152,11 @@ impl Compiler {
31323152 );
31333153
31343154 if let Some(default_expr) = default {
3135- let scope_name = format!("<ParamSpec default of {name}>");
3136- self.compile_type_param_bound_or_default(default_expr, &scope_name, false)?;
3155+ self.compile_type_param_bound_or_default(
3156+ default_expr,
3157+ name.as_str(),
3158+ false,
3159+ )?;
31373160 emit!(
31383161 self,
31393162 Instruction::CallIntrinsic2 {
@@ -3160,8 +3183,11 @@ impl Compiler {
31603183
31613184 if let Some(default_expr) = default {
31623185 // TypeVarTuple allows starred expressions
3163- let scope_name = format!("<TypeVarTuple default of {name}>");
3164- self.compile_type_param_bound_or_default(default_expr, &scope_name, true)?;
3186+ self.compile_type_param_bound_or_default(
3187+ default_expr,
3188+ name.as_str(),
3189+ true,
3190+ )?;
31653191 emit!(
31663192 self,
31673193 Instruction::CallIntrinsic2 {
@@ -4560,7 +4586,7 @@ impl Compiler {
45604586 self.current_code_info()
45614587 .metadata
45624588 .varnames
4563- .insert("format".to_owned());
4589+ .insert(". format".to_owned());
45644590
45654591 // Emit format validation: if format > VALUE_WITH_FAKE_GLOBALS: raise NotImplementedError
45664592 self.emit_format_validation()?;
0 commit comments