Skip to content

Add SymbolUsage::TypeParams #5941

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3888,8 +3888,6 @@ def test_pep695_generic_class_with_future_annotations(self):
# should not have changed as a result of the get_type_hints() calls!
self.assertEqual(ann_module695.__dict__, original_globals)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_pep695_generic_class_with_future_annotations_and_local_shadowing(self):
hints_for_B = get_type_hints(ann_module695.B)
self.assertEqual(hints_for_B, {"x": int, "y": str, "z": bytes})
Expand Down Expand Up @@ -3935,8 +3933,6 @@ def test_pep_695_generic_method_with_future_annotations_name_clash_with_global_v
set(ann_module695.D.generic_method_2.__type_params__)
)

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_pep_695_generics_with_future_annotations_nested_in_function(self):
results = ann_module695.nested()

Expand Down
7 changes: 6 additions & 1 deletion compiler/codegen/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,11 @@ impl Compiler<'_> {
cache = &mut info.cellvar_cache;
NameOpType::Deref
} // TODO: is this right?
// SymbolScope::Unknown => NameOpType::Global,
SymbolScope::TypeParams => {
// Type parameters are always cell variables
cache = &mut info.cellvar_cache;
NameOpType::Deref
} // SymbolScope::Unknown => NameOpType::Global,
};

if NameUsage::Load == usage && name == "__debug__" {
Expand Down Expand Up @@ -1630,6 +1634,7 @@ impl Compiler<'_> {
let vars = match symbol.scope {
SymbolScope::Free => &parent_code.freevar_cache,
SymbolScope::Cell => &parent_code.cellvar_cache,
SymbolScope::TypeParams => &parent_code.cellvar_cache,
_ if symbol.flags.contains(SymbolFlags::FREE_CLASS) => &parent_code.freevar_cache,
x => unreachable!(
"var {} in a {:?} should be free or cell but it's {:?}",
Expand Down
20 changes: 17 additions & 3 deletions compiler/codegen/src/symboltable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ pub enum SymbolScope {
GlobalImplicit,
Free,
Cell,
TypeParams,
}

bitflags! {
Expand Down Expand Up @@ -359,6 +360,10 @@ impl SymbolTableAnalyzer {
SymbolScope::Local | SymbolScope::Cell => {
// all is well
}
SymbolScope::TypeParams => {
// Type parameters are always cell variables in their scope
symbol.scope = SymbolScope::Cell;
}
SymbolScope::Unknown => {
// Try hard to figure out what the scope of this symbol is.
let scope = if symbol.is_bound() {
Expand Down Expand Up @@ -557,6 +562,7 @@ enum SymbolUsage {
AnnotationParameter,
AssignedNamedExprInComprehension,
Iter,
TypeParam,
}

struct SymbolTableBuilder<'src> {
Expand Down Expand Up @@ -1267,6 +1273,9 @@ impl SymbolTableBuilder<'_> {
}

fn scan_type_params(&mut self, type_params: &TypeParams) -> SymbolTableResult {
// Register .type_params as a type parameter (automatically becomes cell variable)
self.register_name(".type_params", SymbolUsage::TypeParam, type_params.range)?;

// First register all type parameters
for type_param in &type_params.type_params {
match type_param {
Expand All @@ -1276,7 +1285,7 @@ impl SymbolTableBuilder<'_> {
range: type_var_range,
..
}) => {
self.register_name(name.as_str(), SymbolUsage::Assigned, *type_var_range)?;
self.register_name(name.as_str(), SymbolUsage::TypeParam, *type_var_range)?;
if let Some(binding) = bound {
self.scan_expression(binding, ExpressionContext::Load)?;
}
Expand All @@ -1286,14 +1295,14 @@ impl SymbolTableBuilder<'_> {
range: param_spec_range,
..
}) => {
self.register_name(name, SymbolUsage::Assigned, *param_spec_range)?;
self.register_name(name, SymbolUsage::TypeParam, *param_spec_range)?;
}
TypeParam::TypeVarTuple(TypeParamTypeVarTuple {
name,
range: type_var_tuple_range,
..
}) => {
self.register_name(name, SymbolUsage::Assigned, *type_var_tuple_range)?;
self.register_name(name, SymbolUsage::TypeParam, *type_var_tuple_range)?;
}
}
}
Expand Down Expand Up @@ -1544,6 +1553,11 @@ impl SymbolTableBuilder<'_> {
SymbolUsage::Iter => {
flags.insert(SymbolFlags::ITER);
}
SymbolUsage::TypeParam => {
// Type parameters are always cell variables in their scope
symbol.scope = SymbolScope::Cell;
flags.insert(SymbolFlags::ASSIGNED);
}
}

// and even more checking
Expand Down
6 changes: 5 additions & 1 deletion vm/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,11 @@ impl ExecutingFrame<'_> {
}
bytecode::Instruction::LoadClassDeref(i) => {
let i = i.get(arg) as usize;
let name = self.code.freevars[i - self.code.cellvars.len()];
let name = if i < self.code.cellvars.len() {
self.code.cellvars[i]
} else {
self.code.freevars[i - self.code.cellvars.len()]
};
let value = self.locals.mapping().subscript(name, vm).ok();
self.push_value(match value {
Some(v) => v,
Expand Down
Loading