Use u64 instead of i64 in Int type (#11356)

## Summary

I believe the value here is always unsigned, since we represent `-42` as
a unary operator on `42`.
This commit is contained in:
Charlie Marsh 2024-05-10 09:35:15 -04:00 committed by GitHub
parent 1f794077ec
commit 35ba3c91ce
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 35 additions and 39 deletions

View file

@ -3,7 +3,7 @@ use std::str::FromStr;
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation}; 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 ruff_text_size::{Ranged, TextRange};
use crate::checkers::ast::Checker; use crate::checkers::ast::Checker;
@ -38,7 +38,7 @@ impl LiteralType {
LiteralType::Str => ast::ExprStringLiteral::default().into(), LiteralType::Str => ast::ExprStringLiteral::default().into(),
LiteralType::Bytes => ast::ExprBytesLiteral::default().into(), LiteralType::Bytes => ast::ExprBytesLiteral::default().into(),
LiteralType::Int => ast::ExprNumberLiteral { LiteralType::Int => ast::ExprNumberLiteral {
value: ast::Number::Int(0.into()), value: ast::Number::Int(Int::from(0u8)),
range: TextRange::default(), range: TextRange::default(),
} }
.into(), .into(),

View file

@ -1582,15 +1582,15 @@ mod tests {
ctx: ExprContext::Load, ctx: ExprContext::Load,
}); });
let constant_one = Expr::NumberLiteral(ExprNumberLiteral { let constant_one = Expr::NumberLiteral(ExprNumberLiteral {
value: Number::Int(1.into()), value: Number::Int(Int::from(1u8)),
range: TextRange::default(), range: TextRange::default(),
}); });
let constant_two = Expr::NumberLiteral(ExprNumberLiteral { let constant_two = Expr::NumberLiteral(ExprNumberLiteral {
value: Number::Int(2.into()), value: Number::Int(Int::from(2u8)),
range: TextRange::default(), range: TextRange::default(),
}); });
let constant_three = Expr::NumberLiteral(ExprNumberLiteral { let constant_three = Expr::NumberLiteral(ExprNumberLiteral {
value: Number::Int(3.into()), value: Number::Int(Int::from(3u8)),
range: TextRange::default(), range: TextRange::default(),
}); });
let type_var_one = TypeParam::TypeVar(TypeParamTypeVar { let type_var_one = TypeParam::TypeVar(TypeParamTypeVar {

View file

@ -10,7 +10,7 @@ impl FromStr for Int {
/// Parse an [`Int`] from a string. /// Parse an [`Int`] from a string.
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.parse::<i64>() { match s.parse::<u64>() {
Ok(value) => Ok(Int::small(value)), Ok(value) => Ok(Int::small(value)),
Err(err) => { Err(err) => {
if matches!( if matches!(
@ -31,7 +31,7 @@ impl Int {
pub const ONE: Int = Int(Number::Small(1)); pub const ONE: Int = Int(Number::Small(1));
/// Create an [`Int`] to represent a value that can be represented as an `i64`. /// 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)) Self(Number::Small(value))
} }
@ -49,7 +49,7 @@ impl Int {
radix: u32, radix: u32,
token: &str, token: &str,
) -> Result<Self, std::num::ParseIntError> { ) -> Result<Self, std::num::ParseIntError> {
match i64::from_str_radix(number, radix) { match u64::from_str_radix(number, radix) {
Ok(value) => Ok(Int::small(value)), Ok(value) => Ok(Int::small(value)),
Err(err) => { Err(err) => {
if matches!( 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<u64> {
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. /// Return the [`Int`] as an i8, if it can be represented as that data type.
pub fn as_i8(&self) -> Option<i8> { pub fn as_i8(&self) -> Option<i8> {
match &self.0 { match &self.0 {
@ -113,9 +121,9 @@ impl Int {
} }
/// Return the [`Int`] as an i64, if it can be represented as that data type. /// Return the [`Int`] as an i64, if it can be represented as that data type.
pub const fn as_i64(&self) -> Option<i64> { pub fn as_i64(&self) -> Option<i64> {
match &self.0 { match &self.0 {
Number::Small(small) => Some(*small), Number::Small(small) => i64::try_from(*small).ok(),
Number::Big(_) => None, Number::Big(_) => None,
} }
} }
@ -177,51 +185,33 @@ impl PartialEq<i64> for Int {
impl From<u8> for Int { impl From<u8> for Int {
fn from(value: u8) -> Self { fn from(value: u8) -> Self {
Self::small(i64::from(value)) Self::small(u64::from(value))
} }
} }
impl From<u16> for Int { impl From<u16> for Int {
fn from(value: u16) -> Self { fn from(value: u16) -> Self {
Self::small(i64::from(value)) Self::small(u64::from(value))
} }
} }
impl From<u32> for Int { impl From<u32> for Int {
fn from(value: u32) -> Self { fn from(value: u32) -> Self {
Self::small(i64::from(value)) Self::small(u64::from(value))
} }
} }
impl From<i8> for Int { impl From<u64> for Int {
fn from(value: i8) -> Self { fn from(value: u64) -> Self {
Self::small(i64::from(value))
}
}
impl From<i16> for Int {
fn from(value: i16) -> Self {
Self::small(i64::from(value))
}
}
impl From<i32> for Int {
fn from(value: i32) -> Self {
Self::small(i64::from(value))
}
}
impl From<i64> for Int {
fn from(value: i64) -> Self {
Self::small(value) Self::small(value)
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum Number { enum Number {
/// A "small" number that can be represented as an `i64`. /// A "small" number that can be represented as an `u64`.
Small(i64), Small(u64),
/// A "large" number that cannot be represented as an `i64`. /// A "large" number that cannot be represented as an `u64`.
Big(Box<str>), Big(Box<str>),
} }

View file

@ -1777,7 +1777,7 @@ def f(arg=%timeit a = b):
#[test] #[test]
fn test_numbers() { fn test_numbers() {
let source = 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)); assert_debug_snapshot!(lex_source(source));
} }

View file

@ -79,12 +79,18 @@ expression: lex_source(source)
), ),
( (
Int { Int {
value: 0x995DC9BBDF1939FA, value: 11051210869376104954,
}, },
64..82, 64..82,
), ),
(
Int {
value: 0x995DC9BBDF1939FA995DC9BBDF1939FA,
},
83..117,
),
( (
Newline, Newline,
82..82, 117..117,
), ),
] ]