Skip to content

Non-regular recursive alias rejection uses the wrong rule code and misleading wording (should be an opt-in house rule) #383

Description

@MelbourneDeveloper

Summary

Non-terminating (non-regular / polymorphic) recursive type aliases are reported under generics_syntax_scoping with the message "Circular type alias definition". Rejecting them is a defensible engineering decision, but the code and the wording are both wrong, and neither is backed by the typing spec.

This is filed as a house-rule / diagnostic-quality issue, explicitly not a conformance issue.

Found via the "type torture" puzzle on X: https://x.com/charliermarsh/status/2082885991686090885

Current behaviour

type R[T] = set[R[T | R[T]]]
error[generics_syntax_scoping]: Circular type alias definition: `R` references itself with different type arguments
  --> t.py:2:6
   = help: Recursive type aliases must reference themselves with the same type parameters
   = see: https://www.basilisk-python.dev/errors/generics_syntax_scoping

Three problems

1. It is not a scoping error. generics_syntax_scoping is the bucket for PEP 695 scoping rules. Nothing here is out of scope — the alias resolves fine, it just does not have a finite normal form. Sharing a code with an unrelated rule makes the diagnostic un-configurable and un-searchable, and it distorts the meaning of the generics_syntax_scoping code for users who suppress or route it.

2. "Circular" is the wrong word. Plain circularity is legal and widely supported — PEP 695 formally mandates that recursive type aliases work, and every major checker supports them. Telling a user their recursive alias is "circular" implies recursion itself is the problem. The actual property is that expansion does not terminate: each expansion of R[T] grows its own type argument, so there is no fixed point.

3. The help text states a rule that is stricter than what is enforced. "Recursive type aliases must reference themselves with the same type parameters" is not a spec rule, and it is not even what the checker does — it is a description of the workaround.

Proposal

Give it its own opt-in house rule, separate from the PEP conformance set:

  • Code: something like non-regular-recursive-alias (BSK-xxxx), registered as an opinionated rule per [CHKARCH-CONFIGURATION-ONLY], since no PEP requires it.
  • Message: "type alias R expands infinitely: each expansion of R[T] grows its type argument, so the alias has no finite form".
  • Help: point at the fix — introduce a named intermediate alias, or drop the growing argument — rather than restating a rule that does not exist.
  • Docs page: a real /errors/BSK-xxxx entry explaining non-regular recursion, so the see: link answers the question the diagnostic raises.

Spec position

The typing spec's aliases chapter says nothing about recursive aliases at all, let alone banning non-regular ones; its only explicit type-statement errors are non-annotation expression forms and use of legacy TypeVars. So this diagnostic is Basilisk policy, and it should be labelled and configured as policy.

Related

The inverse defect — legal recursive aliases being rejected by the same rule — is #371, and is a genuine conformance-grade false positive. That one must be fixed regardless of what happens to this one. Splitting the codes makes both tractable: one rule for "this recursion does not terminate" (opt-in policy), and no diagnostic at all for ordinary recursion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions