Skip to content

Commit 40cba5d

Browse files
[red-knot] Cleanup various todo_type!() messages (#15063)
Co-authored-by: Micha Reiser <[email protected]>
1 parent 596d80c commit 40cba5d

File tree

4 files changed

+52
-62
lines changed

4 files changed

+52
-62
lines changed

crates/red_knot_python_semantic/resources/mdtest/annotations/literal_string.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@ qux = (foo, bar)
7373
reveal_type(qux) # revealed: tuple[Literal["foo"], Literal["bar"]]
7474

7575
# TODO: Infer "LiteralString"
76-
reveal_type(foo.join(qux)) # revealed: @Todo(call todo)
76+
reveal_type(foo.join(qux)) # revealed: @Todo(Attribute access on `StringLiteral` types)
7777

7878
template: LiteralString = "{}, {}"
7979
reveal_type(template) # revealed: Literal["{}, {}"]
8080
# TODO: Infer `LiteralString`
81-
reveal_type(template.format(foo, bar)) # revealed: @Todo(call todo)
81+
reveal_type(template.format(foo, bar)) # revealed: @Todo(Attribute access on `StringLiteral` types)
8282
```
8383

8484
### Assignability

crates/red_knot_python_semantic/resources/mdtest/with/async.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ class Manager:
1717

1818
async def test():
1919
async with Manager() as f:
20-
reveal_type(f) # revealed: @Todo(async with statement)
20+
reveal_type(f) # revealed: @Todo(async `with` statement)
2121
```

crates/red_knot_python_semantic/src/types.rs

+22-29
Original file line numberDiff line numberDiff line change
@@ -1458,15 +1458,10 @@ impl<'db> Type<'db> {
14581458
}
14591459

14601460
match self {
1461-
Type::Any => Type::Any.into(),
1462-
Type::Never => {
1463-
// TODO: attribute lookup on Never type
1464-
todo_type!().into()
1465-
}
1466-
Type::Unknown => Type::Unknown.into(),
1461+
Type::Any | Type::Unknown | Type::Todo(_) => self.into(),
1462+
Type::Never => todo_type!("attribute lookup on Never").into(),
14671463
Type::FunctionLiteral(_) => {
1468-
// TODO: attribute lookup on function type
1469-
todo_type!().into()
1464+
todo_type!("Attribute access on `FunctionLiteral` types").into()
14701465
}
14711466
Type::ModuleLiteral(module_ref) => {
14721467
// `__dict__` is a very special member that is never overridden by module globals;
@@ -1581,40 +1576,38 @@ impl<'db> Type<'db> {
15811576
Type::Intersection(_) => {
15821577
// TODO perform the get_member on each type in the intersection
15831578
// TODO return the intersection of those results
1584-
todo_type!().into()
1579+
todo_type!("Attribute access on `Intersection` types").into()
15851580
}
1586-
Type::IntLiteral(_) => {
1587-
// TODO raise error
1588-
todo_type!().into()
1581+
Type::IntLiteral(_) => todo_type!("Attribute access on `IntLiteral` types").into(),
1582+
Type::BooleanLiteral(_) => {
1583+
todo_type!("Attribute access on `BooleanLiteral` types").into()
15891584
}
1590-
Type::BooleanLiteral(_) => todo_type!().into(),
15911585
Type::StringLiteral(_) => {
15921586
// TODO defer to `typing.LiteralString`/`builtins.str` methods
15931587
// from typeshed's stubs
1594-
todo_type!().into()
1588+
todo_type!("Attribute access on `StringLiteral` types").into()
15951589
}
15961590
Type::LiteralString => {
15971591
// TODO defer to `typing.LiteralString`/`builtins.str` methods
15981592
// from typeshed's stubs
1599-
todo_type!().into()
1593+
todo_type!("Attribute access on `LiteralString` types").into()
16001594
}
16011595
Type::BytesLiteral(_) => {
16021596
// TODO defer to Type::Instance(<bytes from typeshed>).member
1603-
todo_type!().into()
1597+
todo_type!("Attribute access on `BytesLiteral` types").into()
16041598
}
16051599
Type::SliceLiteral(_) => {
16061600
// TODO defer to `builtins.slice` methods
1607-
todo_type!().into()
1601+
todo_type!("Attribute access on `SliceLiteral` types").into()
16081602
}
16091603
Type::Tuple(_) => {
16101604
// TODO: implement tuple methods
1611-
todo_type!().into()
1605+
todo_type!("Attribute access on heterogeneous tuple types").into()
16121606
}
16131607
Type::AlwaysTruthy | Type::AlwaysFalsy => {
16141608
// TODO return `Callable[[], Literal[True/False]]` for `__bool__` access
16151609
KnownClass::Object.to_instance(db).member(db, name)
16161610
}
1617-
&todo @ Type::Todo(_) => todo.into(),
16181611
}
16191612
}
16201613

@@ -1819,12 +1812,8 @@ impl<'db> Type<'db> {
18191812
}
18201813
}
18211814

1822-
// `Any` is callable, and its return type is also `Any`.
1823-
Type::Any => CallOutcome::callable(Type::Any),
1824-
1825-
Type::Todo(_) => CallOutcome::callable(todo_type!("call todo")),
1826-
1827-
Type::Unknown => CallOutcome::callable(Type::Unknown),
1815+
// Dynamic types are callable, and the return type is the same dynamic type
1816+
Type::Any | Type::Todo(_) | Type::Unknown => CallOutcome::callable(self),
18281817

18291818
Type::Union(union) => CallOutcome::union(
18301819
self,
@@ -1834,8 +1823,7 @@ impl<'db> Type<'db> {
18341823
.map(|elem| elem.call(db, arg_types)),
18351824
),
18361825

1837-
// TODO: intersection types
1838-
Type::Intersection(_) => CallOutcome::callable(todo_type!()),
1826+
Type::Intersection(_) => CallOutcome::callable(todo_type!("Type::Intersection.call()")),
18391827

18401828
_ => CallOutcome::not_callable(self),
18411829
}
@@ -1936,8 +1924,7 @@ impl<'db> Type<'db> {
19361924
}) => Type::instance(*class),
19371925
Type::SubclassOf(_) => Type::Any,
19381926
Type::Union(union) => union.map(db, |element| element.to_instance(db)),
1939-
// TODO: we can probably do better here: --Alex
1940-
Type::Intersection(_) => todo_type!(),
1927+
Type::Intersection(_) => todo_type!("Type::Intersection.to_instance()"),
19411928
// TODO: calling `.to_instance()` on any of these should result in a diagnostic,
19421929
// since they already indicate that the object is an instance of some kind:
19431930
Type::BooleanLiteral(_)
@@ -2170,6 +2157,12 @@ impl<'db> From<Type<'db>> for Symbol<'db> {
21702157
}
21712158
}
21722159

