Skip to content

Commit e6d4d3b

Browse files
committed
No errors for ReadOnly[Required[…]]
1 parent bf21754 commit e6d4d3b

File tree

4 files changed

+30
-8
lines changed

4 files changed

+30
-8
lines changed

crates/ty_python_semantic/resources/mdtest/annotations/unsupported_type_qualifiers.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ def _(
3131
ClassVar # error: [invalid-type-form] "Type qualifier `typing.ClassVar` is not allowed in type expressions (only in annotation expressions)"
3232
| int
3333
),
34-
c: ReadOnly, # error: [invalid-type-form] "Type qualifier `typing.ReadOnly` is not allowed in type expressions (only in annotation expressions, and only with exactly one argument)"
34+
c: (
35+
ReadOnly | int
36+
), # error: [invalid-type-form] "Type qualifier `typing.ReadOnly` is not allowed in type expressions (only in annotation expressions, and only with exactly one argument)"
3537
) -> None:
3638
reveal_type(a) # revealed: Unknown | int
3739
reveal_type(b) # revealed: Unknown | int
38-
reveal_type(c) # revealed: Unknown
40+
reveal_type(c) # revealed: Unknown | int
3941
```
4042

4143
## Inheritance

crates/ty_python_semantic/resources/mdtest/typed_dict.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,20 @@ def _(person: Person, unknown_key: Any):
432432
person[unknown_key] = "Eve"
433433
```
434434

435+
## `ReadOnly`
436+
437+
`ReadOnly` is not supported yet, but this test makes sure that we do not emit any false positive
438+
diagnostics:
439+
440+
```py
441+
from typing_extensions import TypedDict, ReadOnly, Required
442+
443+
class Person(TypedDict, total=False):
444+
id: ReadOnly[Required[int]]
445+
name: str
446+
age: int | None
447+
```
448+
435449
## Methods on `TypedDict`
436450

437451
```py

crates/ty_python_semantic/src/types.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6882,6 +6882,8 @@ bitflags! {
68826882
const REQUIRED = 1 << 3;
68836883
/// `typing_extensions.NotRequired`
68846884
const NOT_REQUIRED = 1 << 4;
6885+
/// `typing_extensions.ReadOnly`
6886+
const READ_ONLY = 1 << 5;
68856887
}
68866888
}
68876889

crates/ty_python_semantic/src/types/infer.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9443,6 +9443,9 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
94439443
Type::SpecialForm(SpecialFormType::NotRequired) => {
94449444
TypeAndQualifiers::new(Type::unknown(), TypeQualifiers::NOT_REQUIRED)
94459445
}
9446+
Type::SpecialForm(SpecialFormType::ReadOnly) => {
9447+
TypeAndQualifiers::new(Type::unknown(), TypeQualifiers::READ_ONLY)
9448+
}
94469449
Type::ClassLiteral(class)
94479450
if class.is_known(self.db(), KnownClass::InitVar) =>
94489451
{
@@ -9521,7 +9524,8 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
95219524
type_qualifier @ (SpecialFormType::ClassVar
95229525
| SpecialFormType::Final
95239526
| SpecialFormType::Required
9524-
| SpecialFormType::NotRequired),
9527+
| SpecialFormType::NotRequired
9528+
| SpecialFormType::ReadOnly),
95259529
) => {
95269530
let arguments = if let ast::Expr::Tuple(tuple) = slice {
95279531
&*tuple.elts
@@ -9546,6 +9550,9 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
95469550
SpecialFormType::NotRequired => {
95479551
type_and_qualifiers.add_qualifier(TypeQualifiers::NOT_REQUIRED);
95489552
}
9553+
SpecialFormType::ReadOnly => {
9554+
type_and_qualifiers.add_qualifier(TypeQualifiers::READ_ONLY);
9555+
}
95499556
_ => unreachable!(),
95509557
}
95519558
type_and_qualifiers
@@ -10832,14 +10839,11 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
1083210839
KnownClass::Deque,
1083310840
),
1083410841

10835-
SpecialFormType::ReadOnly => {
10836-
self.infer_type_expression(arguments_slice);
10837-
todo_type!("`ReadOnly[]` type qualifier")
10838-
}
1083910842
SpecialFormType::ClassVar
1084010843
| SpecialFormType::Final
1084110844
| SpecialFormType::Required
10842-
| SpecialFormType::NotRequired => {
10845+
| SpecialFormType::NotRequired
10846+
| SpecialFormType::ReadOnly => {
1084310847
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
1084410848
let diag = builder.into_diagnostic(format_args!(
1084510849
"Type qualifier `{special_form}` is not allowed in type expressions \

0 commit comments

Comments
 (0)