@@ -2173,24 +2173,18 @@ impl Compiler<'_> {
2173
2173
) -> CompileResult < ( ) > {
2174
2174
self . prepare_decorators ( decorator_list) ?;
2175
2175
2176
- let has_type_params = type_params. is_some ( ) ;
2176
+ let is_generic = type_params. is_some ( ) ;
2177
2177
let firstlineno = self . get_source_line_number ( ) . get ( ) . to_u32 ( ) ;
2178
2178
2179
- if has_type_params {
2180
- // For PEP 695 classes, we need to:
2181
- // 1. Enter type params scope
2182
- // 2. Compile type params
2183
- // 3. Call compile_class_body (creates nested scope)
2184
- // 4. Generate class creation code
2185
- // 5. Exit type params scope and wrap everything in a function
2186
-
2179
+ // Step 1: If generic, enter type params scope and compile type params
2180
+ if is_generic {
2187
2181
let type_params_name = format ! ( "<generic parameters of {}>" , name) ;
2188
2182
self . push_output (
2189
2183
bytecode:: CodeFlags :: IS_OPTIMIZED | bytecode:: CodeFlags :: NEW_LOCALS ,
2190
2184
0 ,
2191
2185
0 ,
2192
2186
0 ,
2193
- type_params_name. clone ( ) ,
2187
+ type_params_name,
2194
2188
) ;
2195
2189
2196
2190
// Set private name for name mangling
@@ -2200,35 +2194,39 @@ impl Compiler<'_> {
2200
2194
self . compile_type_params ( type_params. unwrap ( ) ) ?;
2201
2195
let dot_type_params = self . name ( ".type_params" ) ;
2202
2196
emit ! ( self , Instruction :: StoreLocal ( dot_type_params) ) ;
2197
+ }
2203
2198
2204
- // Compile the class body (creates its own scope )
2205
- let prev_ctx = self . ctx ;
2206
- self . ctx = CompileContext {
2207
- func : FunctionContext :: NoFunction ,
2208
- in_class : true ,
2209
- loop_data : None ,
2210
- } ;
2211
- let class_code = self . compile_class_body ( name, body, type_params, firstlineno) ?;
2212
- self . ctx = prev_ctx;
2199
+ // Step 2: Compile class body (always done, whether generic or not )
2200
+ let prev_ctx = self . ctx ;
2201
+ self . ctx = CompileContext {
2202
+ func : FunctionContext :: NoFunction ,
2203
+ in_class : true ,
2204
+ loop_data : None ,
2205
+ } ;
2206
+ let class_code = self . compile_class_body ( name, body, type_params, firstlineno) ?;
2207
+ self . ctx = prev_ctx;
2213
2208
2214
- // Back in type params scope, create .generic_base
2209
+ // Step 3: Generate the rest of the code for the call
2210
+ if is_generic {
2211
+ // Still in type params scope
2212
+ let dot_type_params = self . name ( ".type_params" ) ;
2213
+ let dot_generic_base = self . name ( ".generic_base" ) ;
2214
+
2215
+ // Create .generic_base
2215
2216
emit ! ( self , Instruction :: LoadNameAny ( dot_type_params) ) ;
2216
2217
emit ! (
2217
2218
self ,
2218
2219
Instruction :: CallIntrinsic1 {
2219
2220
func: bytecode:: IntrinsicFunction1 :: SubscriptGeneric
2220
2221
}
2221
2222
) ;
2222
- let dot_generic_base = self . name ( ".generic_base" ) ;
2223
2223
emit ! ( self , Instruction :: StoreLocal ( dot_generic_base) ) ;
2224
2224
2225
- // Generate the class creation code (still in type params scope)
2225
+ // Generate class creation code
2226
2226
emit ! ( self , Instruction :: LoadBuildClass ) ;
2227
2227
2228
- // Set up the class function
2228
+ // Set up the class function with type params
2229
2229
let mut func_flags = bytecode:: MakeFunctionFlags :: empty ( ) ;
2230
-
2231
- // Load .type_params for the class function
2232
2230
emit ! ( self , Instruction :: LoadNameAny ( dot_type_params) ) ;
2233
2231
func_flags |= bytecode:: MakeFunctionFlags :: TYPE_PARAMS ;
2234
2232
@@ -2240,12 +2238,10 @@ impl Compiler<'_> {
2240
2238
code : Box :: new ( class_code) ,
2241
2239
} ) ;
2242
2240
self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
2243
-
2244
2241
emit ! ( self , Instruction :: MakeFunction ( func_flags) ) ;
2245
-
2246
2242
self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
2247
2243
2248
- // Compile bases with .generic_base appended
2244
+ // Compile original bases
2249
2245
let base_count = if let Some ( arguments) = arguments {
2250
2246
for arg in & arguments. args {
2251
2247
self . compile_expression ( arg) ?;
@@ -2272,7 +2268,6 @@ impl Compiler<'_> {
2272
2268
}
2273
2269
self . compile_expression ( & keyword. value ) ?;
2274
2270
}
2275
-
2276
2271
emit ! (
2277
2272
self ,
2278
2273
Instruction :: CallFunctionKeyword {
@@ -2286,52 +2281,38 @@ impl Compiler<'_> {
2286
2281
// Return the created class
2287
2282
self . emit_return_value ( ) ;
2288
2283
2289
- // Exit type params scope and get the code object
2284
+ // Exit type params scope and wrap in function
2290
2285
let type_params_code = self . exit_scope ( ) ;
2291
2286
2292
- // Now execute the type params function
2287
+ // Execute the type params function
2293
2288
if self . build_closure ( & type_params_code) {
2294
2289
// Should not need closure
2295
2290
}
2296
2291
self . emit_load_const ( ConstantData :: Code {
2297
2292
code : Box :: new ( type_params_code) ,
2298
2293
} ) ;
2299
2294
self . emit_load_const ( ConstantData :: Str {
2300
- value : type_params_name . into ( ) ,
2295
+ value : format ! ( "<generic parameters of {}>" , name ) . into ( ) ,
2301
2296
} ) ;
2302
2297
emit ! (
2303
2298
self ,
2304
2299
Instruction :: MakeFunction ( bytecode:: MakeFunctionFlags :: empty( ) )
2305
2300
) ;
2306
-
2307
2301
emit ! ( self , Instruction :: CallFunctionPositional { nargs: 0 } ) ;
2308
2302
} else {
2309
- // Traditional class without type params
2310
- let prev_ctx = self . ctx ;
2311
- self . ctx = CompileContext {
2312
- func : FunctionContext :: NoFunction ,
2313
- in_class : true ,
2314
- loop_data : None ,
2315
- } ;
2316
-
2317
- let code = self . compile_class_body ( name, body, type_params, firstlineno) ?;
2318
- self . ctx = prev_ctx;
2319
-
2303
+ // Non-generic class: standard path
2320
2304
emit ! ( self , Instruction :: LoadBuildClass ) ;
2321
2305
2322
2306
let mut func_flags = bytecode:: MakeFunctionFlags :: empty ( ) ;
2323
-
2324
- if self . build_closure ( & code) {
2307
+ if self . build_closure ( & class_code) {
2325
2308
func_flags |= bytecode:: MakeFunctionFlags :: CLOSURE ;
2326
2309
}
2327
2310
2328
2311
self . emit_load_const ( ConstantData :: Code {
2329
- code : Box :: new ( code ) ,
2312
+ code : Box :: new ( class_code ) ,
2330
2313
} ) ;
2331
2314
self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
2332
-
2333
2315
emit ! ( self , Instruction :: MakeFunction ( func_flags) ) ;
2334
-
2335
2316
self . emit_load_const ( ConstantData :: Str { value : name. into ( ) } ) ;
2336
2317
2337
2318
let call = if let Some ( arguments) = arguments {
@@ -2342,6 +2323,7 @@ impl Compiler<'_> {
2342
2323
self . compile_normal_call ( call) ;
2343
2324
}
2344
2325
2326
+ // Step 4: Apply decorators and store (common to both paths)
2345
2327
self . apply_decorators ( decorator_list) ;
2346
2328
self . store_name ( name)
2347
2329
}
0 commit comments