2160+
impl<'db> From<&Type<'db>> for Symbol<'db> {
2161+
fn from(value: &Type<'db>) -> Self {
2162+
Self::from(*value)
2163+
}
2164+
}
2165+
21732166
/// Error struct providing information on type(s) that were deemed to be invalid
21742167
/// in a type expression context, and the type we should therefore fallback to
21752168
/// for the problematic type expression.

crates/red_knot_python_semantic/src/types/infer.rs

+27-30
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,7 @@ impl<'db> TypeInferenceBuilder<'db> {
14471447
) -> Type<'db> {
14481448
// TODO: Handle async with statements (they use `aenter` and `aexit`)
14491449
if is_async {
1450-
return todo_type!("async with statement");
1450+
return todo_type!("async `with` statement");
14511451
}
14521452

14531453
let context_manager_ty = context_expression_ty.to_meta_type(self.db());
@@ -1680,7 +1680,8 @@ impl<'db> TypeInferenceBuilder<'db> {
16801680
default,
16811681
} = node;
16821682
self.infer_optional_expression(default.as_deref());
1683-
self.add_declaration_with_binding(node.into(), definition, todo_type!(), todo_type!());
1683+
let pep_695_todo = todo_type!("PEP-695 ParamSpec definition types");
1684+
self.add_declaration_with_binding(node.into(), definition, pep_695_todo, pep_695_todo);
16841685
}
16851686

