treewide: enforce strict clippy check

This commit is contained in:
2026-08-22 18:41:23 +08:00
parent 5f494983b8
commit cb38031f85
51 changed files with 1237 additions and 568 deletions
+75 -5
View File
@@ -4,7 +4,9 @@ use std::marker::PhantomData;
use std::mem::size_of;
use std::ops::Deref;
use fix_bytecode::Continuation;
use fix_lang::*;
use fix_macros::unelide_lifetimes;
use gc_arena::barrier::Unlock;
use gc_arena::collect::Trace;
use gc_arena::{Collect, Gc, GcRefLock, Mutation, RefLock};
@@ -20,7 +22,10 @@ mod private {
}
pub trait ValueVariant: private::Cealed {
#[allow(private_bounds)]
#[expect(
private_bounds,
reason = "Storable is a sealed implementation detail of the value system"
)]
type Ty<'gc>: Storable + 'gc;
const TYPE: NixType;
}
@@ -52,6 +57,9 @@ macro_rules! define_value_types {
}
#[inline(always)]
unsafe fn from_raw_box(raw: RawBox) -> Self {
// SAFETY: the caller guarantees `raw` represents a valid
// `Self` of this inline type, so it holds a `Value` (making
// `value()` `Some`) whose payload decodes to this type.
unsafe { <Self as RawStore>::from_val(raw.value().unwrap_unchecked()) }
}
}
@@ -73,13 +81,17 @@ macro_rules! define_value_types {
}
#[inline(always)]
unsafe fn from_raw_box(raw: RawBox) -> Self {
// SAFETY: the caller guarantees `raw` represents a valid
// `Self` of this GC type, so it holds a `Value` (making
// `value()` `Some`) whose payload is the pointer originally
// produced by `Gc::as_ptr` in `to_raw_box`.
unsafe { Gc::from_ptr(<*mut $gtype as RawStore>::from_val(raw.value().unwrap_unchecked())) }
}
}
impl private::Cealed for Gc<'_, $gtype> {}
impl private::Cealed for $gtype {}
impl ValueVariant for $gtype {
type Ty<'gc> = Gc<'gc, fix_macros::unelide_lifetimes!('gc; $gtype)>;
type Ty<'gc> = Gc<'gc, unelide_lifetimes!('gc; $gtype)>;
const TYPE: NixType = $gty;
}
)*
@@ -93,6 +105,7 @@ macro_rules! define_value_types {
let mut mask_true: u8 = 0;
let mut i = 0;
while i < tags.len() {
#[expect(clippy::indexing_slicing, reason = "loop condition guarantees `i < tags.len()`")]
let (neg, val) = tags[i];
let bit = 1 << val;
if neg {
@@ -106,12 +119,17 @@ macro_rules! define_value_types {
}
};
// SAFETY: `trace` visits every reachable `Gc` pointer: for each GC
// tag it downcasts to the concrete `Gc` type and forwards `trace`,
// while inline tags hold no GC pointers and need no tracing.
unsafe impl<'gc> Collect<'gc> for Value<'gc> {
const NEEDS_TRACE: bool = true;
fn trace<T: Trace<'gc>>(&self, cc: &mut T) {
let Some(tag) = self.raw.tag() else { return };
match tag {
$($gtag => unsafe {
// SAFETY: `tag` matched `$gtag`, so `downcast` to the
// corresponding GC type is guaranteed to be `Some`.
self.downcast::<$gtype>().unwrap_unchecked().trace(cc)
},)*
$($itag => (),)*
@@ -123,9 +141,13 @@ macro_rules! define_value_types {
impl fmt::Debug for Value<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.tag() {
// SAFETY: `tag()` is `None`, meaning the `RawBox` holds a
// float, so `float()` is guaranteed to be `Some`.
None => write!(f, "Float({:?})", unsafe {
self.raw.float().unwrap_unchecked()
}),
// SAFETY: `tag()` matched `$itag`, so `downcast` to the
// corresponding inline type is guaranteed to be `Some`.
$(Some($itag) => write!(f, "{}({:?})", $iname, unsafe {
self.downcast::<$itype>().unwrap_unchecked()
}),)*
@@ -171,6 +193,8 @@ impl Storable for f64 {
}
#[inline(always)]
unsafe fn from_raw_box(raw: RawBox) -> Self {
// SAFETY: the caller guarantees `raw` represents a valid `f64`, so
// `float()` is guaranteed to be `Some`.
unsafe { raw.float().copied().unwrap_unchecked() }
}
}
@@ -180,6 +204,12 @@ impl ValueVariant for f64 {
const TYPE: NixType = NixType::Float;
}
impl<'gc, T: Storable + 'gc> From<T> for Value<'gc> {
fn from(value: T) -> Self {
Value::new(value)
}
}
/// # Nix runtime value representation
///
/// NaN-boxed value fitting in 8 bytes.
@@ -206,7 +236,10 @@ impl<'gc> Value<'gc> {
impl<'gc> Value<'gc> {
#[inline]
#[allow(private_bounds)]
#[expect(
private_bounds,
reason = "Storable is a sealed implementation detail of the value system"
)]
pub fn new<T: Storable>(val: T) -> Self {
Self {
raw: val.to_raw_box(),
@@ -230,7 +263,10 @@ impl<'gc> Value<'gc> {
#[inline]
pub fn downcast<T: ValueVariant>(self) -> Option<T::Ty<'gc>> {
self.is::<T>().then(|| unsafe { T::Ty::from_raw_box(self.raw) })
self.is::<T>()
// SAFETY: `is::<T>()` returned true, so `self.raw` represents a
// valid `T::Ty`.
.then(|| unsafe { T::Ty::from_raw_box(self.raw) })
}
#[inline]
@@ -259,6 +295,10 @@ impl<'gc> Value<'gc> {
}
#[inline]
#[expect(
clippy::unreachable,
reason = "the preceding `if`/`else if` chain exhausts every registered value tag"
)]
pub fn ty(self) -> NixType {
if self.is::<f64>() {
NixType::Float
@@ -316,7 +356,10 @@ impl<'gc> From<StaticValue> for Value<'gc> {
impl StaticValue {
#[inline]
#[allow(private_bounds)]
#[expect(
private_bounds,
reason = "Storable is a sealed implementation detail of the value system"
)]
pub fn new<T: Storable + 'static>(val: T) -> Self {
Self(Value::new(val))
}
@@ -429,6 +472,10 @@ impl<'gc> AttrSet<'gc> {
Self { entries }
}
#[expect(
clippy::indexing_slicing,
reason = "index comes from a successful `binary_search_by_key`, so it is a valid entry index"
)]
pub fn lookup(&self, key: StringId) -> Option<Value<'gc>> {
self.entries
.binary_search_by_key(&key, |(k, _)| *k)
@@ -440,6 +487,10 @@ impl<'gc> AttrSet<'gc> {
self.entries.binary_search_by_key(&key, |(k, _)| *k).is_ok()
}
#[expect(
clippy::indexing_slicing,
reason = "`i`/`j` stay strictly below their lengths inside the loop, and the trailing slices use those in-bounds cursors as start indices"
)]
pub fn merge(&self, other: &Self, mc: &Mutation<'gc>) -> Gc<'gc, Self> {
use std::cmp::Ordering::*;
@@ -500,6 +551,9 @@ impl<'gc> List<'gc> {
impl<'gc> Unlock for List<'gc> {
type Unlocked = RefCell<SmallVec<[Value<'gc>; 4]>>;
unsafe fn unlock_unchecked(&self) -> &Self::Unlocked {
// SAFETY: the caller upholds the `Unlock` contract (mutation happens
// behind a write barrier); we forward that obligation to the inner
// `RefLock`'s `unlock_unchecked`.
unsafe { self.inner.unlock_unchecked() }
}
}
@@ -539,6 +593,10 @@ impl<'gc> Env<'gc> {
}
}
#[expect(
clippy::indexing_slicing,
reason = "`locals` was just created with `1 + n_locals` elements, so index 0 is always valid"
)]
pub fn with_arg(arg: Value<'gc>, n_locals: u32, prev: Gc<'gc, RefLock<Env<'gc>>>) -> Self {
let mut locals = smallvec::smallvec![Value::default(); 1 + n_locals as usize];
locals[0] = arg;
@@ -576,6 +634,18 @@ pub struct PrimOp {
pub dispatch_ip: u32,
}
impl From<BuiltinId> for PrimOp {
fn from(id: BuiltinId) -> Self {
let BuiltinInfo { arity, .. } = id.info();
let dispatch_ip = Continuation::entry_for_builtin(id).ip();
Self {
id,
arity,
dispatch_ip,
}
}
}
impl RawStore for PrimOp {
fn to_val(self, value: &mut RawValue) {
let bytes = self.dispatch_ip.to_le_bytes();