From fbed171f905a7a0e8d6c89663e4ff23399d17dfe Mon Sep 17 00:00:00 2001 From: Alex Orlenko Date: Sat, 24 May 2025 10:18:16 +0100 Subject: [PATCH] Revert "Support 52-bit integers for Luau" This reverts commit ef8b8e11ec56d09dfc4e795687e2ec12fdc4c29a. --- mlua-sys/src/luau/compat.rs | 25 ------------------------- mlua-sys/src/luau/lauxlib.rs | 8 +++----- mlua-sys/src/luau/lua.rs | 20 ++++++++------------ src/conversion.rs | 36 +++++++++++++++++++++++++++++++----- src/luau/mod.rs | 2 +- src/value.rs | 5 +---- tests/tests.rs | 23 ----------------------- 7 files changed, 44 insertions(+), 75 deletions(-) diff --git a/mlua-sys/src/luau/compat.rs b/mlua-sys/src/luau/compat.rs index 4121293..d151330 100644 --- a/mlua-sys/src/luau/compat.rs +++ b/mlua-sys/src/luau/compat.rs @@ -127,11 +127,6 @@ pub unsafe fn lua_isinteger(L: *mut lua_State, idx: c_int) -> c_int { 0 } -#[inline(always)] -pub unsafe fn lua_pushinteger(L: *mut lua_State, i: lua_Integer) { - lua_pushnumber(L, i as lua_Number); -} - #[inline(always)] pub unsafe fn lua_tointeger(L: *mut lua_State, i: c_int) -> lua_Integer { lua_tointegerx(L, i, ptr::null_mut()) @@ -183,7 +178,6 @@ pub unsafe fn lua_geti(L: *mut lua_State, mut idx: c_int, n: lua_Integer) -> c_i #[inline(always)] pub unsafe fn lua_rawgeti(L: *mut lua_State, idx: c_int, n: lua_Integer) -> c_int { - let n = n.try_into().expect("cannot convert index from lua_Integer"); lua_rawgeti_(L, idx, n) } @@ -219,7 +213,6 @@ pub unsafe fn lua_seti(L: *mut lua_State, mut idx: c_int, n: lua_Integer) { #[inline(always)] pub unsafe fn lua_rawseti(L: *mut lua_State, idx: c_int, n: lua_Integer) { - let n = n.try_into().expect("cannot convert index from lua_Integer"); lua_rawseti_(L, idx, n) } @@ -322,24 +315,6 @@ pub unsafe fn luaL_checkstack(L: *mut lua_State, sz: c_int, msg: *const c_char) } } -#[inline(always)] -pub unsafe fn luaL_checkinteger(L: *mut lua_State, narg: c_int) -> lua_Integer { - let mut isnum = 0; - let int = lua_tointegerx(L, narg, &mut isnum); - if isnum == 0 { - luaL_typeerror(L, narg, lua_typename(L, LUA_TNUMBER)); - } - int -} - -pub unsafe fn luaL_optinteger(L: *mut lua_State, narg: c_int, def: lua_Integer) -> lua_Integer { - if lua_isnoneornil(L, narg) != 0 { - def - } else { - luaL_checkinteger(L, narg) - } -} - #[inline(always)] pub unsafe fn luaL_getmetafield(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int { if luaL_getmetafield_(L, obj, e) != 0 { diff --git a/mlua-sys/src/luau/lauxlib.rs b/mlua-sys/src/luau/lauxlib.rs index 845bb28..267490c 100644 --- a/mlua-sys/src/luau/lauxlib.rs +++ b/mlua-sys/src/luau/lauxlib.rs @@ -3,7 +3,7 @@ use std::os::raw::{c_char, c_float, c_int, c_void}; use std::ptr; -use super::lua::{self, lua_CFunction, lua_Number, lua_State, lua_Unsigned, LUA_REGISTRYINDEX}; +use super::lua::{self, lua_CFunction, lua_Integer, lua_Number, lua_State, lua_Unsigned, LUA_REGISTRYINDEX}; #[repr(C)] pub struct luaL_Reg { @@ -33,10 +33,8 @@ extern "C-unwind" { pub fn luaL_checkboolean(L: *mut lua_State, narg: c_int) -> c_int; pub fn luaL_optboolean(L: *mut lua_State, narg: c_int, def: c_int) -> c_int; - #[link_name = "luaL_checkinteger"] - pub fn luaL_checkinteger_(L: *mut lua_State, narg: c_int) -> c_int; - #[link_name = "luaL_optinteger"] - pub fn luaL_optinteger_(L: *mut lua_State, narg: c_int, def: c_int) -> c_int; + pub fn luaL_checkinteger(L: *mut lua_State, narg: c_int) -> lua_Integer; + pub fn luaL_optinteger(L: *mut lua_State, narg: c_int, def: lua_Integer) -> lua_Integer; pub fn luaL_checkunsigned(L: *mut lua_State, narg: c_int) -> lua_Unsigned; pub fn luaL_optunsigned(L: *mut lua_State, narg: c_int, def: lua_Unsigned) -> lua_Unsigned; diff --git a/mlua-sys/src/luau/lua.rs b/mlua-sys/src/luau/lua.rs index 017ea66..26a3eae 100644 --- a/mlua-sys/src/luau/lua.rs +++ b/mlua-sys/src/luau/lua.rs @@ -70,11 +70,8 @@ pub const LUA_MINSTACK: c_int = 20; /// A Lua number, usually equivalent to `f64`. pub type lua_Number = c_double; -/// A Lua integer, usually equivalent to `i64` -#[cfg(target_pointer_width = "32")] -pub type lua_Integer = i32; -#[cfg(target_pointer_width = "64")] -pub type lua_Integer = i64; +/// A Lua integer, equivalent to `i32`. +pub type lua_Integer = c_int; /// A Lua unsigned integer, equivalent to `u32`. pub type lua_Unsigned = c_uint; @@ -139,7 +136,7 @@ extern "C-unwind" { pub fn lua_tonumberx(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> lua_Number; #[link_name = "lua_tointegerx"] - pub fn lua_tointegerx_(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> c_int; + pub fn lua_tointegerx_(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> lua_Integer; pub fn lua_tounsignedx(L: *mut lua_State, idx: c_int, isnum: *mut c_int) -> lua_Unsigned; pub fn lua_tovector(L: *mut lua_State, idx: c_int) -> *const c_float; pub fn lua_toboolean(L: *mut lua_State, idx: c_int) -> c_int; @@ -163,8 +160,7 @@ extern "C-unwind" { // pub fn lua_pushnil(L: *mut lua_State); pub fn lua_pushnumber(L: *mut lua_State, n: lua_Number); - #[link_name = "lua_pushinteger"] - pub fn lua_pushinteger_(L: *mut lua_State, n: c_int); + pub fn lua_pushinteger(L: *mut lua_State, n: lua_Integer); pub fn lua_pushunsigned(L: *mut lua_State, n: lua_Unsigned); #[cfg(not(feature = "luau-vector4"))] pub fn lua_pushvector(L: *mut lua_State, x: c_float, y: c_float, z: c_float); @@ -314,13 +310,13 @@ extern "C-unwind" { // #[inline(always)] -pub unsafe fn lua_tonumber(L: *mut lua_State, idx: c_int) -> lua_Number { - lua_tonumberx(L, idx, ptr::null_mut()) +pub unsafe fn lua_tonumber(L: *mut lua_State, i: c_int) -> lua_Number { + lua_tonumberx(L, i, ptr::null_mut()) } #[inline(always)] -pub unsafe fn lua_tointeger_(L: *mut lua_State, idx: c_int) -> c_int { - lua_tointegerx_(L, idx, ptr::null_mut()) +pub unsafe fn lua_tointeger_(L: *mut lua_State, i: c_int) -> lua_Integer { + lua_tointegerx_(L, i, ptr::null_mut()) } #[inline(always)] diff --git a/src/conversion.rs b/src/conversion.rs index b7dfa30..2f64719 100644 --- a/src/conversion.rs +++ b/src/conversion.rs @@ -808,9 +808,15 @@ macro_rules! lua_convert_int { impl IntoLua for $x { #[inline] fn into_lua(self, _: &Lua) -> Result { - Ok(cast(self) + cast(self) .map(Value::Integer) - .unwrap_or_else(|| Value::Number(self as ffi::lua_Number))) + .or_else(|| cast(self).map(Value::Number)) + // This is impossible error because conversion to Number never fails + .ok_or_else(|| Error::ToLuaConversionError { + from: stringify!($x).to_string(), + to: "number", + message: Some("out of range".to_owned()), + }) } #[inline] @@ -893,7 +899,13 @@ macro_rules! lua_convert_float { impl IntoLua for $x { #[inline] fn into_lua(self, _: &Lua) -> Result { - Ok(Value::Number(self as _)) + cast(self) + .ok_or_else(|| Error::ToLuaConversionError { + from: stringify!($x).to_string(), + to: "number", + message: Some("out of range".to_string()), + }) + .map(Value::Number) } } @@ -902,19 +914,33 @@ macro_rules! lua_convert_float { fn from_lua(value: Value, lua: &Lua) -> Result { let ty = value.type_name(); lua.coerce_number(value)? - .map(|n| n as $x) .ok_or_else(|| Error::FromLuaConversionError { from: ty, to: stringify!($x).to_string(), message: Some("expected number or string coercible to number".to_string()), }) + .and_then(|n| { + cast(n).ok_or_else(|| Error::FromLuaConversionError { + from: ty, + to: stringify!($x).to_string(), + message: Some("number out of range".to_string()), + }) + }) } unsafe fn from_stack(idx: c_int, lua: &RawLua) -> Result { let state = lua.state(); let type_id = ffi::lua_type(state, idx); if type_id == ffi::LUA_TNUMBER { - return Ok(ffi::lua_tonumber(state, idx) as _); + let mut ok = 0; + let i = ffi::lua_tonumberx(state, idx, &mut ok); + if ok != 0 { + return cast(i).ok_or_else(|| Error::FromLuaConversionError { + from: "number", + to: stringify!($x).to_string(), + message: Some("out of range".to_owned()), + }); + } } // Fallback to default Self::from_lua(lua.stack_value(idx, Some(type_id)), lua.lua()) diff --git a/src/luau/mod.rs b/src/luau/mod.rs index 29427ed..b3935d3 100644 --- a/src/luau/mod.rs +++ b/src/luau/mod.rs @@ -51,7 +51,7 @@ unsafe extern "C-unwind" fn lua_collectgarbage(state: *mut ffi::lua_State) -> c_ 1 } Ok("step") => { - let res = ffi::lua_gc(state, ffi::LUA_GCSTEP, arg as _); + let res = ffi::lua_gc(state, ffi::LUA_GCSTEP, arg); ffi::lua_pushboolean(state, res); 1 } diff --git a/src/value.rs b/src/value.rs index 119f147..d77fddf 100644 --- a/src/value.rs +++ b/src/value.rs @@ -272,10 +272,7 @@ impl Value { /// If the value is a Lua [`Integer`], try to convert it to `i64` or return `None` otherwise. #[inline] pub fn as_i64(&self) -> Option { - #[cfg(target_pointer_width = "64")] - return self.as_integer(); - #[cfg(not(target_pointer_width = "64"))] - return self.as_integer().map(i64::from); + self.as_integer().map(i64::from) } /// Cast the value to `u64`. diff --git a/tests/tests.rs b/tests/tests.rs index d934ff7..4a00724 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -501,29 +501,6 @@ fn test_panic() -> Result<()> { Ok(()) } -#[cfg(target_pointer_width = "64")] -#[test] -fn test_safe_integers() -> Result<()> { - const MAX_SAFE_INTEGER: i64 = 2i64.pow(53) - 1; - const MIN_SAFE_INTEGER: i64 = -2i64.pow(53) + 1; - - let lua = Lua::new(); - let f = lua.load("return ...").into_function()?; - - assert_eq!(f.call::(MAX_SAFE_INTEGER)?, MAX_SAFE_INTEGER); - assert_eq!(f.call::(MIN_SAFE_INTEGER)?, MIN_SAFE_INTEGER); - - // For Lua versions that does not support 64-bit integers, the values will be converted to f64 - #[cfg(any(feature = "luau", feature = "lua51", feature = "luajit"))] - { - assert_ne!(f.call::(MAX_SAFE_INTEGER + 2)?, MAX_SAFE_INTEGER + 2); - assert_ne!(f.call::(MIN_SAFE_INTEGER - 2)?, MIN_SAFE_INTEGER - 2); - assert_eq!(f.call::(i64::MAX)?, i64::MAX as f64); - } - - Ok(()) -} - #[test] fn test_num_conversion() -> Result<()> { let lua = Lua::new();