Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,10 @@ class Foo:

d = {}
d[0]: int | str = 42

# these are still errors: `from __future__ import annotations`
# only stringifies *type annotations*, not arbitrary runtime expressions

X = str | int # error: [unsupported-operator]
Y = tuple[str | int, ...] # error: [unsupported-operator]
```
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ error[unsupported-operator]: Unsupported `|` operation
| | Has type `<class 'str'>`
| Has type `<class 'int'>`
|
info: Note that `X | Y` PEP 604 union syntax is only available in Python 3.10 and later
info: PEP 604 `|` unions are only available on Python 3.10+ unless they are quoted
info: Python 3.9 was assumed when resolving types because it was specified on the command line
info: rule `unsupported-operator` is enabled by default

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/annotations/union.md
8 |
9 | d = {}
10 | d[0]: int | str = 42
11 |
12 | # these are still errors: `from __future__ import annotations`
13 | # only stringifies *type annotations*, not arbitrary runtime expressions
14 |
15 | X = str | int # error: [unsupported-operator]
16 | Y = tuple[str | int, ...] # error: [unsupported-operator]
```

# Diagnostics
Expand All @@ -53,7 +59,7 @@ error[unsupported-operator]: Unsupported `|` operation
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: Python 3.9 was assumed when resolving types because it was specified on the command line
info: rule `unsupported-operator` is enabled by default

```
Expand All @@ -73,7 +79,7 @@ error[unsupported-operator]: Unsupported `|` operation
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: Python 3.9 was assumed when resolving types because it was specified on the command line
info: rule `unsupported-operator` is enabled by default

```
Expand All @@ -90,7 +96,45 @@ error[unsupported-operator]: Unsupported `|` operation
| Has type `<class 'int'>`
|
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: Python 3.9 was assumed when resolving types because it was specified on the command line
info: rule `unsupported-operator` is enabled by default

```

```
error[unsupported-operator]: Unsupported `|` operation
--> src/b.py:15:5
|
13 | # only stringifies *type annotations*, not arbitrary runtime expressions
14 |
15 | X = str | int # error: [unsupported-operator]
| ---^^^---
| | |
| | Has type `<class 'int'>`
| Has type `<class 'str'>`
16 | Y = tuple[str | int, ...] # error: [unsupported-operator]
|
info: PEP 604 `|` unions are only available on Python 3.10+ unless they are quoted
info: `from __future__ import annotations` has no effect outside type annotations
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@marcofrasvda, would this have helped make the error clearer for you? "outside type annotations" feels like it might not be clear to everybody, because some folks might think of type alias definitions as being "inside type annotations". Not sure I can think of a better formulation, though, and this diagnostic is already pretty verbose

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah now that I better understand the issue I get that it's not easy to make the error more clear. I think the "has no effect outside" part in the last line is a good indicator that importing annotations might not have the effect the user expects.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A different wording might be "this use of type annotations is not covered by from __future__ import annotation" so it makes a comment about the specific usage rather than a generic statement, but I'm not sure it's better then what you wrote, I guess the next person to encounter this issue might have a better idea :)
Thanks!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no problem! Thanks for the report -- it's important to us for our diagnostics to be clear and helpful :-)

info: Python 3.9 was assumed when resolving types because it was specified on the command line
info: rule `unsupported-operator` is enabled by default

```

```
error[unsupported-operator]: Unsupported `|` operation
--> src/b.py:16:11
|
15 | X = str | int # error: [unsupported-operator]
16 | Y = tuple[str | int, ...] # error: [unsupported-operator]
| ---^^^---
| | |
| | Has type `<class 'int'>`
| Has type `<class 'str'>`
|
info: PEP 604 `|` unions are only available on Python 3.10+ unless they are quoted
info: `from __future__ import annotations` has no effect outside type annotations
info: Python 3.9 was assumed when resolving types because it was specified on the command line
info: rule `unsupported-operator` is enabled by default