16861687
fn infer_typevartuple_definition(
@@ -1694,7 +1695,8 @@ impl<'db> TypeInferenceBuilder<'db> {
16941695
default,
16951696
} = node;
16961697
self.infer_optional_expression(default.as_deref());
1697-
self.add_declaration_with_binding(node.into(), definition, todo_type!(), todo_type!());
1698+
let pep_695_todo = todo_type!("PEP-695 TypeVarTuple definition types");
1699+
self.add_declaration_with_binding(node.into(), definition, pep_695_todo, pep_695_todo);
16981700
}
16991701

17001702
fn infer_match_statement(&mut self, match_statement: &ast::StmtMatch) {
@@ -1729,7 +1731,11 @@ impl<'db> TypeInferenceBuilder<'db> {
17291731
// against the subject expression type (which we can query via `infer_expression_types`)
17301732
// and extract the type at the `index` position if the pattern matches. This will be
17311733
// similar to the logic in `self.infer_assignment_definition`.
1732-
self.add_binding(pattern.into(), definition, todo_type!());
1734+
self.add_binding(
1735+
pattern.into(),
1736+
definition,
1737+
todo_type!("`match` pattern definition types"),
1738+
);
17331739
}
17341740

17351741
fn infer_match_pattern(&mut self, pattern: &ast::Pattern) {
@@ -2483,8 +2489,7 @@ impl<'db> TypeInferenceBuilder<'db> {
24832489
ast::Expr::YieldFrom(yield_from) => self.infer_yield_from_expression(yield_from),
24842490
ast::Expr::Await(await_expression) => self.infer_await_expression(await_expression),
24852491
ast::Expr::IpyEscapeCommand(_) => {
2486-
// TODO Implement Ipy escape command support
2487-
todo_type!()
2492+
todo_type!("Ipy escape command support")
24882493
}
24892494
};
24902495

@@ -2922,8 +2927,7 @@ impl<'db> TypeInferenceBuilder<'db> {
29222927
self.infer_parameters(parameters);
29232928
}
29242929

2925-
// TODO function type
2926-
todo_type!()
2930+
todo_type!("typing.Callable type")
29272931
}
29282932

29292933
fn infer_call_expression(&mut self, call_expression: &ast::ExprCall) -> Type<'db> {
@@ -2959,11 +2963,8 @@ impl<'db> TypeInferenceBuilder<'db> {
29592963

29602964
fn infer_yield_expression(&mut self, yield_expression: &ast::ExprYield) -> Type<'db> {
29612965
let ast::ExprYield { range: _, value } = yield_expression;
2962-
29632966
self.infer_optional_expression(value.as_deref());
2964-
2965-
// TODO awaitable type
2966-
todo_type!()
2967+
todo_type!("yield expressions")
29672968
}
29682969

29692970
fn infer_yield_from_expression(&mut self, yield_from: &ast::ExprYieldFrom) -> Type<'db> {
@@ -2975,16 +2976,13 @@ impl<'db> TypeInferenceBuilder<'db> {
29752976
.unwrap_with_diagnostic(&self.context, value.as_ref().into());
29762977

29772978
// TODO get type from `ReturnType` of generator
2978-
todo_type!()
2979+
todo_type!("Generic `typing.Generator` type")
29792980
}
29802981

29812982
fn infer_await_expression(&mut self, await_expression: &ast::ExprAwait) -> Type<'db> {
29822983
let ast::ExprAwait { range: _, value } = await_expression;
2983-
29842984
self.infer_expression(value);
2985-
2986-
// TODO awaitable type
2987-
todo_type!()
2985+
todo_type!("generic `typing.Awaitable` type")
29882986
}
29892987

