Skip to content

Commit 6217f48

Browse files
committed
red_knot: first attempt at string annotation
This separates the inference of string annotations in the deferred region. But, this creates complications in annotations that are only partially stringified e.g., `tuple[int, "Foo"]` where "Foo" is a forward reference. This commit exists so as to create a checkpoint in case some of the ideas explored here are useful.
1 parent 5c548dc commit 6217f48

File tree

5 files changed

+350
-44
lines changed

5 files changed

+350
-44
lines changed

crates/red_knot_python_semantic/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ license = { workspace = true }
1414
ruff_db = { workspace = true }
1515
ruff_index = { workspace = true }
1616
ruff_python_ast = { workspace = true, features = ["salsa"] }
17+
ruff_python_parser = { workspace = true }
1718
ruff_python_stdlib = { workspace = true }
1819
ruff_source_file = { workspace = true }
1920
ruff_text_size = { workspace = true }

crates/red_knot_python_semantic/src/types.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ mod display;
3535
mod infer;
3636
mod mro;
3737
mod narrow;
38+
mod string_annotation;
3839
mod unpacker;
3940

4041
#[salsa::tracked(return_ref)]
@@ -56,7 +57,7 @@ pub fn check_types(db: &dyn Db, file: File) -> TypeCheckDiagnostics {
5657

5758
/// Infer the public type of a symbol (its type as seen from outside its scope).
5859
fn symbol_by_id<'db>(db: &'db dyn Db, scope: ScopeId<'db>, symbol: ScopedSymbolId) -> Symbol<'db> {
59-
let _span = tracing::trace_span!("symbol_ty_by_id", ?symbol).entered();
60+
let _span = tracing::trace_span!("symbol_by_id", ?symbol).entered();
6061

6162
let use_def = use_def_map(db, scope);
6263

@@ -180,13 +181,21 @@ pub(crate) fn global_symbol<'db>(db: &'db dyn Db, file: File, name: &str) -> Sym
180181
/// Infer the type of a binding.
181182
pub(crate) fn binding_ty<'db>(db: &'db dyn Db, definition: Definition<'db>) -> Type<'db> {
182183
let inference = infer_definition_types(db, definition);
183-
inference.binding_ty(definition)
184+
if inference.is_eagerly_deferred(definition) {
185+
infer_deferred_types(db, definition).binding_ty(definition)
186+
} else {
187+
inference.binding_ty(definition)
188+
}
184189
}
185190

186191
/// Infer the type of a declaration.
187192
fn declaration_ty<'db>(db: &'db dyn Db, definition: Definition<'db>) -> Type<'db> {
188193
let inference = infer_definition_types(db, definition);
189-
inference.declaration_ty(definition)
194+
if inference.is_eagerly_deferred(definition) {
195+
infer_deferred_types(db, definition).declaration_ty(definition)
196+
} else {
197+
inference.declaration_ty(definition)
198+
}
190199
}
191200

192201
/// Infer the type of a (possibly deferred) sub-expression of a [`Definition`].
@@ -2220,6 +2229,21 @@ impl<'db> IterationOutcome<'db> {
22202229
}
22212230
}
22222231

2232+
#[derive(Debug)]
2233+
enum MaybeDeferred<'db> {
2234+
Type(Type<'db>),
2235+
Deferred,
2236+
}
2237+
2238+
impl<'db> MaybeDeferred<'db> {
2239+
fn expect_type(self) -> Type<'db> {
2240+
match self {
2241+
MaybeDeferred::Type(ty) => ty,
2242+
MaybeDeferred::Deferred => panic!("expected a type, but got a deferred annotation"),
2243+
}
2244+
}
2245+
}
2246+
22232247
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
22242248
pub enum Truthiness {
22252249
/// For an object `x`, `bool(x)` will always return `True`

0 commit comments

Comments
 (0)