Skip to content

aliases_implicit: is_assignable_to_bound accepts every TypeVar bound outside int/float/complex #410

Description

@MelbourneDeveloper

Split out of #408. Confirmed live on main @ da74283 and on the bidirectionaltype-inference branch.

The code

crates/basilisk-checker/src/rules/aliases_implicit.rs:757

fn is_assignable_to_bound(
    subtyping: &crate::subtyping::SubtypingContext,
    arg: &str,
    bound: &str,
) -> bool {
    match bound {
        "int" | "float" | "complex" => subtyping.is_subtype(arg, bound),
        _ => true,
    }
}

Every TypeVar bound that is not int, float, or complex returns true — accept. Bound checking on type-alias parameterization exists only for the numeric tower.

Why that is exactly the numeric tower

aliases_implicit.py declares exactly one bounded TypeVar:

TFloat = TypeVar("TFloat", bound=float)   # line 10
GoodTypeAlias12 = list[TFloat]            # line 41
...
p6: GoodTypeAlias12[str],  # E: type argument doesn't match bound   (line 81)

float is the only bound the suite exercises. The implemented set is int | float | complex — that one bound plus its two numeric-tower neighbours. Nothing else in the language is checked.

Failing case

from typing import TypeVar

T = TypeVar("T", bound=str)
Alias = list[T]

def f(x: Alias[int]) -> None: ...   # should error: int does not satisfy bound str

bound is "str", so the _ => true arm accepts. No diagnostic. The same holds for every user-defined class bound, every protocol bound, and every constrained TypeVar (TypeVar("T", str, bytes) — constraints are not consulted here at all; AliasInfo::typevar_bounds only carries bound_type_name).

Note also that arg and bound are compared as strings (bound_type_name is a name, arg is annotation text), so even within the numeric tower this cannot see through an alias, a qualified name, or a subscripted generic.

Fix

Route all bounds — not a hardcoded three — through the real subtyping context, resolving both the argument and the bound to types rather than comparing names. Carry TypeVar constraints alongside bounds and check membership for constrained TypeVars. _ => true must not be the default answer for the rest of the type system.

Needs off-suite regression tests: a bound=str case cannot fail in the conformance suite, because the suite has no such case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    spec-violationCode functionality/logic does not match its spec (see SPEC-CONFORMANCE-AUDIT-PLAN.md)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions