mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-27 23:20:39 +00:00
Auto merge of #102944 - nnethercote:ast-Lit-third-time-lucky, r=petrochenkov
Use `token::Lit` in `ast::ExprKind::Lit`. Instead of `ast::Lit`. Literal lowering now happens at two different times. Expression literals are lowered when HIR is crated. Attribute literals are lowered during parsing. r? `@petrochenkov`
This commit is contained in:
commit
cbd6159095
12 changed files with 90 additions and 77 deletions
|
@ -73,12 +73,21 @@ impl EarlyLintPass for AlmostCompleteLetterRange {
|
|||
}
|
||||
|
||||
fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg: Option<(Span, &str)>) {
|
||||
if let ExprKind::Lit(start_lit) = &start.peel_parens().kind
|
||||
&& let ExprKind::Lit(end_lit) = &end.peel_parens().kind
|
||||
if let ExprKind::Lit(start_token_lit) = start.peel_parens().kind
|
||||
&& let ExprKind::Lit(end_token_lit) = end.peel_parens().kind
|
||||
&& matches!(
|
||||
(&start_lit.kind, &end_lit.kind),
|
||||
(LitKind::Byte(b'a') | LitKind::Char('a'), LitKind::Byte(b'z') | LitKind::Char('z'))
|
||||
| (LitKind::Byte(b'A') | LitKind::Char('A'), LitKind::Byte(b'Z') | LitKind::Char('Z'))
|
||||
(
|
||||
LitKind::from_token_lit(start_token_lit),
|
||||
LitKind::from_token_lit(end_token_lit),
|
||||
),
|
||||
(
|
||||
Ok(LitKind::Byte(b'a') | LitKind::Char('a')),
|
||||
Ok(LitKind::Byte(b'z') | LitKind::Char('z'))
|
||||
)
|
||||
| (
|
||||
Ok(LitKind::Byte(b'A') | LitKind::Char('A')),
|
||||
Ok(LitKind::Byte(b'Z') | LitKind::Char('Z')),
|
||||
)
|
||||
)
|
||||
&& !in_external_macro(cx.sess(), span)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, Lit, LitKind};
|
||||
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind};
|
||||
use rustc_ast::token;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
@ -52,8 +53,8 @@ enum Side {
|
|||
|
||||
impl IntPlusOne {
|
||||
#[expect(clippy::cast_sign_loss)]
|
||||
fn check_lit(lit: &Lit, target_value: i128) -> bool {
|
||||
if let LitKind::Int(value, ..) = lit.kind {
|
||||
fn check_lit(token_lit: token::Lit, target_value: i128) -> bool {
|
||||
if let Ok(LitKind::Int(value, ..)) = LitKind::from_token_lit(token_lit) {
|
||||
return value == (target_value as u128);
|
||||
}
|
||||
false
|
||||
|
@ -65,11 +66,11 @@ impl IntPlusOne {
|
|||
(BinOpKind::Ge, &ExprKind::Binary(ref lhskind, ref lhslhs, ref lhsrhs), _) => {
|
||||
match (lhskind.node, &lhslhs.kind, &lhsrhs.kind) {
|
||||
// `-1 + x`
|
||||
(BinOpKind::Add, &ExprKind::Lit(ref lit), _) if Self::check_lit(lit, -1) => {
|
||||
(BinOpKind::Add, &ExprKind::Lit(lit), _) if Self::check_lit(lit, -1) => {
|
||||
Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs)
|
||||
},
|
||||
// `x - 1`
|
||||
(BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
|
||||
(BinOpKind::Sub, _, &ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
|
||||
Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs)
|
||||
},
|
||||
_ => None,
|
||||
|
@ -81,10 +82,10 @@ impl IntPlusOne {
|
|||
{
|
||||
match (&rhslhs.kind, &rhsrhs.kind) {
|
||||
// `y + 1` and `1 + y`
|
||||
(&ExprKind::Lit(ref lit), _) if Self::check_lit(lit, 1) => {
|
||||
(&ExprKind::Lit(lit), _) if Self::check_lit(lit, 1) => {
|
||||
Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs)
|
||||
},
|
||||
(_, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
|
||||
(_, &ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
|
||||
Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs)
|
||||
},
|
||||
_ => None,
|
||||
|
@ -96,10 +97,10 @@ impl IntPlusOne {
|
|||
{
|
||||
match (&lhslhs.kind, &lhsrhs.kind) {
|
||||
// `1 + x` and `x + 1`
|
||||
(&ExprKind::Lit(ref lit), _) if Self::check_lit(lit, 1) => {
|
||||
(&ExprKind::Lit(lit), _) if Self::check_lit(lit, 1) => {
|
||||
Self::generate_recommendation(cx, binop, lhsrhs, rhs, Side::Lhs)
|
||||
},
|
||||
(_, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
|
||||
(_, &ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
|
||||
Self::generate_recommendation(cx, binop, lhslhs, rhs, Side::Lhs)
|
||||
},
|
||||
_ => None,
|
||||
|
@ -109,11 +110,11 @@ impl IntPlusOne {
|
|||
(BinOpKind::Le, _, &ExprKind::Binary(ref rhskind, ref rhslhs, ref rhsrhs)) => {
|
||||
match (rhskind.node, &rhslhs.kind, &rhsrhs.kind) {
|
||||
// `-1 + y`
|
||||
(BinOpKind::Add, &ExprKind::Lit(ref lit), _) if Self::check_lit(lit, -1) => {
|
||||
(BinOpKind::Add, &ExprKind::Lit(lit), _) if Self::check_lit(lit, -1) => {
|
||||
Self::generate_recommendation(cx, binop, rhsrhs, lhs, Side::Rhs)
|
||||
},
|
||||
// `y - 1`
|
||||
(BinOpKind::Sub, _, &ExprKind::Lit(ref lit)) if Self::check_lit(lit, 1) => {
|
||||
(BinOpKind::Sub, _, &ExprKind::Lit(lit)) if Self::check_lit(lit, 1) => {
|
||||
Self::generate_recommendation(cx, binop, rhslhs, lhs, Side::Rhs)
|
||||
},
|
||||
_ => None,
|
||||
|
|
|
@ -5,11 +5,13 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
|
|||
use clippy_utils::numeric_literal::{NumericLiteral, Radix};
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind};
|
||||
use rustc_ast::ast::{Expr, ExprKind, LitKind};
|
||||
use rustc_ast::token;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_session::{declare_tool_lint, impl_lint_pass};
|
||||
use rustc_span::Span;
|
||||
use std::iter;
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
@ -236,8 +238,8 @@ impl EarlyLintPass for LiteralDigitGrouping {
|
|||
return;
|
||||
}
|
||||
|
||||
if let ExprKind::Lit(ref lit) = expr.kind {
|
||||
self.check_lit(cx, lit);
|
||||
if let ExprKind::Lit(lit) = expr.kind {
|
||||
self.check_lit(cx, lit, expr.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -252,12 +254,13 @@ impl LiteralDigitGrouping {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) {
|
||||
fn check_lit(self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
|
||||
if_chain! {
|
||||
if let Some(src) = snippet_opt(cx, lit.span);
|
||||
if let Some(mut num_lit) = NumericLiteral::from_lit(&src, lit);
|
||||
if let Some(src) = snippet_opt(cx, span);
|
||||
if let Ok(lit_kind) = LitKind::from_token_lit(lit);
|
||||
if let Some(mut num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind);
|
||||
then {
|
||||
if !Self::check_for_mistyped_suffix(cx, lit.span, &mut num_lit) {
|
||||
if !Self::check_for_mistyped_suffix(cx, span, &mut num_lit) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -293,14 +296,14 @@ impl LiteralDigitGrouping {
|
|||
| WarningType::InconsistentDigitGrouping
|
||||
| WarningType::UnusualByteGroupings
|
||||
| WarningType::LargeDigitGroups => {
|
||||
!lit.span.from_expansion()
|
||||
!span.from_expansion()
|
||||
}
|
||||
WarningType::DecimalRepresentation | WarningType::MistypedLiteralSuffix => {
|
||||
true
|
||||
}
|
||||
};
|
||||
if should_warn {
|
||||
warning_type.display(num_lit.format(), cx, lit.span);
|
||||
warning_type.display(num_lit.format(), cx, span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -458,8 +461,8 @@ impl EarlyLintPass for DecimalLiteralRepresentation {
|
|||
return;
|
||||
}
|
||||
|
||||
if let ExprKind::Lit(ref lit) = expr.kind {
|
||||
self.check_lit(cx, lit);
|
||||
if let ExprKind::Lit(lit) = expr.kind {
|
||||
self.check_lit(cx, lit, expr.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -469,19 +472,20 @@ impl DecimalLiteralRepresentation {
|
|||
pub fn new(threshold: u64) -> Self {
|
||||
Self { threshold }
|
||||
}
|
||||
fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) {
|
||||
fn check_lit(self, cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
|
||||
// Lint integral literals.
|
||||
if_chain! {
|
||||
if let LitKind::Int(val, _) = lit.kind;
|
||||
if let Some(src) = snippet_opt(cx, lit.span);
|
||||
if let Some(num_lit) = NumericLiteral::from_lit(&src, lit);
|
||||
if let Ok(lit_kind) = LitKind::from_token_lit(lit);
|
||||
if let LitKind::Int(val, _) = lit_kind;
|
||||
if let Some(src) = snippet_opt(cx, span);
|
||||
if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit_kind);
|
||||
if num_lit.radix == Radix::Decimal;
|
||||
if val >= u128::from(self.threshold);
|
||||
then {
|
||||
let hex = format!("{val:#X}");
|
||||
let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false);
|
||||
let _ = Self::do_lint(num_lit.integer).map_err(|warning_type| {
|
||||
warning_type.display(num_lit.format(), cx, lit.span);
|
||||
warning_type.display(num_lit.format(), cx, span);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use rustc_ast::ast::Lit;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::Span;
|
||||
|
||||
use super::{SEPARATED_LITERAL_SUFFIX, UNSEPARATED_LITERAL_SUFFIX};
|
||||
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &str, sugg_type: &str) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, lit_snip: &str, suffix: &str, sugg_type: &str) {
|
||||
let Some(maybe_last_sep_idx) = lit_snip.len().checked_sub(suffix.len() + 1) else {
|
||||
return; // It's useless so shouldn't lint.
|
||||
};
|
||||
|
@ -15,7 +15,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &s
|
|||
span_lint_and_sugg(
|
||||
cx,
|
||||
SEPARATED_LITERAL_SUFFIX,
|
||||
lit.span,
|
||||
lit_span,
|
||||
&format!("{sugg_type} type suffix should not be separated by an underscore"),
|
||||
"remove the underscore",
|
||||
format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]),
|
||||
|
@ -25,7 +25,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &s
|
|||
span_lint_and_sugg(
|
||||
cx,
|
||||
UNSEPARATED_LITERAL_SUFFIX,
|
||||
lit.span,
|
||||
lit_span,
|
||||
&format!("{sugg_type} type suffix should be separated by an underscore"),
|
||||
"add an underscore",
|
||||
format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]),
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_ast::ast::Lit;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::Span;
|
||||
|
||||
use super::MIXED_CASE_HEX_LITERALS;
|
||||
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, suffix: &str, lit_snip: &str) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, suffix: &str, lit_snip: &str) {
|
||||
let Some(maybe_last_sep_idx) = lit_snip.len().checked_sub(suffix.len() + 1) else {
|
||||
return; // It's useless so shouldn't lint.
|
||||
};
|
||||
|
@ -23,7 +23,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, suffix: &str, lit_snip: &s
|
|||
span_lint(
|
||||
cx,
|
||||
MIXED_CASE_HEX_LITERALS,
|
||||
lit.span,
|
||||
lit_span,
|
||||
"inconsistent casing in hexadecimal literal",
|
||||
);
|
||||
break;
|
||||
|
|
|
@ -9,7 +9,8 @@ mod zero_prefixed_literal;
|
|||
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use rustc_ast::ast::{Expr, ExprKind, Generics, Lit, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
|
||||
use rustc_ast::ast::{Expr, ExprKind, Generics, LitFloatType, LitIntType, LitKind, NodeId, Pat, PatKind};
|
||||
use rustc_ast::token;
|
||||
use rustc_ast::visit::FnKind;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
|
||||
|
@ -374,42 +375,43 @@ impl EarlyLintPass for MiscEarlyLints {
|
|||
return;
|
||||
}
|
||||
|
||||
if let ExprKind::Lit(ref lit) = expr.kind {
|
||||
MiscEarlyLints::check_lit(cx, lit);
|
||||
if let ExprKind::Lit(lit) = expr.kind {
|
||||
MiscEarlyLints::check_lit(cx, lit, expr.span);
|
||||
}
|
||||
double_neg::check(cx, expr);
|
||||
}
|
||||
}
|
||||
|
||||
impl MiscEarlyLints {
|
||||
fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) {
|
||||
fn check_lit(cx: &EarlyContext<'_>, lit: token::Lit, span: Span) {
|
||||
// We test if first character in snippet is a number, because the snippet could be an expansion
|
||||
// from a built-in macro like `line!()` or a proc-macro like `#[wasm_bindgen]`.
|
||||
// Note that this check also covers special case that `line!()` is eagerly expanded by compiler.
|
||||
// See <https://github.com/rust-lang/rust-clippy/issues/4507> for a regression.
|
||||
// FIXME: Find a better way to detect those cases.
|
||||
let lit_snip = match snippet_opt(cx, lit.span) {
|
||||
let lit_snip = match snippet_opt(cx, span) {
|
||||
Some(snip) if snip.chars().next().map_or(false, |c| c.is_ascii_digit()) => snip,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
if let LitKind::Int(value, lit_int_type) = lit.kind {
|
||||
let lit_kind = LitKind::from_token_lit(lit);
|
||||
if let Ok(LitKind::Int(value, lit_int_type)) = lit_kind {
|
||||
let suffix = match lit_int_type {
|
||||
LitIntType::Signed(ty) => ty.name_str(),
|
||||
LitIntType::Unsigned(ty) => ty.name_str(),
|
||||
LitIntType::Unsuffixed => "",
|
||||
};
|
||||
literal_suffix::check(cx, lit, &lit_snip, suffix, "integer");
|
||||
literal_suffix::check(cx, span, &lit_snip, suffix, "integer");
|
||||
if lit_snip.starts_with("0x") {
|
||||
mixed_case_hex_literals::check(cx, lit, suffix, &lit_snip);
|
||||
mixed_case_hex_literals::check(cx, span, suffix, &lit_snip);
|
||||
} else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") {
|
||||
// nothing to do
|
||||
} else if value != 0 && lit_snip.starts_with('0') {
|
||||
zero_prefixed_literal::check(cx, lit, &lit_snip);
|
||||
zero_prefixed_literal::check(cx, span, &lit_snip);
|
||||
}
|
||||
} else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind {
|
||||
} else if let Ok(LitKind::Float(_, LitFloatType::Suffixed(float_ty))) = lit_kind {
|
||||
let suffix = float_ty.name_str();
|
||||
literal_suffix::check(cx, lit, &lit_snip, suffix, "float");
|
||||
literal_suffix::check(cx, span, &lit_snip, suffix, "float");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use rustc_ast::ast::Lit;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::Span;
|
||||
|
||||
use super::ZERO_PREFIXED_LITERAL;
|
||||
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, lit_snip: &str) {
|
||||
let trimmed_lit_snip = lit_snip.trim_start_matches(|c| c == '_' || c == '0');
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
ZERO_PREFIXED_LITERAL,
|
||||
lit.span,
|
||||
lit_span,
|
||||
"this is a decimal constant",
|
||||
|diag| {
|
||||
diag.span_suggestion(
|
||||
lit.span,
|
||||
lit_span,
|
||||
"if you mean to use a decimal constant, remove the `0` to avoid confusion",
|
||||
trimmed_lit_snip.to_string(),
|
||||
Applicability::MaybeIncorrect,
|
||||
|
@ -22,7 +22,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str) {
|
|||
// do not advise to use octal form if the literal cannot be expressed in base 8.
|
||||
if !lit_snip.contains(|c| c == '8' || c == '9') {
|
||||
diag.span_suggestion(
|
||||
lit.span,
|
||||
lit_span,
|
||||
"if you mean to use an octal constant, use `0o`",
|
||||
format!("0o{trimmed_lit_snip}"),
|
||||
Applicability::MaybeIncorrect,
|
||||
|
|
|
@ -56,11 +56,11 @@ impl EarlyLintPass for OctalEscapes {
|
|||
return;
|
||||
}
|
||||
|
||||
if let ExprKind::Lit(lit) = &expr.kind {
|
||||
if matches!(lit.token_lit.kind, LitKind::Str) {
|
||||
check_lit(cx, &lit.token_lit, lit.span, true);
|
||||
} else if matches!(lit.token_lit.kind, LitKind::ByteStr) {
|
||||
check_lit(cx, &lit.token_lit, lit.span, false);
|
||||
if let ExprKind::Lit(token_lit) = &expr.kind {
|
||||
if matches!(token_lit.kind, LitKind::Str) {
|
||||
check_lit(cx, &token_lit, expr.span, true);
|
||||
} else if matches!(token_lit.kind, LitKind::ByteStr) {
|
||||
check_lit(cx, &token_lit, expr.span, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind, UnOp};
|
||||
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp};
|
||||
use rustc_ast::token;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
@ -120,7 +121,7 @@ impl EarlyLintPass for Precedence {
|
|||
if_chain! {
|
||||
if !all_odd;
|
||||
if let ExprKind::Lit(lit) = &arg.kind;
|
||||
if let LitKind::Int(..) | LitKind::Float(..) = &lit.kind;
|
||||
if let token::LitKind::Integer | token::LitKind::Float = &lit.kind;
|
||||
then {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
span_lint_and_sugg(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use rustc_ast::ast::{Expr, ExprKind, LitFloatType, LitKind};
|
||||
use rustc_ast::ast::{Expr, ExprKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
|
@ -33,14 +33,14 @@ fn is_useless_rounding(expr: &Expr) -> Option<(&str, String)> {
|
|||
if let ExprKind::MethodCall(name_ident, receiver, _, _) = &expr.kind
|
||||
&& let method_name = name_ident.ident.name.as_str()
|
||||
&& (method_name == "ceil" || method_name == "round" || method_name == "floor")
|
||||
&& let ExprKind::Lit(spanned) = &receiver.kind
|
||||
&& let LitKind::Float(symbol, ty) = spanned.kind {
|
||||
let f = symbol.as_str().parse::<f64>().unwrap();
|
||||
let f_str = symbol.to_string() + if let LitFloatType::Suffixed(ty) = ty {
|
||||
ty.name_str()
|
||||
} else {
|
||||
""
|
||||
};
|
||||
&& let ExprKind::Lit(token_lit) = &receiver.kind
|
||||
&& token_lit.is_semantic_float() {
|
||||
let f = token_lit.symbol.as_str().parse::<f64>().unwrap();
|
||||
let mut f_str = token_lit.symbol.to_string();
|
||||
match token_lit.suffix {
|
||||
Some(suffix) => f_str.push_str(suffix.as_str()),
|
||||
None => {}
|
||||
}
|
||||
if f.fract() == 0.0 {
|
||||
Some((method_name, f_str))
|
||||
} else {
|
||||
|
|
|
@ -152,7 +152,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
|
|||
},
|
||||
(Binary(lo, ll, lr), Binary(ro, rl, rr)) => lo.node == ro.node && eq_expr(ll, rl) && eq_expr(lr, rr),
|
||||
(Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r),
|
||||
(Lit(l), Lit(r)) => l.kind == r.kind,
|
||||
(Lit(l), Lit(r)) => l == r,
|
||||
(Cast(l, lt), Cast(r, rt)) | (Type(l, lt), Type(r, rt)) => eq_expr(l, r) && eq_ty(lt, rt),
|
||||
(Let(lp, le, _), Let(rp, re, _)) => eq_pat(lp, rp) && eq_expr(le, re),
|
||||
(If(lc, lt, le), If(rc, rt, re)) => eq_expr(lc, rc) && eq_block(lt, rt) && eq_expr_opt(le, re),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_ast::ast::{Lit, LitFloatType, LitIntType, LitKind};
|
||||
use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
|
||||
use std::iter;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
|
@ -46,10 +46,6 @@ pub struct NumericLiteral<'a> {
|
|||
}
|
||||
|
||||
impl<'a> NumericLiteral<'a> {
|
||||
pub fn from_lit(src: &'a str, lit: &Lit) -> Option<NumericLiteral<'a>> {
|
||||
NumericLiteral::from_lit_kind(src, &lit.kind)
|
||||
}
|
||||
|
||||
pub fn from_lit_kind(src: &'a str, lit_kind: &LitKind) -> Option<NumericLiteral<'a>> {
|
||||
let unsigned_src = src.strip_prefix('-').map_or(src, |s| s);
|
||||
if lit_kind.is_numeric()
|
||||
|
|
Loading…
Reference in a new issue