Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Reject GenericAlias parameters added after caching
Validate stale cached parameters and retain the Python regression without obsolete reference prerequisites.

Assisted-by: OpenAI Codex:model identifier unavailable
  • Loading branch information
youknowdot committed Oct 11, 2026
commit 9c3351f155a31d8f99c96f118b808cf77ac5422c
5 changes: 4 additions & 1 deletion crates/vm/src/builtins/genericalias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,10 @@ pub(crate) fn subs_parameters(
if let Some(iparam) = tuple_index(parameters.as_slice(), arg) {
subst.call((arg_items[iparam].clone(),), vm)?
} else {
subs_tvars(arg.clone(), parameters, &arg_items, vm)?
return Err(vm.new_type_error(format!(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Defer stale checks until the parameter cache is materialized

When __typing_subst__ is added before an alias's first parameter lookup, this return treats the parameter as stale even though Python 3.15 has not cached __parameters__ yet. For example, let late.__parameters__ == (T,), create GenericAlias(list, late), set late.__typing_subst__ = lambda x: x, and evaluate alias[int]; Python returns list[int], but PyGenericAlias::new eagerly saved (T,), so late misses tuple_index and this branch raises. Lazily materialize or track the parameter cache so the guard applies only after it was actually cached.

AGENTS.md reference: AGENTS.md:L7-L7

Useful? React with 👍 / 👎.

"argument {} with __typing_subst__ was not found in __parameters__",
arg.repr(vm)?
)));
}
} else {
subs_tvars(arg.clone(), parameters, &arg_items, vm)?
Expand Down
22 changes: 22 additions & 0 deletions extra_tests/snippets/stdlib_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,25 @@ def __module__(self):
)
assert alias_namespace["alias"].__module__ is None
assert alias_module_lookups == []


# GenericAlias rejects parameters added after its parameter tuple was cached.
from types import GenericAlias


class LateParameter:
def __repr__(self):
return "late_parameter"


first = LateParameter()
first.__typing_subst__ = lambda value: value
late = LateParameter()
alias = GenericAlias(dict, (first, late))
assert alias.__parameters__ == (first,)
late.__typing_subst__ = lambda value: value
with assert_raises(TypeError) as caught:
alias[0]
assert str(caught.exception) == (
"argument late_parameter with __typing_subst__ was not found in __parameters__"
Comment on lines +109 to +112

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove the newly added test logic

This new assertion block adds test logic to extra_tests/snippets/stdlib_typing.py, while the repository's critical test-code policy permits test-file changes only for adding or removing expected-failure decorators and explicitly forbids modifying assertions, logic, or data. Remove this addition from the test file or change the repository policy first; it cannot land in its current form.

AGENTS.md reference: AGENTS.md:L273-L280

Useful? React with 👍 / 👎.

)