mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 13:51:37 +00:00
[red-knot] resolve int/list/dict/set/tuple to builtin type (#12521)
Now that we have builtins available, resolve some simple cases to the right builtin type. We should also adjust the display for types to include their module name; that's not done yet here.
This commit is contained in:
parent
bf23d38a21
commit
4b69271809
2 changed files with 102 additions and 23 deletions
|
@ -43,14 +43,14 @@ pub(crate) fn symbol_ty_by_name<'db>(
|
|||
.unwrap_or(Type::Unbound)
|
||||
}
|
||||
|
||||
/// Shorthand for `symbol_ty` that looks up a module-global symbol in a file.
|
||||
/// Shorthand for `symbol_ty` that looks up a module-global symbol by name in a file.
|
||||
pub(crate) fn global_symbol_ty_by_name<'db>(db: &'db dyn Db, file: File, name: &str) -> Type<'db> {
|
||||
symbol_ty_by_name(db, global_scope(db, file), name)
|
||||
}
|
||||
|
||||
/// Shorthand for `symbol_ty` that looks up a symbol in the builtins.
|
||||
///
|
||||
/// Returns `None` if the builtins module isn't available for some reason.
|
||||
/// Returns `Unbound` if the builtins module isn't available for some reason.
|
||||
pub(crate) fn builtins_symbol_ty_by_name<'db>(db: &'db dyn Db, name: &str) -> Type<'db> {
|
||||
builtins_scope(db)
|
||||
.map(|builtins| symbol_ty_by_name(db, builtins, name))
|
||||
|
|
|
@ -553,7 +553,6 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
pattern,
|
||||
guard,
|
||||
} = case;
|
||||
// TODO infer case patterns; they aren't normal expressions
|
||||
self.infer_match_pattern(pattern);
|
||||
self.infer_optional_expression(guard.as_deref());
|
||||
self.infer_body(body);
|
||||
|
@ -920,10 +919,10 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
let ast::ExprNumberLiteral { range: _, value } = literal;
|
||||
|
||||
match value {
|
||||
ast::Number::Int(n) => {
|
||||
// TODO support big int literals
|
||||
n.as_i64().map(Type::IntLiteral).unwrap_or(Type::Unknown)
|
||||
}
|
||||
ast::Number::Int(n) => n
|
||||
.as_i64()
|
||||
.map(Type::IntLiteral)
|
||||
.unwrap_or_else(|| builtins_symbol_ty_by_name(self.db, "int")),
|
||||
// TODO builtins.float or builtins.complex
|
||||
_ => Type::Unknown,
|
||||
}
|
||||
|
@ -1004,8 +1003,8 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
self.infer_expression(elt);
|
||||
}
|
||||
|
||||
// TODO tuple type
|
||||
Type::Unknown
|
||||
// TODO generic
|
||||
builtins_symbol_ty_by_name(self.db, "tuple")
|
||||
}
|
||||
|
||||
fn infer_list_expression(&mut self, list: &ast::ExprList) -> Type<'db> {
|
||||
|
@ -1019,8 +1018,8 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
self.infer_expression(elt);
|
||||
}
|
||||
|
||||
// TODO list type
|
||||
Type::Unknown
|
||||
// TODO generic
|
||||
builtins_symbol_ty_by_name(self.db, "list")
|
||||
}
|
||||
|
||||
fn infer_set_expression(&mut self, set: &ast::ExprSet) -> Type<'db> {
|
||||
|
@ -1030,8 +1029,8 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
self.infer_expression(elt);
|
||||
}
|
||||
|
||||
// TODO set type
|
||||
Type::Unknown
|
||||
// TODO generic
|
||||
builtins_symbol_ty_by_name(self.db, "set")
|
||||
}
|
||||
|
||||
fn infer_dict_expression(&mut self, dict: &ast::ExprDict) -> Type<'db> {
|
||||
|
@ -1042,8 +1041,8 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
self.infer_expression(&item.value);
|
||||
}
|
||||
|
||||
// TODO dict type
|
||||
Type::Unknown
|
||||
// TODO generic
|
||||
builtins_symbol_ty_by_name(self.db, "dict")
|
||||
}
|
||||
|
||||
fn infer_generator_expression(&mut self, generator: &ast::ExprGenerator) -> Type<'db> {
|
||||
|
@ -1346,23 +1345,19 @@ impl<'db> TypeInferenceBuilder<'db> {
|
|||
ast::Operator::Add => n
|
||||
.checked_add(m)
|
||||
.map(Type::IntLiteral)
|
||||
// TODO builtins.int
|
||||
.unwrap_or(Type::Unknown),
|
||||
.unwrap_or_else(|| builtins_symbol_ty_by_name(self.db, "int")),
|
||||
ast::Operator::Sub => n
|
||||
.checked_sub(m)
|
||||
.map(Type::IntLiteral)
|
||||
// TODO builtins.int
|
||||
.unwrap_or(Type::Unknown),
|
||||
.unwrap_or_else(|| builtins_symbol_ty_by_name(self.db, "int")),
|
||||
ast::Operator::Mult => n
|
||||
.checked_mul(m)
|
||||
.map(Type::IntLiteral)
|
||||
// TODO builtins.int
|
||||
.unwrap_or(Type::Unknown),
|
||||
.unwrap_or_else(|| builtins_symbol_ty_by_name(self.db, "int")),
|
||||
ast::Operator::Div => n
|
||||
.checked_div(m)
|
||||
.map(Type::IntLiteral)
|
||||
// TODO builtins.int
|
||||
.unwrap_or(Type::Unknown),
|
||||
.unwrap_or_else(|| builtins_symbol_ty_by_name(self.db, "int")),
|
||||
ast::Operator::Mod => n
|
||||
.checked_rem(m)
|
||||
.map(Type::IntLiteral)
|
||||
|
@ -2236,6 +2231,90 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn big_int() -> anyhow::Result<()> {
|
||||
let mut db = setup_db();
|
||||
|
||||
db.write_dedented(
|
||||
"/src/a.py",
|
||||
"
|
||||
x = 10_000_000_000_000_000_000
|
||||
",
|
||||
)?;
|
||||
|
||||
assert_public_ty(&db, "/src/a.py", "x", "Literal[int]");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_literal() -> anyhow::Result<()> {
|
||||
let mut db = setup_db();
|
||||
|
||||
db.write_dedented(
|
||||
"/src/a.py",
|
||||
"
|
||||
x = ()
|
||||
",
|
||||
)?;
|
||||
|
||||
// TODO should be a generic type
|
||||
assert_public_ty(&db, "/src/a.py", "x", "Literal[tuple]");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_literal() -> anyhow::Result<()> {
|
||||
let mut db = setup_db();
|
||||
|
||||
db.write_dedented(
|
||||
"/src/a.py",
|
||||
"
|
||||
x = []
|
||||
",
|
||||
)?;
|
||||
|
||||
// TODO should be a generic type
|
||||
assert_public_ty(&db, "/src/a.py", "x", "Literal[list]");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn set_literal() -> anyhow::Result<()> {
|
||||
let mut db = setup_db();
|
||||
|
||||
db.write_dedented(
|
||||
"/src/a.py",
|
||||
"
|
||||
x = {1, 2}
|
||||
",
|
||||
)?;
|
||||
|
||||
// TODO should be a generic type
|
||||
assert_public_ty(&db, "/src/a.py", "x", "Literal[set]");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dict_literal() -> anyhow::Result<()> {
|
||||
let mut db = setup_db();
|
||||
|
||||
db.write_dedented(
|
||||
"/src/a.py",
|
||||
"
|
||||
x = {}
|
||||
",
|
||||
)?;
|
||||
|
||||
// TODO should be a generic type
|
||||
assert_public_ty(&db, "/src/a.py", "x", "Literal[dict]");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn first_public_def<'db>(db: &'db TestDb, file: File, name: &str) -> Definition<'db> {
|
||||
let scope = global_scope(db, file);
|
||||
*use_def_map(db, scope)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue