Summary
When @overload is referenced through a name other than the imported one — e.g. o = overload — the entire overload rule family stops firing. overloads_definitions (missing implementation, a hard spec error) and overloads_consistency (duplicate/unreachable overload) both go silent.
Found via the "type torture" puzzle on X: https://x.com/charliermarsh/status/2082885991686090885
Reported from the web playground; reproduced identically on the CLI. Reproduced on a clean cargo build --release of main @ 5b756d3.
Reported reproduction
from typing import*;o=overload
type R[T]=set[R[T|R[T]]]
@o
def f()->R[R]:0
@o
def f():0
class C:__call__:"C";f=f
C(C()()).f()
Basilisk reports exactly one diagnostic (generics_syntax_scoping on line 2 — see the separate issue about that rule) and misses the overload errors entirely.
Minimal cases
# A — direct decorator, no implementation: CAUGHT
from typing import overload
@overload
def f(x: int) -> int: ...
@overload
def f(x: str) -> str: ...
# error[overloads_definitions]: Function `f` has 2 `@overload` signatures but no implementation
# B — same file, decorator aliased: SILENT
from typing import overload
o = overload
@o
def f(x: int) -> int: ...
@o
def f(x: str) -> str: ...
# (no diagnostics)
# C — star import, direct decorator: CAUGHT (so `import *` is not the trigger)
from typing import *
@overload
def f(x: int) -> int: ...
@overload
def f(x: str) -> str: ...
# error[overloads_definitions]: ...
The same aliasing also hides overloads_consistency. With the decorator written directly, the torture puzzle's two identical def f() signatures are caught:
from typing import *
@overload
def f()->int:0
@overload
def f():0
class C:
__call__: "C"
g = f
C(C()()).g()
# error[overloads_definitions]: Function `f` has 2 `@overload` signatures but no implementation
# error[overloads_consistency]: `@overload` variant of `f` has the same parameter signature as a previous overload
Swap @overload for @o and both disappear. So a single unrecognised decorator name suppresses two independent spec errors.
Expected
o = overload binds the name o to typing.overload itself; @o is @overload by identity. A function decorated with it is an overload, and outside a stub an overload set without an implementation is an error the spec requires.
Decorator recognition should resolve the decorator expression through the module's binding table to its originating symbol, rather than matching the decorator's spelled name. The same gap will apply to any other special form referenced through a local alias (from typing import overload as ov is worth checking as part of the fix, along with typing.overload / t.overload attribute spellings).
Severity note
This is a silent-under-report, not a false positive, so it does not threaten the conformance gate — the upstream suite always spells @overload directly. It is still a wrong answer on valid Python, and the failure mode is the dangerous kind: an entire rule family disappears with no signal.
Summary
When
@overloadis referenced through a name other than the imported one — e.g.o = overload— the entire overload rule family stops firing.overloads_definitions(missing implementation, a hard spec error) andoverloads_consistency(duplicate/unreachable overload) both go silent.Found via the "type torture" puzzle on X: https://x.com/charliermarsh/status/2082885991686090885
Reported from the web playground; reproduced identically on the CLI. Reproduced on a clean
cargo build --releaseofmain@ 5b756d3.Reported reproduction
Basilisk reports exactly one diagnostic (
generics_syntax_scopingon line 2 — see the separate issue about that rule) and misses the overload errors entirely.Minimal cases
The same aliasing also hides
overloads_consistency. With the decorator written directly, the torture puzzle's two identicaldef f()signatures are caught:Swap
@overloadfor@oand both disappear. So a single unrecognised decorator name suppresses two independent spec errors.Expected
o = overloadbinds the nameototyping.overloaditself;@ois@overloadby identity. A function decorated with it is an overload, and outside a stub an overload set without an implementation is an error the spec requires.Decorator recognition should resolve the decorator expression through the module's binding table to its originating symbol, rather than matching the decorator's spelled name. The same gap will apply to any other special form referenced through a local alias (
from typing import overload as ovis worth checking as part of the fix, along withtyping.overload/t.overloadattribute spellings).Severity note
This is a silent-under-report, not a false positive, so it does not threaten the conformance gate — the upstream suite always spells
@overloaddirectly. It is still a wrong answer on valid Python, and the failure mode is the dangerous kind: an entire rule family disappears with no signal.