refactor(lexer): replace #[allow] with #[expect] (#8289)

Pure refactor. Replace `#[allow]` with `#[expect]` in lexer, and remove various `#[allow]`s which were unnecessary.
This commit is contained in:
overlookmotel 2025-01-06 18:01:16 +00:00
parent 0462edbe7e
commit fabf116f4b
9 changed files with 34 additions and 40 deletions

View file

@ -1,10 +1,10 @@
use super::{Kind, Lexer}; use super::{Kind, Lexer};
use crate::diagnostics; use crate::diagnostics;
#[allow(clippy::unnecessary_safety_comment)]
/// Handle next byte of source. /// Handle next byte of source.
/// ///
/// SAFETY: /// # SAFETY
///
/// * Lexer must not be at end of file. /// * Lexer must not be at end of file.
/// * `byte` must be next byte of source code, corresponding to current position of `lexer.source`. /// * `byte` must be next byte of source code, corresponding to current position of `lexer.source`.
/// * Only `BYTE_HANDLERS` for ASCII characters may use the `ascii_byte_handler!()` macro. /// * Only `BYTE_HANDLERS` for ASCII characters may use the `ascii_byte_handler!()` macro.
@ -72,7 +72,6 @@ macro_rules! byte_handler {
}; };
} }
#[allow(clippy::unnecessary_safety_comment)]
/// Macro for defining byte handler for an ASCII character. /// Macro for defining byte handler for an ASCII character.
/// ///
/// In addition to defining a `const` for the handler, it also asserts that lexer /// In addition to defining a `const` for the handler, it also asserts that lexer
@ -132,7 +131,6 @@ macro_rules! ascii_byte_handler {
}; };
} }
#[allow(clippy::unnecessary_safety_comment)]
/// Macro for defining byte handler for an ASCII character which is start of an identifier /// Macro for defining byte handler for an ASCII character which is start of an identifier
/// (`a`-`z`, `A`-`Z`, `$` or `_`). /// (`a`-`z`, `A`-`Z`, `$` or `_`).
/// ///

View file