```
21 changes: 16 additions & 5 deletions crates/ty_python_semantic/src/types/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::lint::{Level, LintRegistryBuilder, LintStatus};
use crate::place::{DefinedPlace, Place};
use crate::semantic_index::definition::{Definition, DefinitionKind};
use crate::semantic_index::place::{PlaceTable, ScopedPlaceId};
use crate::semantic_index::{global_scope, place_table, use_def_map};
use crate::semantic_index::{SemanticIndex, global_scope, place_table, use_def_map};
use crate::suppression::FileSuppressionId;
use crate::types::call::CallError;
use crate::types::class::{CodeGeneratorKind, DisjointBase, DisjointBaseKind, MethodDecorator};
Expand Down Expand Up @@ -5699,6 +5699,7 @@ pub(super) fn report_unsupported_augmented_assignment<'db>(

pub(super) fn report_unsupported_binary_operation<'db>(
context: &InferContext<'db, '_>,
index: &SemanticIndex<'db>,
binary_expression: &ast::ExprBinOp,
left_ty: Type<'db>,
right_ty: Type<'db>,
Expand All @@ -5724,11 +5725,21 @@ pub(super) fn report_unsupported_binary_operation<'db>(
|| right_ty.is_subtype_of(db, KnownClass::Type.to_instance(db)))
&& Program::get(db).python_version(db) < PythonVersion::PY310
{
diagnostic.info(
"Note that `X | Y` PEP 604 union syntax is only available in Python 3.10 and later",
);
add_inferred_python_version_hint_to_diagnostic(db, &mut diagnostic, "resolving types");
note_py_version_too_old_for_pep_604(db, index, &mut diagnostic);
}
}

pub(super) fn note_py_version_too_old_for_pep_604<'db>(
db: &'db dyn Db,
index: &SemanticIndex<'db>,
diagnostic: &mut Diagnostic,
) {
diagnostic.info("PEP 604 `|` unions are only available on Python 3.10+ unless they are quoted");
if index.has_future_annotations() {
diagnostic
.info("`from __future__ import annotations` has no effect outside type annotations");
}
add_inferred_python_version_hint_to_diagnostic(db, diagnostic, "resolving types");
}

#[derive(Debug, Copy, Clone)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,14 @@ impl<'db> TypeInferenceBuilder<'db, '_> {

self.infer_binary_expression_type(binary.into(), false, left_ty, right_ty, *op)
.unwrap_or_else(|| {
report_unsupported_binary_operation(&self.context, binary, left_ty, right_ty, *op);
report_unsupported_binary_operation(
&self.context,
self.index,
binary,
left_ty,
right_ty,
*op,
);
Type::unknown()
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use super::{DeferredExpressionState, TypeInferenceBuilder};
use crate::semantic_index::scope::ScopeKind;
use crate::types::diagnostic::{
self, INVALID_TYPE_FORM, NOT_SUBSCRIPTABLE, UNBOUND_TYPE_VARIABLE, UNSUPPORTED_OPERATOR,
report_invalid_argument_number_to_special_form, report_invalid_arguments_to_callable,
note_py_version_too_old_for_pep_604, report_invalid_argument_number_to_special_form,
report_invalid_arguments_to_callable,
};
use crate::types::infer::InferenceFlags;
use crate::types::infer::builder::{InnerExpressionInferenceState, MultiInferenceState};
Expand Down Expand Up @@ -264,14 +265,10 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
&& !binary.left.is_string_literal_expr()
&& !binary.right.is_string_literal_expr()
{
diagnostic.info(
"PEP 604 `|` unions are only available on \
Python 3.10+ unless they are quoted",
);
add_inferred_python_version_hint_to_diagnostic(
note_py_version_too_old_for_pep_604(
self.db(),
self.index,
&mut diagnostic,
"inferring types",
);
} else if python_version < PythonVersion::PY314 {
diagnostic.info(
Expand Down
Loading