Skip to content

Conversation

@charliermarsh
Copy link
Member

@charliermarsh charliermarsh commented Nov 30, 2025

Summary

The exact behavior around what's allowed vs. disallowed was partly detected through trial and error in the runtime.

I was a little confused by this comment that says "NamedTuple subclasses cannot be inherited from" because in practice that doesn't appear to error at runtime.

Closes #1683.

@charliermarsh charliermarsh added the ty Multi-file analysis & type inference label Nov 30, 2025
@charliermarsh charliermarsh changed the title Forbid use of super() in NamedTuple subclasses [ty] Forbid use of super() in NamedTuple subclasses Nov 30, 2025
@astral-sh-bot
Copy link

astral-sh-bot bot commented Nov 30, 2025

Diagnostic diff on typing conformance tests

No changes detected when running ty on typing conformance tests ✅

@astral-sh-bot
Copy link

astral-sh-bot bot commented Nov 30, 2025

mypy_primer results

Changes were detected when running on open source projects
scikit-build-core (https://github.com/scikit-build/scikit-build-core)
+ src/scikit_build_core/build/_pathutil.py:25:38: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `str | PathLike[str]`, found `DirEntry[Path]`
+ src/scikit_build_core/build/_pathutil.py:27:24: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `str | PathLike[str]`, found `DirEntry[Path]`
+ src/scikit_build_core/build/wheel.py:98:20: error[no-matching-overload] No overload of bound method `__init__` matches arguments
- Found 41 diagnostics
+ Found 44 diagnostics

pydantic (https://github.com/pydantic/pydantic)
- pydantic/fields.py:943:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:943:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:983:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:983:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1026:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1026:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1066:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1066:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1109:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1109:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1148:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1148:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1188:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1188:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1567:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`, found `Top[dict[Unknown, Unknown]] | (((dict[str, Divergent], /) -> None) & ~Top[dict[Unknown, Unknown]]) | None`
+ pydantic/fields.py:1567:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`, found `Top[dict[Unknown, Unknown]] | (((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) & ~Top[dict[Unknown, Unknown]]) | None`

No memory usage changes detected ✅

@charliermarsh charliermarsh force-pushed the charlie/named branch 2 times, most recently from ca3d7ae to 25b9574 Compare November 30, 2025 03:13
Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

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

Thank you, this is excellent! Just a few nitpicks really


## `super()` is not supported in NamedTuple methods

Using `super()` in a method of a `NamedTuple` subclass will raise an exception at runtime. In Python
Copy link
Member

Choose a reason for hiding this comment

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

extremely nitpicky comment: my preferred term is "NamedTuple class" rather than "NamedTuple subclass". The generated class doesn't actually have NamedTuple in its MRO (because NamedTuple is actually a function rather than a class!) -- the generated class actually inherits directly from tuple. The runtime does some magic to swap out NamedTuple for tuple in the class's bases, so it feels slightly incorrect to refer to it as a "subclass of" NamedTuple, even if NamedTuple is included in the class's bases.

Suggested change
Using `super()` in a method of a `NamedTuple` subclass will raise an exception at runtime. In Python
Using `super()` in a method of a `NamedTuple` class will raise an exception at runtime. In Python

Copy link
Member

Choose a reason for hiding this comment

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

You could also add a test to verify that using super() on a NamedTuple class works fine if it occurs outside the class, e.g.

class F(NamedTuple):
    x: int

super(F, F(42))  # fine

.report_lint(&SUPER_CALL_IN_NAMED_TUPLE_METHOD, call_expression)
{
builder.into_diagnostic(format_args!(
"Cannot use `super()` in a method of NamedTuple subclass `{}`",
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
"Cannot use `super()` in a method of NamedTuple subclass `{}`",
"Cannot use `super()` in a method of NamedTuple class `{}`",

.report_lint(&SUPER_CALL_IN_NAMED_TUPLE_METHOD, call_expression)
{
builder.into_diagnostic(format_args!(
"Cannot use `super()` in a method of NamedTuple subclass `{}`",
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
"Cannot use `super()` in a method of NamedTuple subclass `{}`",
"Cannot use `super()` in a method of NamedTuple class `{}`",


declare_lint! {
/// ## What it does
/// Checks for calls to `super()` inside methods of `NamedTuple` subclasses.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// Checks for calls to `super()` inside methods of `NamedTuple` subclasses.
/// Checks for calls to `super()` inside methods of `NamedTuple` classes.

/// Checks for calls to `super()` inside methods of `NamedTuple` subclasses.
///
/// ## Why is this bad?
/// Using `super()` in a method of a `NamedTuple` subclass will raise an exception at runtime.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// Using `super()` in a method of a `NamedTuple` subclass will raise an exception at runtime.
/// Using `super()` in a method of a `NamedTuple` class will raise an exception at runtime.

Comment on lines 1785 to 1786
summary: "detects `super()` calls in methods of `NamedTuple` subclasses",
status: LintStatus::preview("1.0.0"),
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
summary: "detects `super()` calls in methods of `NamedTuple` subclasses",
status: LintStatus::preview("1.0.0"),
summary: "detects `super()` calls in methods of `NamedTuple` classes",
status: LintStatus::preview("0.0.1-alpha.30"),

@AlexWaygood
Copy link
Member

I was a little confused by this comment that says "NamedTuple subclasses cannot be inherited from" because in practice that doesn't appear to error at runtime.

yeah, I think that comment was just incorrect

@charliermarsh charliermarsh enabled auto-merge (squash) November 30, 2025 15:34
@charliermarsh charliermarsh merged commit e7beb7e into main Nov 30, 2025
40 checks passed
@charliermarsh charliermarsh deleted the charlie/named branch November 30, 2025 15:49
@codspeed-hq
Copy link

codspeed-hq bot commented Nov 30, 2025

CodSpeed Performance Report

Merging #21700 will improve performances by 4.45%

Comparing charlie/named (664df36) with main (b02e821)

Summary

⚡ 1 improvement
✅ 21 untouched
⏩ 30 skipped1

Benchmarks breakdown

Mode Benchmark BASE HEAD Change
WallTime large[pydantic] 207.5 s 198.7 s +4.45%

Footnotes

  1. 30 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Detect attempts to use super() in NamedTuple methods

3 participants