[ty] Rename non-subscriptable error code to not-subscriptable (#22193)

This commit is contained in:
Simon Lamon
2025-12-27 12:44:35 +01:00
committed by GitHub
parent da188d5cf6
commit c032e27566
17 changed files with 112 additions and 112 deletions

View File

@@ -2005,30 +2005,6 @@ def func(x: bool): ...
func("string") # error: [no-matching-overload]
```
## `non-subscriptable`
<small>
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20non-subscriptable" target="_blank">Related issues</a> ·
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1453" target="_blank">View source</a>
</small>
**What it does**
Checks for subscripting objects that do not support subscripting.
**Why is this bad?**
Subscripting an object that does not support it will raise a `TypeError` at runtime.
**Examples**
```python
4[1] # TypeError: 'int' object is not subscriptable
```
## `not-iterable`
<small>
@@ -2055,6 +2031,30 @@ for i in 34: # TypeError: 'int' object is not iterable
pass
```
## `not-subscriptable`
<small>
Default level: <a href="../../rules#rule-levels" title="This lint has a default level of 'error'."><code>error</code></a> ·
Added in <a href="https://github.com/astral-sh/ty/releases/tag/0.0.1-alpha.1">0.0.1-alpha.1</a> ·
<a href="https://github.com/astral-sh/ty/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20not-subscriptable" target="_blank">Related issues</a> ·
<a href="https://github.com/astral-sh/ruff/blob/main/crates%2Fty_python_semantic%2Fsrc%2Ftypes%2Fdiagnostic.rs#L1453" target="_blank">View source</a>
</small>
**What it does**
Checks for subscripting objects that do not support subscripting.
**Why is this bad?**
Subscripting an object that does not support it will raise a `TypeError` at runtime.
**Examples**
```python
4[1] # TypeError: 'int' object is not subscriptable
```
## `override-of-final-method`
<small>

View File

@@ -149,7 +149,7 @@ fn both_warnings_and_errors() -> anyhow::Result<()> {
"test.py",
r#"
print(x) # [unresolved-reference]
print(4[1]) # [non-subscriptable]
print(4[1]) # [not-subscriptable]
"#,
)?;
@@ -162,18 +162,18 @@ fn both_warnings_and_errors() -> anyhow::Result<()> {
|
2 | print(x) # [unresolved-reference]
| ^
3 | print(4[1]) # [non-subscriptable]
3 | print(4[1]) # [not-subscriptable]
|
info: rule `unresolved-reference` was selected on the command line
error[non-subscriptable]: Cannot subscript object of type `Literal[4]` with no `__getitem__` method
error[not-subscriptable]: Cannot subscript object of type `Literal[4]` with no `__getitem__` method
--> test.py:3:7
|
2 | print(x) # [unresolved-reference]
3 | print(4[1]) # [non-subscriptable]
3 | print(4[1]) # [not-subscriptable]
| ^^^^
|
info: rule `non-subscriptable` is enabled by default
info: rule `not-subscriptable` is enabled by default
Found 2 diagnostics
@@ -189,7 +189,7 @@ fn both_warnings_and_errors_and_error_on_warning_is_true() -> anyhow::Result<()>
"test.py",
r###"
print(x) # [unresolved-reference]
print(4[1]) # [non-subscriptable]
print(4[1]) # [not-subscriptable]
"###,
)?;
@@ -202,18 +202,18 @@ fn both_warnings_and_errors_and_error_on_warning_is_true() -> anyhow::Result<()>
|
2 | print(x) # [unresolved-reference]
| ^
3 | print(4[1]) # [non-subscriptable]
3 | print(4[1]) # [not-subscriptable]
|
info: rule `unresolved-reference` was selected on the command line
error[non-subscriptable]: Cannot subscript object of type `Literal[4]` with no `__getitem__` method
error[not-subscriptable]: Cannot subscript object of type `Literal[4]` with no `__getitem__` method
--> test.py:3:7
|
2 | print(x) # [unresolved-reference]
3 | print(4[1]) # [non-subscriptable]
3 | print(4[1]) # [not-subscriptable]
| ^^^^
|
info: rule `non-subscriptable` is enabled by default
info: rule `not-subscriptable` is enabled by default
Found 2 diagnostics
@@ -229,7 +229,7 @@ fn exit_zero_is_true() -> anyhow::Result<()> {
"test.py",
r#"
print(x) # [unresolved-reference]
print(4[1]) # [non-subscriptable]
print(4[1]) # [not-subscriptable]
"#,
)?;
@@ -242,18 +242,18 @@ fn exit_zero_is_true() -> anyhow::Result<()> {
|
2 | print(x) # [unresolved-reference]
| ^
3 | print(4[1]) # [non-subscriptable]
3 | print(4[1]) # [not-subscriptable]
|
info: rule `unresolved-reference` was selected on the command line
error[non-subscriptable]: Cannot subscript object of type `Literal[4]` with no `__getitem__` method
error[not-subscriptable]: Cannot subscript object of type `Literal[4]` with no `__getitem__` method
--> test.py:3:7
|
2 | print(x) # [unresolved-reference]
3 | print(4[1]) # [non-subscriptable]
3 | print(4[1]) # [not-subscriptable]
| ^^^^
|
info: rule `non-subscriptable` is enabled by default
info: rule `not-subscriptable` is enabled by default
Found 2 diagnostics

View File

@@ -634,7 +634,7 @@ fn concise_diagnostics() -> anyhow::Result<()> {
"test.py",
r#"
print(x) # [unresolved-reference]
print(4[1]) # [non-subscriptable]
print(4[1]) # [not-subscriptable]
"#,
)?;
@@ -643,7 +643,7 @@ fn concise_diagnostics() -> anyhow::Result<()> {
exit_code: 1
----- stdout -----
test.py:2:7: warning[unresolved-reference] Name `x` used when not defined
test.py:3:7: error[non-subscriptable] Cannot subscript object of type `Literal[4]` with no `__getitem__` method
test.py:3:7: error[not-subscriptable] Cannot subscript object of type `Literal[4]` with no `__getitem__` method
Found 2 diagnostics
----- stderr -----
@@ -658,7 +658,7 @@ fn gitlab_diagnostics() -> anyhow::Result<()> {
"test.py",
r#"
print(x) # [unresolved-reference]
print(4[1]) # [non-subscriptable]
print(4[1]) # [not-subscriptable]
from typing_extensions import reveal_type
reveal_type('str'.lower()) # [revealed-type]
"#,
@@ -694,8 +694,8 @@ fn gitlab_diagnostics() -> anyhow::Result<()> {
}
},
{
"check_name": "non-subscriptable",
"description": "non-subscriptable: Cannot subscript object of type `Literal[4]` with no `__getitem__` method",
"check_name": "not-subscriptable",
"description": "not-subscriptable: Cannot subscript object of type `Literal[4]` with no `__getitem__` method",
"severity": "major",
"fingerprint": "[FINGERPRINT]",
"location": {
@@ -744,7 +744,7 @@ fn github_diagnostics() -> anyhow::Result<()> {
"test.py",
r#"
print(x) # [unresolved-reference]
print(4[1]) # [non-subscriptable]
print(4[1]) # [not-subscriptable]
from typing_extensions import reveal_type
reveal_type('str'.lower()) # [revealed-type]
"#,
@@ -755,7 +755,7 @@ fn github_diagnostics() -> anyhow::Result<()> {
exit_code: 1
----- stdout -----
::warning title=ty (unresolved-reference),file=<temp_dir>/test.py,line=2,col=7,endLine=2,endColumn=8::test.py:2:7: unresolved-reference: Name `x` used when not defined
::error title=ty (non-subscriptable),file=<temp_dir>/test.py,line=3,col=7,endLine=3,endColumn=11::test.py:3:7: non-subscriptable: Cannot subscript object of type `Literal[4]` with no `__getitem__` method
::error title=ty (not-subscriptable),file=<temp_dir>/test.py,line=3,col=7,endLine=3,endColumn=11::test.py:3:7: not-subscriptable: Cannot subscript object of type `Literal[4]` with no `__getitem__` method
::notice title=ty (revealed-type),file=<temp_dir>/test.py,line=5,col=13,endLine=5,endColumn=26::test.py:5:13: revealed-type: Revealed type: `LiteralString`
----- stderr -----

View File

@@ -53,7 +53,7 @@ class ClassWithNormalDunder:
def __getitem__(self, key: int) -> str:
return str(key)
# error: [non-subscriptable]
# error: [not-subscriptable]
ClassWithNormalDunder[0]
```
@@ -85,7 +85,7 @@ class ThisFails:
this_fails = ThisFails()
# error: [non-subscriptable] "Cannot subscript object of type `ThisFails` with no `__getitem__` method"
# error: [not-subscriptable] "Cannot subscript object of type `ThisFails` with no `__getitem__` method"
reveal_type(this_fails[0]) # revealed: Unknown
```
@@ -259,8 +259,8 @@ class NotSubscriptable2:
self.__getitem__ = external_getitem
def _(union: NotSubscriptable1 | NotSubscriptable2):
# error: [non-subscriptable] "Cannot subscript object of type `NotSubscriptable2` with no `__getitem__` method"
# error: [non-subscriptable] "Cannot subscript object of type `NotSubscriptable1` with no `__getitem__` method"
# error: [not-subscriptable] "Cannot subscript object of type `NotSubscriptable2` with no `__getitem__` method"
# error: [not-subscriptable] "Cannot subscript object of type `NotSubscriptable1` with no `__getitem__` method"
union[0]
```

View File

@@ -667,6 +667,6 @@ class B(A): ...
reveal_type(A()[0]) # revealed: int
reveal_type(super(B, B()).__getitem__) # revealed: bound method B.__getitem__(key: int) -> int
# error: [non-subscriptable] "Cannot subscript object of type `<super: <class 'B'>, B>` with no `__getitem__` method"
# error: [not-subscriptable] "Cannot subscript object of type `<super: <class 'B'>, B>` with no `__getitem__` method"
super(B, B())[0]
```

View File

@@ -216,7 +216,7 @@ class OnlyDelItem:
d = OnlyDelItem()
del d[0] # OK
# error: [non-subscriptable] "Cannot subscript object of type `OnlyDelItem` with no `__getitem__` method"
# error: [not-subscriptable] "Cannot subscript object of type `OnlyDelItem` with no `__getitem__` method"
d[0]
```
@@ -232,7 +232,7 @@ class OnlyGetItem:
g = OnlyGetItem()
reveal_type(g[0]) # revealed: str
# error: [non-subscriptable] "Cannot delete subscript on object of type `OnlyGetItem` with no `__delitem__` method"
# error: [not-subscriptable] "Cannot delete subscript on object of type `OnlyGetItem` with no `__delitem__` method"
del g[0]
```

View File

@@ -72,32 +72,32 @@ from typing import TypeVar, Protocol, TypedDict
type B = ...
# error: [non-subscriptable] "Cannot subscript non-generic type alias"
# error: [not-subscriptable] "Cannot subscript non-generic type alias"
reveal_type(B[int]) # revealed: Unknown
# error: [non-subscriptable] "Cannot subscript non-generic type alias"
# error: [not-subscriptable] "Cannot subscript non-generic type alias"
def _(b: B[int]):
reveal_type(b) # revealed: Unknown
type IntOrStr = int | str
# error: [non-subscriptable] "Cannot subscript non-generic type alias"
# error: [not-subscriptable] "Cannot subscript non-generic type alias"
def _(c: IntOrStr[int]):
reveal_type(c) # revealed: Unknown
type ListOfInts = list[int]
# error: [non-subscriptable] "Cannot subscript non-generic type alias: `list[int]` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type alias: `list[int]` is already specialized"
def _(l: ListOfInts[int]):
reveal_type(l) # revealed: Unknown
type List[T] = list[T]
# error: [non-subscriptable] "Cannot subscript non-generic type alias: Double specialization is not allowed"
# error: [not-subscriptable] "Cannot subscript non-generic type alias: Double specialization is not allowed"
def _(l: List[int][int]):
reveal_type(l) # revealed: Unknown
# error: [non-subscriptable] "Cannot subscript non-generic type: `<class 'list[T@DoubleSpecialization]'>` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type: `<class 'list[T@DoubleSpecialization]'>` is already specialized"
type DoubleSpecialization[T] = list[T][T]
def _(d: DoubleSpecialization[int]):
@@ -105,7 +105,7 @@ def _(d: DoubleSpecialization[int]):
type Tuple = tuple[int, str]
# error: [non-subscriptable] "Cannot subscript non-generic type alias: `tuple[int, str]` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type alias: `tuple[int, str]` is already specialized"
def _(doubly_specialized: Tuple[int]):
reveal_type(doubly_specialized) # revealed: Unknown
@@ -116,7 +116,7 @@ class LegacyProto(Protocol[T]):
type LegacyProtoInt = LegacyProto[int]
# error: [non-subscriptable] "Cannot subscript non-generic type alias: `LegacyProto[int]` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type alias: `LegacyProto[int]` is already specialized"
def _(x: LegacyProtoInt[int]):
reveal_type(x) # revealed: Unknown
@@ -125,7 +125,7 @@ class Proto[T](Protocol):
type ProtoInt = Proto[int]
# error: [non-subscriptable] "Cannot subscript non-generic type alias: `Proto[int]` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type alias: `Proto[int]` is already specialized"
def _(x: ProtoInt[int]):
reveal_type(x) # revealed: Unknown
@@ -135,7 +135,7 @@ class LegacyDict(TypedDict[T]):
type LegacyDictInt = LegacyDict[int]
# error: [non-subscriptable] "Cannot subscript non-generic type alias"
# error: [not-subscriptable] "Cannot subscript non-generic type alias"
def _(x: LegacyDictInt[int]):
reveal_type(x) # revealed: Unknown
@@ -144,13 +144,13 @@ class Dict[T](TypedDict):
type DictInt = Dict[int]
# error: [non-subscriptable] "Cannot subscript non-generic type alias: `Dict[int]` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type alias: `Dict[int]` is already specialized"
def _(x: DictInt[int]):
reveal_type(x) # revealed: Unknown
type Union = list[str] | list[int]
# error: [non-subscriptable] "Cannot subscript non-generic type alias: `list[str] | list[int]` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type alias: `list[str] | list[int]` is already specialized"
def _(x: Union[int]):
reveal_type(x) # revealed: Unknown
```

View File

@@ -664,18 +664,18 @@ from typing import Protocol, TypeVar, TypedDict
ListOfInts = list[int]
# error: [non-subscriptable] "Cannot subscript non-generic type: `<class 'list[int]'>` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type: `<class 'list[int]'>` is already specialized"
def _(doubly_specialized: ListOfInts[int]):
reveal_type(doubly_specialized) # revealed: Unknown
type ListOfInts2 = list[int]
# error: [non-subscriptable] "Cannot subscript non-generic type alias: `list[int]` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type alias: `list[int]` is already specialized"
DoublySpecialized = ListOfInts2[int]
def _(doubly_specialized: DoublySpecialized):
reveal_type(doubly_specialized) # revealed: Unknown
# error: [non-subscriptable] "Cannot subscript non-generic type: `<class 'list[int]'>` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type: `<class 'list[int]'>` is already specialized"
List = list[int][int]
def _(doubly_specialized: List):
@@ -683,7 +683,7 @@ def _(doubly_specialized: List):
Tuple = tuple[int, str]
# error: [non-subscriptable] "Cannot subscript non-generic type: `<class 'tuple[int, str]'>` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type: `<class 'tuple[int, str]'>` is already specialized"
def _(doubly_specialized: Tuple[int]):
reveal_type(doubly_specialized) # revealed: Unknown
@@ -694,7 +694,7 @@ class LegacyProto(Protocol[T]):
LegacyProtoInt = LegacyProto[int]
# error: [non-subscriptable] "Cannot subscript non-generic type: `<class 'LegacyProto[int]'>` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type: `<class 'LegacyProto[int]'>` is already specialized"
def _(doubly_specialized: LegacyProtoInt[int]):
reveal_type(doubly_specialized) # revealed: Unknown
@@ -703,7 +703,7 @@ class Proto[T](Protocol):
ProtoInt = Proto[int]
# error: [non-subscriptable] "Cannot subscript non-generic type: `<class 'Proto[int]'>` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type: `<class 'Proto[int]'>` is already specialized"
def _(doubly_specialized: ProtoInt[int]):
reveal_type(doubly_specialized) # revealed: Unknown
@@ -711,10 +711,10 @@ def _(doubly_specialized: ProtoInt[int]):
class LegacyDict(TypedDict[T]):
x: T
# TODO: should be a `non-subscriptable` error
# TODO: should be a `not-subscriptable` error
LegacyDictInt = LegacyDict[int]
# TODO: should be a `non-subscriptable` error
# TODO: should be a `not-subscriptable` error
def _(doubly_specialized: LegacyDictInt[int]):
# TODO: should be `Unknown`
reveal_type(doubly_specialized) # revealed: @Todo(Inference of subscript on special form)
@@ -724,20 +724,20 @@ class Dict[T](TypedDict):
DictInt = Dict[int]
# error: [non-subscriptable] "Cannot subscript non-generic type: `<class 'Dict[int]'>` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type: `<class 'Dict[int]'>` is already specialized"
def _(doubly_specialized: DictInt[int]):
reveal_type(doubly_specialized) # revealed: Unknown
Union = list[str] | list[int]
# error: [non-subscriptable] "Cannot subscript non-generic type: `<types.UnionType special-form 'list[str] | list[int]'>` is already specialized"
# error: [not-subscriptable] "Cannot subscript non-generic type: `<types.UnionType special-form 'list[str] | list[int]'>` is already specialized"
def _(doubly_specialized: Union[int]):
reveal_type(doubly_specialized) # revealed: Unknown
type MyListAlias[T] = list[T]
MyListOfInts = MyListAlias[int]
# error: [non-subscriptable] "Cannot subscript non-generic type alias: Double specialization is not allowed"
# error: [not-subscriptable] "Cannot subscript non-generic type alias: Double specialization is not allowed"
def _(doubly_specialized: MyListOfInts[int]):
reveal_type(doubly_specialized) # revealed: Unknown
```
@@ -775,7 +775,7 @@ def this_does_not_work() -> TypeOf[IntOrStr]:
raise NotImplementedError()
def _(
# error: [non-subscriptable] "Cannot subscript non-generic type"
# error: [not-subscriptable] "Cannot subscript non-generic type"
specialized: this_does_not_work()[int],
):
reveal_type(specialized) # revealed: Unknown
@@ -784,7 +784,7 @@ def _(
Similarly, if you try to specialize a union type without a binding context, we emit an error:
```py
# error: [non-subscriptable] "Cannot subscript non-generic type"
# error: [not-subscriptable] "Cannot subscript non-generic type"
x: (list[T] | set[T])[int]
def _():

View File

@@ -247,11 +247,11 @@ does["not"]["exist"] = 0
# error: [unresolved-reference]
reveal_type(does["not"]["exist"]) # revealed: Unknown
non_subscriptable = 1
not_subscriptable = 1
# error: [invalid-assignment]
non_subscriptable[0] = 0
# error: [non-subscriptable]
reveal_type(non_subscriptable[0]) # revealed: Unknown
not_subscriptable[0] = 0
# error: [not-subscriptable]
reveal_type(not_subscriptable[0]) # revealed: Unknown
```
### No narrowing for custom classes with arbitrary `__getitem__` / `__setitem__`

View File

@@ -14,20 +14,20 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/subscript/instance.md
```
1 | class NotSubscriptable: ...
2 |
3 | a = NotSubscriptable()[0] # error: [non-subscriptable]
3 | a = NotSubscriptable()[0] # error: [not-subscriptable]
```
# Diagnostics
```
error[non-subscriptable]: Cannot subscript object of type `NotSubscriptable` with no `__getitem__` method
error[not-subscriptable]: Cannot subscript object of type `NotSubscriptable` with no `__getitem__` method
--> src/mdtest_snippet.py:3:5
|
1 | class NotSubscriptable: ...
2 |
3 | a = NotSubscriptable()[0] # error: [non-subscriptable]
3 | a = NotSubscriptable()[0] # error: [not-subscriptable]
| ^^^^^^^^^^^^^^^^^^^^^
|
info: rule `non-subscriptable` is enabled by default
info: rule `not-subscriptable` is enabled by default
```

View File

@@ -69,7 +69,7 @@ def _(flag: bool):
else:
class Spam: ...
# error: [non-subscriptable] "Cannot subscript object of type `<class 'Spam'>` with no `__class_getitem__` method"
# error: [not-subscriptable] "Cannot subscript object of type `<class 'Spam'>` with no `__class_getitem__` method"
# revealed: str | Unknown
reveal_type(Spam[42])
```

View File

@@ -7,7 +7,7 @@
```py
class NotSubscriptable: ...
a = NotSubscriptable()[0] # error: [non-subscriptable]
a = NotSubscriptable()[0] # error: [not-subscriptable]
```
## `__getitem__` not callable

View File

@@ -416,7 +416,7 @@ def test2(val: tuple[str, None] | list[int | float]):
```py
def test3(val: tuple[str] | tuple[int] | int):
# error: [non-subscriptable] "Cannot subscript object of type `int` with no `__getitem__` method"
# error: [not-subscriptable] "Cannot subscript object of type `int` with no `__getitem__` method"
reveal_type(val[0]) # revealed: str | int | Unknown
```

View File

@@ -94,7 +94,7 @@ pub(crate) fn register_lints(registry: &mut LintRegistryBuilder) {
registry.register_lint(&INVALID_TYPE_VARIABLE_CONSTRAINTS);
registry.register_lint(&MISSING_ARGUMENT);
registry.register_lint(&NO_MATCHING_OVERLOAD);
registry.register_lint(&NON_SUBSCRIPTABLE);
registry.register_lint(&NOT_SUBSCRIPTABLE);
registry.register_lint(&NOT_ITERABLE);
registry.register_lint(&UNSUPPORTED_BOOL_CONVERSION);
registry.register_lint(&PARAMETER_ALREADY_ASSIGNED);
@@ -1461,7 +1461,7 @@ declare_lint! {
/// ```python
/// 4[1] # TypeError: 'int' object is not subscriptable
/// ```
pub(crate) static NON_SUBSCRIPTABLE = {
pub(crate) static NOT_SUBSCRIPTABLE = {
summary: "detects subscripting objects that do not support subscripting",
status: LintStatus::stable("0.0.1-alpha.1"),
default_level: Level::Error,
@@ -2402,24 +2402,24 @@ pub(super) fn report_index_out_of_bounds(
}
/// Emit a diagnostic declaring that a type does not support subscripting.
pub(super) fn report_non_subscriptable(
pub(super) fn report_not_subscriptable(
context: &InferContext,
node: &ast::ExprSubscript,
non_subscriptable_ty: Type,
not_subscriptable_ty: Type,
method: &str,
) {
let Some(builder) = context.report_lint(&NON_SUBSCRIPTABLE, node) else {
let Some(builder) = context.report_lint(&NOT_SUBSCRIPTABLE, node) else {
return;
};
if method == "__delitem__" {
builder.into_diagnostic(format_args!(
"Cannot delete subscript on object of type `{}` with no `{method}` method",
non_subscriptable_ty.display(context.db())
not_subscriptable_ty.display(context.db())
));
} else {
builder.into_diagnostic(format_args!(
"Cannot subscript object of type `{}` with no `{method}` method",
non_subscriptable_ty.display(context.db())
not_subscriptable_ty.display(context.db())
));
}
}

View File

@@ -63,7 +63,7 @@ use crate::types::diagnostic::{
INVALID_LEGACY_TYPE_VARIABLE, INVALID_METACLASS, INVALID_NAMED_TUPLE, INVALID_NEWTYPE,
INVALID_OVERLOAD, INVALID_PARAMETER_DEFAULT, INVALID_PARAMSPEC, INVALID_PROTOCOL,
INVALID_TYPE_ARGUMENTS, INVALID_TYPE_FORM, INVALID_TYPE_GUARD_CALL,
INVALID_TYPE_VARIABLE_CONSTRAINTS, IncompatibleBases, NON_SUBSCRIPTABLE,
INVALID_TYPE_VARIABLE_CONSTRAINTS, IncompatibleBases, NOT_SUBSCRIPTABLE,
POSSIBLY_MISSING_ATTRIBUTE, POSSIBLY_MISSING_IMPLICIT_CALL, POSSIBLY_MISSING_IMPORT,
SUBCLASS_OF_FINAL_CLASS, TypedDictDeleteErrorKind, UNDEFINED_REVEAL, UNRESOLVED_ATTRIBUTE,
UNRESOLVED_GLOBAL, UNRESOLVED_IMPORT, UNRESOLVED_REFERENCE, UNSUPPORTED_OPERATOR,
@@ -80,7 +80,7 @@ use crate::types::diagnostic::{
report_invalid_or_unsupported_base, report_invalid_return_type,
report_invalid_type_checking_constant, report_invalid_type_param_order,
report_named_tuple_field_with_leading_underscore,
report_namedtuple_field_without_default_after_field_with_default, report_non_subscriptable,
report_namedtuple_field_without_default_after_field_with_default, report_not_subscriptable,
report_possibly_missing_attribute, report_possibly_unresolved_reference,
report_rebound_typevar, report_slice_step_size_zero, report_unsupported_augmented_assignment,
report_unsupported_binary_operation, report_unsupported_comparison,
@@ -4372,7 +4372,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
}
}
CallDunderError::MethodNotAvailable => {
report_non_subscriptable(
report_not_subscriptable(
&self.context,
target,
object_ty,
@@ -12191,7 +12191,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
// Type parameter list cannot be empty, so if we reach here, `value_ty` is not a generic type.
if let Some(builder) = self
.context
.report_lint(&NON_SUBSCRIPTABLE, &*subscript.value)
.report_lint(&NOT_SUBSCRIPTABLE, &*subscript.value)
{
let mut diagnostic =
builder.into_diagnostic("Cannot subscript non-generic type");
@@ -12449,7 +12449,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
_,
) if alias.generic_context(db).is_none() => {
debug_assert!(alias.specialization(db).is_none());
if let Some(builder) = self.context.report_lint(&NON_SUBSCRIPTABLE, subscript) {
if let Some(builder) = self.context.report_lint(&NOT_SUBSCRIPTABLE, subscript) {
let value_type = alias.raw_value_type(db);
let mut diagnostic =
builder.into_diagnostic("Cannot subscript non-generic type alias");
@@ -12658,11 +12658,11 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
.as_class_literal()
.is_some_and(|class| class.iter_mro(db, None).contains(&ClassBase::Generic))
{
report_non_subscriptable(context, subscript, value_ty, "__class_getitem__");
report_not_subscriptable(context, subscript, value_ty, "__class_getitem__");
}
} else {
if expr_context != ExprContext::Store {
report_non_subscriptable(context, subscript, value_ty, "__getitem__");
report_not_subscriptable(context, subscript, value_ty, "__getitem__");
}
}

View File

@@ -5,7 +5,7 @@ use super::{DeferredExpressionState, TypeInferenceBuilder};
use crate::FxOrderSet;
use crate::semantic_index::semantic_index;
use crate::types::diagnostic::{
self, INVALID_TYPE_FORM, NON_SUBSCRIPTABLE, report_invalid_argument_number_to_special_form,
self, INVALID_TYPE_FORM, NOT_SUBSCRIPTABLE, report_invalid_argument_number_to_special_form,
report_invalid_arguments_to_callable,
};
use crate::types::generics::bind_typevar;
@@ -921,7 +921,7 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
KnownInstanceType::TypeAliasType(type_alias @ TypeAliasType::PEP695(_)) => {
if type_alias.specialization(self.db()).is_some() {
if let Some(builder) =
self.context.report_lint(&NON_SUBSCRIPTABLE, subscript)
self.context.report_lint(&NOT_SUBSCRIPTABLE, subscript)
{
let mut diagnostic =
builder.into_diagnostic("Cannot subscript non-generic type alias");
@@ -951,7 +951,7 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
self.infer_type_expression(slice);
if let Some(builder) =
self.context.report_lint(&NON_SUBSCRIPTABLE, subscript)
self.context.report_lint(&NOT_SUBSCRIPTABLE, subscript)
{
let value_type = type_alias.raw_value_type(self.db());
let mut diagnostic = builder

12
ty.schema.json generated
View File

@@ -886,9 +886,9 @@
}
]
},
"non-subscriptable": {
"title": "detects subscripting objects that do not support subscripting",
"description": "## What it does\nChecks for subscripting objects that do not support subscripting.\n\n## Why is this bad?\nSubscripting an object that does not support it will raise a `TypeError` at runtime.\n\n## Examples\n```python\n4[1] # TypeError: 'int' object is not subscriptable\n```",
"not-iterable": {
"title": "detects iteration over an object that is not iterable",
"description": "## What it does\nChecks for objects that are not iterable but are used in a context that requires them to be.\n\n## Why is this bad?\nIterating over an object that is not iterable will raise a `TypeError` at runtime.\n\n## Examples\n\n```python\nfor i in 34: # TypeError: 'int' object is not iterable\n pass\n```",
"default": "error",
"oneOf": [
{
@@ -896,9 +896,9 @@
}
]
},
"not-iterable": {
"title": "detects iteration over an object that is not iterable",
"description": "## What it does\nChecks for objects that are not iterable but are used in a context that requires them to be.\n\n## Why is this bad?\nIterating over an object that is not iterable will raise a `TypeError` at runtime.\n\n## Examples\n\n```python\nfor i in 34: # TypeError: 'int' object is not iterable\n pass\n```",
"not-subscriptable": {
"title": "detects subscripting objects that do not support subscripting",
"description": "## What it does\nChecks for subscripting objects that do not support subscripting.\n\n## Why is this bad?\nSubscripting an object that does not support it will raise a `TypeError` at runtime.\n\n## Examples\n```python\n4[1] # TypeError: 'int' object is not subscriptable\n```",
"default": "error",
"oneOf": [
{