diff --git a/crates/ty_python_semantic/resources/mdtest/annotations/string.md b/crates/ty_python_semantic/resources/mdtest/annotations/string.md index ca1994513d090..4ea46898475ba 100644 --- a/crates/ty_python_semantic/resources/mdtest/annotations/string.md +++ b/crates/ty_python_semantic/resources/mdtest/annotations/string.md @@ -170,7 +170,12 @@ from __future__ import annotations def f(v: int | "Foo"): # fine reveal_type(v) # revealed: int | Foo -class Foo: ... +class Foo: + def __init__(self): + self.x: "int" | "str" = 42 + +d = {} +d[0]: "int" | "str" = 42 # error: [unsupported-operator] X = list["int" | None] diff --git a/crates/ty_python_semantic/resources/mdtest/annotations/union.md b/crates/ty_python_semantic/resources/mdtest/annotations/union.md index 8313d7142a65d..1fc2ba5f7072b 100644 --- a/crates/ty_python_semantic/resources/mdtest/annotations/union.md +++ b/crates/ty_python_semantic/resources/mdtest/annotations/union.md @@ -83,3 +83,45 @@ X = int | str def f(y: X): reveal_type(y) # revealed: int | str ``` + +## Diagnostics for PEP-604 unions used on Python less than 3.10 + + + +PEP-604 unions generally don't work on Python \<=3.9: + +```toml +[environment] +python-version = "3.9" +``` + +`a.py`: + +```py +x: int | str # error: [unsupported-operator] + +class Foo: + def __init__(self): + self.x: int | str = 42 # error: [unsupported-operator] + +d = {} +d[0]: int | str = 42 # error: [unsupported-operator] +``` + +But these runtime errors can be avoided if you add `from __future__ import annotations` to the top +of your file: + +`b.py`: + +```py +from __future__ import annotations + +x: int | str + +class Foo: + def __init__(self): + self.x: int | str = 42 + +d = {} +d[0]: int | str = 42 +``` diff --git "a/crates/ty_python_semantic/resources/mdtest/snapshots/union.md_-_Union_-_Diagnostics_for_PEP-\342\200\246_(8fa61a3cfe810040).snap" "b/crates/ty_python_semantic/resources/mdtest/snapshots/union.md_-_Union_-_Diagnostics_for_PEP-\342\200\246_(8fa61a3cfe810040).snap" new file mode 100644 index 0000000000000..f8754cd1ff5d3 --- /dev/null +++ "b/crates/ty_python_semantic/resources/mdtest/snapshots/union.md_-_Union_-_Diagnostics_for_PEP-\342\200\246_(8fa61a3cfe810040).snap" @@ -0,0 +1,96 @@ +--- +source: crates/ty_test/src/lib.rs +expression: snapshot +--- + +--- +mdtest name: union.md - Union - Diagnostics for PEP-604 unions used on Python less than 3.10 +mdtest path: crates/ty_python_semantic/resources/mdtest/annotations/union.md +--- + +# Python source files + +## a.py + +``` +1 | x: int | str # error: [unsupported-operator] +2 | +3 | class Foo: +4 | def __init__(self): +5 | self.x: int | str = 42 # error: [unsupported-operator] +6 | +7 | d = {} +8 | d[0]: int | str = 42 # error: [unsupported-operator] +``` + +## b.py + +``` + 1 | from __future__ import annotations + 2 | + 3 | x: int | str + 4 | + 5 | class Foo: + 6 | def __init__(self): + 7 | self.x: int | str = 42 + 8 | + 9 | d = {} +10 | d[0]: int | str = 42 +``` + +# Diagnostics + +``` +error[unsupported-operator]: Unsupported `|` operation + --> src/a.py:1:4 + | +1 | x: int | str # error: [unsupported-operator] + | ---^^^--- + | | | + | | Has type `` + | Has type `` +2 | +3 | class Foo: + | +info: PEP 604 `|` unions are only available on Python 3.10+ unless they are quoted +info: Python 3.9 was assumed when inferring types because it was specified on the command line +info: rule `unsupported-operator` is enabled by default + +``` + +``` +error[unsupported-operator]: Unsupported `|` operation + --> src/a.py:5:17 + | +3 | class Foo: +4 | def __init__(self): +5 | self.x: int | str = 42 # error: [unsupported-operator] + | ---^^^--- + | | | + | | Has type `` + | Has type `` +6 | +7 | d = {} + | +info: PEP 604 `|` unions are only available on Python 3.10+ unless they are quoted +info: Python 3.9 was assumed when inferring types because it was specified on the command line +info: rule `unsupported-operator` is enabled by default + +``` + +``` +error[unsupported-operator]: Unsupported `|` operation + --> src/a.py:8:7 + | +7 | d = {} +8 | d[0]: int | str = 42 # error: [unsupported-operator] + | ---^^^--- + | | | + | | Has type `` + | Has type `` + | +info: PEP 604 `|` unions are only available on Python 3.10+ unless they are quoted +info: Python 3.9 was assumed when inferring types because it was specified on the command line +info: rule `unsupported-operator` is enabled by default + +``` diff --git a/crates/ty_python_semantic/src/types/infer/builder.rs b/crates/ty_python_semantic/src/types/infer/builder.rs index a146a74e32148..3be5d323519f3 100644 --- a/crates/ty_python_semantic/src/types/infer/builder.rs +++ b/crates/ty_python_semantic/src/types/infer/builder.rs @@ -3780,8 +3780,10 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> { target, simple: _, } = assignment; - let annotated = - self.infer_annotation_expression(annotation, DeferredExpressionState::None); + let annotated = self.infer_annotation_expression( + annotation, + DeferredExpressionState::from(self.defer_annotations()), + ); if !annotated.qualifiers.is_empty() { for qualifier in [TypeQualifiers::CLASS_VAR, TypeQualifiers::INIT_VAR] {