29902988
/// Look up a name reference that isn't bound in the local scope.
@@ -3521,7 +3519,7 @@ impl<'db> TypeInferenceBuilder<'db> {
35213519
(left, Type::BooleanLiteral(bool_value), op) => {
35223520
self.infer_binary_expression_type(left, Type::IntLiteral(i64::from(bool_value)), op)
35233521
}
3524-
_ => Some(todo_type!()), // TODO
3522+
_ => Some(todo_type!("Support for more binary expressions")),
35253523
}
35263524
}
35273525

@@ -4040,10 +4038,9 @@ impl<'db> TypeInferenceBuilder<'db> {
40404038
}
40414039
}
40424040
}
4043-
// TODO: handle more types
40444041
_ => match op {
40454042
ast::CmpOp::Is | ast::CmpOp::IsNot => Ok(KnownClass::Bool.to_instance(self.db())),
4046-
_ => Ok(todo_type!()),
4043+
_ => Ok(todo_type!("Binary comparisons between more types")),
40474044
},
40484045
}
40494046
}
@@ -4795,7 +4792,7 @@ impl<'db> TypeInferenceBuilder<'db> {
47954792
single_element => {
47964793
let single_element_ty = self.infer_type_expression(single_element);
47974794
if element_could_alter_type_of_whole_tuple(single_element, single_element_ty) {
4798-
todo_type!()
4795+
todo_type!("full tuple[...] support")
47994796
} else {
48004797
Type::tuple(self.db(), [single_element_ty])
48014798
}
@@ -5034,39 +5031,39 @@ impl<'db> TypeInferenceBuilder<'db> {
50345031

50355032
KnownInstanceType::ReadOnly => {
50365033
self.infer_type_expression(arguments_slice);
5037-
todo_type!("Required[] type qualifier")
5034+
todo_type!("`ReadOnly[]` type qualifier")
50385035
}
50395036
KnownInstanceType::NotRequired => {
50405037
self.infer_type_expression(arguments_slice);
5041-
todo_type!("NotRequired[] type qualifier")
5038+
todo_type!("`NotRequired[]` type qualifier")
50425039
}
50435040
KnownInstanceType::ClassVar => {
50445041
self.infer_type_expression(arguments_slice);
5045-
todo_type!("ClassVar[] type qualifier")
5042+
todo_type!("`ClassVar[]` type qualifier")
50465043
}
50475044
KnownInstanceType::Final => {
50485045
self.infer_type_expression(arguments_slice);
5049-
todo_type!("Final[] type qualifier")
5046+
todo_type!("`Final[]` type qualifier")
50505047
}
50515048
KnownInstanceType::Required => {
50525049
self.infer_type_expression(arguments_slice);
5053-
todo_type!("Required[] type qualifier")
5050+
todo_type!("`Required[]` type qualifier")
50545051
}
50555052
KnownInstanceType::TypeIs => {
50565053
self.infer_type_expression(arguments_slice);
5057-
todo_type!("TypeIs[] special form")
5054+
todo_type!("`TypeIs[]` special form")
50585055
}
50595056
KnownInstanceType::TypeGuard => {
50605057
self.infer_type_expression(arguments_slice);
5061-
todo_type!("TypeGuard[] special form")
5058+
todo_type!("`TypeGuard[]` special form")
50625059
}
50635060
KnownInstanceType::Concatenate => {
50645061
self.infer_type_expression(arguments_slice);
5065-
todo_type!("Concatenate[] special form")
5062+
todo_type!("`Concatenate[]` special form")
50665063
}
50675064
KnownInstanceType::Unpack => {
50685065
self.infer_type_expression(arguments_slice);
5069-
todo_type!("Unpack[] special form")
5066+
todo_type!("`Unpack[]` special form")
50705067
}
50715068
KnownInstanceType::NoReturn | KnownInstanceType::Never | KnownInstanceType::Any => {
50725069
self.context.report_lint(

0 commit comments

Comments
 (0)