@ -31,7 +31,7 @@ impl Lexer<'_> {
// If this is end of comment, create trivia, and advance `pos` to after line break. // If this is end of comment, create trivia, and advance `pos` to after line break.
// Do that here rather than in `handle_match`, to avoid branching twice on value of // Do that here rather than in `handle_match`, to avoid branching twice on value of
// the matched byte. // the matched byte.
#[allow(clippy::if_not_else)] #[expect(clippy::if_not_else)]
if next_byte != LS_OR_PS_FIRST { if next_byte != LS_OR_PS_FIRST {
// `\r` or `\n` // `\r` or `\n`
self.trivia_builder self.trivia_builder

View file

@ -47,7 +47,7 @@ impl<'a> Lexer<'a> {
/// # SAFETY /// # SAFETY
/// * `self.source` must not be exhausted (at least 1 char remaining). /// * `self.source` must not be exhausted (at least 1 char remaining).
/// * Next char must be ASCII. /// * Next char must be ASCII.
#[allow(clippy::missing_safety_doc)] // Clippy is wrong! #[expect(clippy::unnecessary_safety_comment)]
pub(super) unsafe fn identifier_name_handler(&mut self) -> &'a str { pub(super) unsafe fn identifier_name_handler(&mut self) -> &'a str {
// Advance past 1st byte. // Advance past 1st byte.
// SAFETY: Caller guarantees not at EOF, and next byte is ASCII. // SAFETY: Caller guarantees not at EOF, and next byte is ASCII.

View file

@ -26,6 +26,7 @@ impl Lexer<'_> {
/// # SAFETY /// # SAFETY
/// * `delimiter` must be an ASCII character. /// * `delimiter` must be an ASCII character.
/// * Next char in `lexer.source` must be ASCII. /// * Next char in `lexer.source` must be ASCII.
#[expect(clippy::unnecessary_safety_comment)]
pub(super) unsafe fn read_jsx_string_literal(&mut self, delimiter: u8) -> Kind { pub(super) unsafe fn read_jsx_string_literal(&mut self, delimiter: u8) -> Kind {
// Skip opening quote // Skip opening quote
debug_assert!(delimiter.is_ascii()); debug_assert!(delimiter.is_ascii());

View file

@ -1,6 +1,3 @@
#![allow(clippy::unnecessary_safety_comment)]
#![allow(unsafe_code)]
//! An Ecma-262 Lexer / Tokenizer //! An Ecma-262 Lexer / Tokenizer
//! Prior Arts: //! Prior Arts:
//! * [jsparagus](https://github.com/mozilla-spidermonkey/jsparagus/blob/24004745a8ed4939fc0dc7332bfd1268ac52285f/crates/parser/src) //! * [jsparagus](https://github.com/mozilla-spidermonkey/jsparagus/blob/24004745a8ed4939fc0dc7332bfd1268ac52285f/crates/parser/src)
@ -99,7 +96,6 @@ pub struct Lexer<'a> {
multi_line_comment_end_finder: Option<memchr::memmem::Finder<'static>>, multi_line_comment_end_finder: Option<memchr::memmem::Finder<'static>>,
} }
#[allow(clippy::unused_self)]
impl<'a> Lexer<'a> { impl<'a> Lexer<'a> {
/// Create new `Lexer`. /// Create new `Lexer`.
/// ///
@ -230,7 +226,6 @@ impl<'a> Lexer<'a> {
/// Get the length offset from the source, in UTF-8 bytes /// Get the length offset from the source, in UTF-8 bytes
#[inline] #[inline]
#[allow(clippy::cast_possible_truncation)]
fn offset(&self) -> u32 { fn offset(&self) -> u32 {
self.source.offset() self.source.offset()
} }

View file

@ -60,7 +60,7 @@ const fn decimal_byte_to_value(b: u8) -> u8 {
b & 15 b & 15
} }
#[allow(clippy::cast_precision_loss, clippy::cast_lossless)] #[expect(clippy::cast_precision_loss, clippy::cast_lossless)]
fn parse_decimal(s: &str) -> f64 { fn parse_decimal(s: &str) -> f64 {
/// Numeric strings longer than this have the chance to overflow u64. /// Numeric strings longer than this have the chance to overflow u64.
/// `u64::MAX + 1` in decimal is 18446744073709551616 (20 chars). /// `u64::MAX + 1` in decimal is 18446744073709551616 (20 chars).
@ -86,7 +86,7 @@ fn parse_decimal(s: &str) -> f64 {
result as f64 result as f64
} }
#[allow(clippy::cast_precision_loss, clippy::cast_lossless)] #[expect(clippy::cast_precision_loss, clippy::cast_lossless)]
fn parse_decimal_with_underscores(s: &str) -> f64 { fn parse_decimal_with_underscores(s: &str) -> f64 {
/// Numeric strings longer than this have the chance to overflow u64. /// Numeric strings longer than this have the chance to overflow u64.
/// `u64::MAX + 1` in decimal is 18446744073709551616 (20 chars). /// `u64::MAX + 1` in decimal is 18446744073709551616 (20 chars).
@ -146,7 +146,7 @@ const fn binary_byte_to_value(b: u8) -> u8 {
/// we consider leading zeros as part of that length. Right now it doesn't seem /// we consider leading zeros as part of that length. Right now it doesn't seem
/// worth it performance-wise to check and strip them. Further experimentation /// worth it performance-wise to check and strip them. Further experimentation
/// could be useful. /// could be useful.
#[allow(clippy::cast_precision_loss, clippy::cast_lossless)] #[expect(clippy::cast_precision_loss, clippy::cast_lossless)]
fn parse_binary(s: &str) -> f64 { fn parse_binary(s: &str) -> f64 {
/// binary literals longer than this many characters have the chance to /// binary literals longer than this many characters have the chance to
/// overflow a u64, forcing us to take the slow path. /// overflow a u64, forcing us to take the slow path.
@ -178,7 +178,7 @@ fn parse_binary_slow(s: &str) -> f64 {
result result
} }
#[allow(clippy::cast_precision_loss, clippy::cast_lossless)] #[expect(clippy::cast_precision_loss, clippy::cast_lossless)]
fn parse_binary_with_underscores(s: &str) -> f64 { fn parse_binary_with_underscores(s: &str) -> f64 {
/// binary literals longer than this many characters have the chance to /// binary literals longer than this many characters have the chance to
/// overflow a u64, forcing us to take the slow path. /// overflow a u64, forcing us to take the slow path.
@ -228,7 +228,7 @@ const fn octal_byte_to_value(b: u8) -> u8 {
b & 7 b & 7
} }
#[allow(clippy::cast_precision_loss, clippy::cast_lossless)] #[expect(clippy::cast_precision_loss, clippy::cast_lossless)]
fn parse_octal(s: &str) -> f64 { fn parse_octal(s: &str) -> f64 {
/// Numeric strings longer than this have the chance to overflow u64. /// Numeric strings longer than this have the chance to overflow u64.
const MAX_FAST_OCTAL_LEN: usize = 21; const MAX_FAST_OCTAL_LEN: usize = 21;
@ -250,7 +250,6 @@ fn parse_octal(s: &str) -> f64 {
#[cold] #[cold]
#[inline(never)] #[inline(never)]
#[allow(clippy::cast_precision_loss, clippy::cast_lossless)]
fn parse_octal_slow(s: &str) -> f64 { fn parse_octal_slow(s: &str) -> f64 {
let mut result = 0_f64; let mut result = 0_f64;
for &b in s.as_bytes() { for &b in s.as_bytes() {
@ -260,7 +259,7 @@ fn parse_octal_slow(s: &str) -> f64 {
result result
} }
#[allow(clippy::cast_precision_loss, clippy::cast_lossless)] #[expect(clippy::cast_precision_loss, clippy::cast_lossless)]
fn parse_octal_with_underscores(s: &str) -> f64 { fn parse_octal_with_underscores(s: &str) -> f64 {
/// Numeric strings longer than this have the chance to overflow u64. /// Numeric strings longer than this have the chance to overflow u64.
const MAX_FAST_OCTAL_LEN: usize = 21; const MAX_FAST_OCTAL_LEN: usize = 21;
@ -284,7 +283,6 @@ fn parse_octal_with_underscores(s: &str) -> f64 {
#[cold] #[cold]
#[inline(never)] #[inline(never)]
#[allow(clippy::cast_precision_loss, clippy::cast_lossless)]
fn parse_octal_with_underscores_slow(s: &str) -> f64 { fn parse_octal_with_underscores_slow(s: &str) -> f64 {
let mut result = 0_f64; let mut result = 0_f64;
for &b in s.as_bytes() { for &b in s.as_bytes() {
@ -321,7 +319,7 @@ const fn hex_byte_to_value(b: u8) -> u8 {
} }
} }
#[allow(clippy::cast_precision_loss, clippy::cast_lossless)] #[expect(clippy::cast_precision_loss, clippy::cast_lossless)]
fn parse_hex(s: &str) -> f64 { fn parse_hex(s: &str) -> f64 {
/// Hex strings longer than this have the chance to overflow u64. /// Hex strings longer than this have the chance to overflow u64.
const MAX_FAST_HEX_LEN: usize = 16; const MAX_FAST_HEX_LEN: usize = 16;
@ -353,7 +351,7 @@ fn parse_hex_slow(s: &str) -> f64 {
result result
} }
#[allow(clippy::cast_precision_loss, clippy::cast_lossless)] #[expect(clippy::cast_precision_loss, clippy::cast_lossless)]
fn parse_hex_with_underscores(s: &str) -> f64 { fn parse_hex_with_underscores(s: &str) -> f64 {
/// Hex strings longer than this have the chance to overflow u64. /// Hex strings longer than this have the chance to overflow u64.
const MAX_FAST_HEX_LEN: usize = 16; const MAX_FAST_HEX_LEN: usize = 16;
@ -419,11 +417,11 @@ fn parse_big_int_without_underscores(s: &str, kind: Kind) -> Result<BigInt, &'st
} }
#[cfg(test)] #[cfg(test)]
#[allow(clippy::unreadable_literal, clippy::mixed_case_hex_literals)] #[expect(clippy::unreadable_literal, clippy::mixed_case_hex_literals)]
mod test { mod test {
use super::*; use super::*;
#[allow(clippy::cast_precision_loss)] #[expect(clippy::cast_precision_loss)]
fn assert_all_ints_eq<I>(test_cases: I, kind: Kind, has_sep: bool) fn assert_all_ints_eq<I>(test_cases: I, kind: Kind, has_sep: bool)
where where
I: IntoIterator<Item = (&'static str, i64)>, I: IntoIterator<Item = (&'static str, i64)>,
@ -474,7 +472,7 @@ mod test {
}; };
#[test] #[test]
#[allow(clippy::excessive_precision, clippy::cast_precision_loss)] #[expect(clippy::cast_precision_loss)]
fn test_int_precision() { fn test_int_precision() {
assert_eq!( assert_eq!(
// 18446744073709551616 = 1 << 64 // 18446744073709551616 = 1 << 64
@ -508,7 +506,6 @@ mod test {
} }
#[test] #[test]
#[allow(clippy::excessive_precision)]
fn test_large_number_of_leading_zeros() { fn test_large_number_of_leading_zeros() {
assert_all_ints_eq( assert_all_ints_eq(
vec![("000000000000000000000000000000000000000000000000000000001", 1)], vec![("000000000000000000000000000000000000000000000000000000001", 1)],
@ -518,7 +515,7 @@ mod test {
} }
#[test] #[test]
#[allow(clippy::excessive_precision)] #[expect(clippy::excessive_precision)]
fn test_float_precision() { fn test_float_precision() {
let cases = vec![ let cases = vec![
("1.7976931348623157e+308", 1.7976931348623157e+308), ("1.7976931348623157e+308", 1.7976931348623157e+308),

View file

@ -41,7 +41,7 @@ pub const SEARCH_BATCH_SIZE: usize = 32;
#[repr(C, align(64))] #[repr(C, align(64))]
pub struct ByteMatchTable([bool; 256]); pub struct ByteMatchTable([bool; 256]);
#[allow(dead_code)] #[expect(dead_code)]
impl ByteMatchTable { impl ByteMatchTable {
// Create new `ByteMatchTable`. // Create new `ByteMatchTable`.
pub const fn new(bytes: [bool; 256]) -> Self { pub const fn new(bytes: [bool; 256]) -> Self {
@ -61,7 +61,7 @@ impl ByteMatchTable {
/// An unsafe function here, whereas for `SafeByteMatchTable` it's safe. /// An unsafe function here, whereas for `SafeByteMatchTable` it's safe.
/// `byte_search!` macro calls `.use_table()` on whatever table it's provided, which makes /// `byte_search!` macro calls `.use_table()` on whatever table it's provided, which makes
/// using the macro unsafe for `ByteMatchTable`, but safe for `SafeByteMatchTable`. /// using the macro unsafe for `ByteMatchTable`, but safe for `SafeByteMatchTable`.
#[allow(clippy::unused_self)] #[expect(clippy::unused_self)]
#[inline] #[inline]
pub const unsafe fn use_table(&self) {} pub const unsafe fn use_table(&self) {}
@ -92,7 +92,7 @@ impl ByteMatchTable {
/// TABLE /// TABLE
/// } /// }
/// ``` /// ```
#[allow(unused_macros)] #[expect(unused_macros)]
macro_rules! byte_match_table { macro_rules! byte_match_table {
(|$byte:ident| $res:expr) => {{ (|$byte:ident| $res:expr) => {{
use crate::lexer::search::ByteMatchTable; use crate::lexer::search::ByteMatchTable;
@ -105,7 +105,7 @@ macro_rules! byte_match_table {
TABLE TABLE
}}; }};
} }
#[allow(unused_imports)] #[expect(unused_imports)]
pub(crate) use byte_match_table; pub(crate) use byte_match_table;
/// Safe byte matcher lookup table. /// Safe byte matcher lookup table.
@ -203,7 +203,7 @@ impl SafeByteMatchTable {
/// A safe function here, whereas for `ByteMatchTable` it's unsafe. /// A safe function here, whereas for `ByteMatchTable` it's unsafe.
/// `byte_search!` macro calls `.use_table()` on whatever table it's provided, which makes /// `byte_search!` macro calls `.use_table()` on whatever table it's provided, which makes
/// using the macro unsafe for `ByteMatchTable`, but safe for `SafeByteMatchTable`. /// using the macro unsafe for `ByteMatchTable`, but safe for `SafeByteMatchTable`.
#[allow(clippy::unused_self)] #[expect(clippy::unused_self)]
#[inline] #[inline]
pub const fn use_table(&self) {} pub const fn use_table(&self) {}
@ -428,10 +428,11 @@ macro_rules! byte_search {
// responsibility to uphold this invariant. // responsibility to uphold this invariant.
// Therefore we can assume this is taken care of one way or another, and wrap the calls // Therefore we can assume this is taken care of one way or another, and wrap the calls
// to unsafe functions in this function with `unsafe {}`. // to unsafe functions in this function with `unsafe {}`.
#[allow(clippy::unnecessary_safety_comment)]
$table.use_table(); $table.use_table();
let mut $pos = $start; let mut $pos = $start;
#[allow(unused_unsafe)] // Silence warnings if macro called in unsafe code #[allow(unused_unsafe, clippy::unnecessary_safety_comment)] // Silence warnings if macro called in unsafe code
'outer: loop { 'outer: loop {
let $byte = if $pos.addr() <= $lexer.source.end_for_batch_search_addr() { let $byte = if $pos.addr() <= $lexer.source.end_for_batch_search_addr() {
// Search a batch of `SEARCH_BATCH_SIZE` bytes. // Search a batch of `SEARCH_BATCH_SIZE` bytes.

View file

@ -1,4 +1,4 @@
#![allow(clippy::unnecessary_safety_comment)] #![expect(clippy::unnecessary_safety_comment)]
use std::{marker::PhantomData, slice, str}; use std::{marker::PhantomData, slice, str};
@ -80,7 +80,7 @@ impl<'a> Source<'a> {
/// ///
/// Requiring a `UniquePromise` to be provided guarantees only 1 `Source` can exist /// Requiring a `UniquePromise` to be provided guarantees only 1 `Source` can exist
/// on a single thread at one time. /// on a single thread at one time.
#[allow(unused_variables, clippy::needless_pass_by_value)] #[expect(unused_variables, clippy::needless_pass_by_value)]
pub(super) fn new(mut source_text: &'a str, unique: UniquePromise) -> Self { pub(super) fn new(mut source_text: &'a str, unique: UniquePromise) -> Self {
// If source text exceeds size limit, substitute a short source text which will fail to parse. // If source text exceeds size limit, substitute a short source text which will fail to parse.
// `Parser::parse` will convert error to `diagnostics::overlong_source()`. // `Parser::parse` will convert error to `diagnostics::overlong_source()`.
@ -295,14 +295,13 @@ impl<'a> Source<'a> {
} }
/// Get current position in source, relative to start of source. /// Get current position in source, relative to start of source.
#[allow(clippy::cast_possible_truncation)]
#[inline] #[inline]
pub(super) fn offset(&self) -> u32 { pub(super) fn offset(&self) -> u32 {
self.offset_of(self.position()) self.offset_of(self.position())
} }
/// Get offset of `pos`. /// Get offset of `pos`.
#[allow(clippy::cast_possible_truncation)] #[expect(clippy::cast_possible_truncation)]
#[inline] #[inline]
pub(super) fn offset_of(&self, pos: SourcePosition) -> u32 { pub(super) fn offset_of(&self, pos: SourcePosition) -> u32 {
// Cannot overflow `u32` because of `MAX_LEN` check in `Source::new` // Cannot overflow `u32` because of `MAX_LEN` check in `Source::new`
@ -435,10 +434,10 @@ impl<'a> Source<'a> {
/// source.next_char().unwrap(); /// source.next_char().unwrap();
/// } /// }
/// ``` /// ```
#[allow(dead_code)] #[expect(dead_code)]
#[inline] #[inline]
unsafe fn next_byte(&mut self) -> Option<u8> { unsafe fn next_byte(&mut self) -> Option<u8> {
#[allow(clippy::if_not_else)] // Hot path first #[expect(clippy::if_not_else)] // Hot path first
if !self.is_eof() { if !self.is_eof() {
// SAFETY: Safe to read from `ptr` as we just checked it's not out of bounds // SAFETY: Safe to read from `ptr` as we just checked it's not out of bounds
Some(self.next_byte_unchecked()) Some(self.next_byte_unchecked())
@ -504,7 +503,7 @@ impl<'a> Source<'a> {
/// Peek next byte of source without consuming it. /// Peek next byte of source without consuming it.
#[inline] #[inline]
pub(super) fn peek_byte(&self) -> Option<u8> { pub(super) fn peek_byte(&self) -> Option<u8> {
#[allow(clippy::if_not_else)] // Hot path first #[expect(clippy::if_not_else)] // Hot path first
if !self.is_eof() { if !self.is_eof() {
// SAFETY: Safe to read from `ptr` as we just checked it's not out of bounds // SAFETY: Safe to read from `ptr` as we just checked it's not out of bounds
Some(unsafe { self.peek_byte_unchecked() }) Some(unsafe { self.peek_byte_unchecked() })
@ -642,7 +641,7 @@ impl SourcePosition<'_> {
// Pointer is "dereferenceable" by definition as a `u8` is 1 byte and cannot span multiple objects. // Pointer is "dereferenceable" by definition as a `u8` is 1 byte and cannot span multiple objects.
// Alignment is not relevant as `u8` is aligned on 1 (i.e. no alignment requirements). // Alignment is not relevant as `u8` is aligned on 1 (i.e. no alignment requirements).
debug_assert!(!self.ptr.is_null()); debug_assert!(!self.ptr.is_null());
#[allow(clippy::ptr_as_ptr)] #[expect(clippy::ptr_as_ptr)]
let p = self.ptr as *const [u8; 2]; let p = self.ptr as *const [u8; 2];
*p.as_ref().unwrap_unchecked() *p.as_ref().unwrap_unchecked()
} }

View file

@ -86,6 +86,7 @@ impl<'a> Lexer<'a> {
/// # SAFETY /// # SAFETY
/// * Byte at `pos` must be `\r`. /// * Byte at `pos` must be `\r`.
/// * `pos` must not be before `self.source.position()`. /// * `pos` must not be before `self.source.position()`.
#[expect(clippy::unnecessary_safety_comment)]
unsafe fn template_literal_carriage_return( unsafe fn template_literal_carriage_return(
&mut self, &mut self,
mut pos: SourcePosition<'a>, mut pos: SourcePosition<'a>,
@ -128,6 +129,7 @@ impl<'a> Lexer<'a> {
/// # SAFETY /// # SAFETY
/// * Byte at `pos` must be `\`. /// * Byte at `pos` must be `\`.
/// * `pos` must not be before `self.source.position()`. /// * `pos` must not be before `self.source.position()`.
#[expect(clippy::unnecessary_safety_comment)]
unsafe fn template_literal_backslash( unsafe fn template_literal_backslash(
&mut self, &mut self,
pos: SourcePosition<'a>, pos: SourcePosition<'a>,
@ -163,6 +165,7 @@ impl<'a> Lexer<'a> {
/// Create arena string for modified template literal, containing the template literal up to `pos`. /// Create arena string for modified template literal, containing the template literal up to `pos`.
/// # SAFETY /// # SAFETY
/// `pos` must not be before `self.source.position()` /// `pos` must not be before `self.source.position()`
#[expect(clippy::unnecessary_safety_comment)]
unsafe fn template_literal_create_string(&self, pos: SourcePosition) -> String<'a> { unsafe fn template_literal_create_string(&self, pos: SourcePosition) -> String<'a> {
// Create arena string to hold modified template literal. // Create arena string to hold modified template literal.
// We don't know how long template literal will end up being. Take a guess that total length // We don't know how long template literal will end up being. Take a guess that total length