diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs index 9648f8528b..e916c9d50c 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs @@ -3,7 +3,7 @@ use std::str::FromStr; use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; -use ruff_python_ast::{self as ast, Expr, LiteralExpressionRef, UnaryOp}; +use ruff_python_ast::{self as ast, Expr, Int, LiteralExpressionRef, UnaryOp}; use ruff_text_size::{Ranged, TextRange}; use crate::checkers::ast::Checker; @@ -38,7 +38,7 @@ impl LiteralType { LiteralType::Str => ast::ExprStringLiteral::default().into(), LiteralType::Bytes => ast::ExprBytesLiteral::default().into(), LiteralType::Int => ast::ExprNumberLiteral { - value: ast::Number::Int(0.into()), + value: ast::Number::Int(Int::from(0u8)), range: TextRange::default(), } .into(), diff --git a/crates/ruff_python_ast/src/helpers.rs b/crates/ruff_python_ast/src/helpers.rs index eab3d17060..208010a993 100644 --- a/crates/ruff_python_ast/src/helpers.rs +++ b/crates/ruff_python_ast/src/helpers.rs @@ -1582,15 +1582,15 @@ mod tests { ctx: ExprContext::Load, }); let constant_one = Expr::NumberLiteral(ExprNumberLiteral { - value: Number::Int(1.into()), + value: Number::Int(Int::from(1u8)), range: TextRange::default(), }); let constant_two = Expr::NumberLiteral(ExprNumberLiteral { - value: Number::Int(2.into()), + value: Number::Int(Int::from(2u8)), range: TextRange::default(), }); let constant_three = Expr::NumberLiteral(ExprNumberLiteral { - value: Number::Int(3.into()), + value: Number::Int(Int::from(3u8)), range: TextRange::default(), }); let type_var_one = TypeParam::TypeVar(TypeParamTypeVar { diff --git a/crates/ruff_python_ast/src/int.rs b/crates/ruff_python_ast/src/int.rs index 166ee5562f..08f3d39119 100644 --- a/crates/ruff_python_ast/src/int.rs +++ b/crates/ruff_python_ast/src/int.rs @@ -10,7 +10,7 @@ impl FromStr for Int { /// Parse an [`Int`] from a string. fn from_str(s: &str) -> Result { - match s.parse::() { + match s.parse::() { Ok(value) => Ok(Int::small(value)), Err(err) => { if matches!( @@ -31,7 +31,7 @@ impl Int { pub const ONE: Int = Int(Number::Small(1)); /// Create an [`Int`] to represent a value that can be represented as an `i64`. - fn small(value: i64) -> Self { + fn small(value: u64) -> Self { Self(Number::Small(value)) } @@ -49,7 +49,7 @@ impl Int { radix: u32, token: &str, ) -> Result { - match i64::from_str_radix(number, radix) { + match u64::from_str_radix(number, radix) { Ok(value) => Ok(Int::small(value)), Err(err) => { if matches!( @@ -88,6 +88,14 @@ impl Int { } } + /// Return the [`Int`] as an u64, if it can be represented as that data type. + pub const fn as_u64(&self) -> Option { + match &self.0 { + Number::Small(small) => Some(*small), + Number::Big(_) => None, + } + } + /// Return the [`Int`] as an i8, if it can be represented as that data type. pub fn as_i8(&self) -> Option { match &self.0 { @@ -113,9 +121,9 @@ impl Int { } /// Return the [`Int`] as an i64, if it can be represented as that data type. - pub const fn as_i64(&self) -> Option { + pub fn as_i64(&self) -> Option { match &self.0 { - Number::Small(small) => Some(*small), + Number::Small(small) => i64::try_from(*small).ok(), Number::Big(_) => None, } } @@ -177,51 +185,33 @@ impl PartialEq for Int { impl From for Int { fn from(value: u8) -> Self { - Self::small(i64::from(value)) + Self::small(u64::from(value)) } } impl From for Int { fn from(value: u16) -> Self { - Self::small(i64::from(value)) + Self::small(u64::from(value)) } } impl From for Int { fn from(value: u32) -> Self { - Self::small(i64::from(value)) + Self::small(u64::from(value)) } } -impl From for Int { - fn from(value: i8) -> Self { - Self::small(i64::from(value)) - } -} - -impl From for Int { - fn from(value: i16) -> Self { - Self::small(i64::from(value)) - } -} - -impl From for Int { - fn from(value: i32) -> Self { - Self::small(i64::from(value)) - } -} - -impl From for Int { - fn from(value: i64) -> Self { +impl From for Int { + fn from(value: u64) -> Self { Self::small(value) } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] enum Number { - /// A "small" number that can be represented as an `i64`. - Small(i64), - /// A "large" number that cannot be represented as an `i64`. + /// A "small" number that can be represented as an `u64`. + Small(u64), + /// A "large" number that cannot be represented as an `u64`. Big(Box), } diff --git a/crates/ruff_python_parser/src/lexer.rs b/crates/ruff_python_parser/src/lexer.rs index 025295f24c..e220935cf1 100644 --- a/crates/ruff_python_parser/src/lexer.rs +++ b/crates/ruff_python_parser/src/lexer.rs @@ -1777,7 +1777,7 @@ def f(arg=%timeit a = b): #[test] fn test_numbers() { let source = - "0x2f 0o12 0b1101 0 123 123_45_67_890 0.2 1e+2 2.1e3 2j 2.2j 000 0x995DC9BBDF1939FA"; + "0x2f 0o12 0b1101 0 123 123_45_67_890 0.2 1e+2 2.1e3 2j 2.2j 000 0x995DC9BBDF1939FA 0x995DC9BBDF1939FA995DC9BBDF1939FA"; assert_debug_snapshot!(lex_source(source)); } diff --git a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__numbers.snap b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__numbers.snap index f9a7a988b1..92bc661965 100644 --- a/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__numbers.snap +++ b/crates/ruff_python_parser/src/snapshots/ruff_python_parser__lexer__tests__numbers.snap @@ -79,12 +79,18 @@ expression: lex_source(source) ), ( Int { - value: 0x995DC9BBDF1939FA, + value: 11051210869376104954, }, 64..82, ), + ( + Int { + value: 0x995DC9BBDF1939FA995DC9BBDF1939FA, + }, + 83..117, + ), ( Newline, - 82..82, + 117..117, ), ]