Skip to content

Commit

Permalink
red-knot: implement unary minus on integer literals (#13114)
Browse files Browse the repository at this point in the history
# Summary

Add support for the first unary operator: negating integer literals. The
resulting type is another integer literal, with the value being the
negated value of the literal. All other types continue to return
`Type::Unknown` for the present, but this is designed to make it easy to
extend easily with other combinations of operator and operand.

Contributes to #12701.

## Test Plan

Add tests with basic negation, including of very large integers and
double negation.
  • Loading branch information
chriskrycho authored Aug 26, 2024
1 parent c8e01d7 commit fe8b152
Showing 1 changed file with 26 additions and 6 deletions.
32 changes: 26 additions & 6 deletions crates/red_knot_python_semantic/src/types/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use salsa::plumbing::AsId;

use ruff_db::files::File;
use ruff_db::parsed::parsed_module;
use ruff_python_ast as ast;
use ruff_python_ast::{self as ast, UnaryOp};
use ruff_python_ast::{AnyNodeRef, ExprContext};
use ruff_text_size::Ranged;

Expand Down Expand Up @@ -1708,14 +1708,14 @@ impl<'db> TypeInferenceBuilder<'db> {
fn infer_unary_expression(&mut self, unary: &ast::ExprUnaryOp) -> Type<'db> {
let ast::ExprUnaryOp {
range: _,
op: _,
op,
operand,
} = unary;

self.infer_expression(operand);

// TODO unary op types
Type::Unknown
match (op, self.infer_expression(operand)) {
(UnaryOp::USub, Type::IntLiteral(value)) => Type::IntLiteral(-value),
_ => Type::Unknown, // TODO other unary op types
}
}

fn infer_binary_expression(&mut self, binary: &ast::ExprBinOp) -> Type<'db> {
Expand Down Expand Up @@ -2296,6 +2296,26 @@ mod tests {
Ok(())
}

#[test]
fn negated_int_literal() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_dedented(
"src/a.py",
"
x = -1
y = -1234567890987654321
z = --987
",
)?;

assert_public_ty(&db, "src/a.py", "x", "Literal[-1]");
assert_public_ty(&db, "src/a.py", "y", "Literal[-1234567890987654321]");
assert_public_ty(&db, "src/a.py", "z", "Literal[987]");

Ok(())
}

#[test]
fn boolean_literal() -> anyhow::Result<()> {
let mut db = setup_db();
Expand Down

0 comments on commit fe8b152

Please sign in to comment.