Skip to content

Union[('A', 'B')] resolves strings as Literal["A"] instead of the actual type — causing false E1002/E1053 errors #6111

@ThiruvarankanM

Description

@ThiruvarankanM

Description

When a type alias is defined using Union[] with string names (forward references), the type checker misreads those strings as plain text values instead of class names. This floods the output with false type errors.


Minimal Reproducible Example

import from typing { Union }

glob MyType = Union[('Foo', 'Bar')];

obj Foo {}
obj Bar {}

def make -> MyType {
    return Foo();  # Should be fine — Foo is a valid member of MyType
}

Expected: No errors. Foo is a valid member of MyType.

Actual:

error[E1002]: Cannot return Foo, expected Literal["Foo"] | Literal["Bar"]

Root Cause

The type checker evaluates each string inside Union[(...)] using get_type_of_expression. When called on a plain string like 'Foo' outside a type-annotation position, it returns Literal["Foo"] (the text) — not the Foo class.

So Union[('Foo', 'Bar')] becomes Literal["Foo"] | Literal["Bar"] instead of Foo | Bar.

The function _try_resolve_forward_ref already exists to resolve string names to real types — it is used correctly for has x: 'Foo' and -> 'Foo' annotations — but it was never called inside the Union[] handler.


Real-World Impact

This pattern is used in doc_ir.jac:

glob DocType = Union[
    ('Doc', 'Text', 'Line', 'Group', 'Indent', 'Concat', 'IfBreak', 'Align')
];

Because DocType resolves to string literals instead of actual classes, every method in doc_ir_gen_pass.impl.jac that uses DocType as a return type or parameter type gets flagged:

error[E1002]: Cannot return Concat, expected Literal["Doc"] | Literal["Text"] | ...
error[E1053]: Cannot assign Text to parameter of type Literal["Doc"] | Literal["Text"] | ...

~1,440 false errors in a single file — all from one misread.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions