@@ -2049,17 +2049,16 @@ impl Lua {
20492049 T : FromLua < ' lua > ,
20502050 {
20512051 let state = self . state ( ) ;
2052- let value = unsafe {
2052+ unsafe {
20532053 let _sg = StackGuard :: new ( state) ;
20542054 check_stack ( state, 3 ) ?;
20552055
20562056 let protect = !self . unlikely_memory_error ( ) ;
20572057 push_string ( state, name. as_bytes ( ) , protect) ?;
20582058 ffi:: lua_rawget ( state, ffi:: LUA_REGISTRYINDEX ) ;
20592059
2060- self . pop_value ( )
2061- } ;
2062- T :: from_lua ( value, self )
2060+ T :: from_stack ( -1 , self )
2061+ }
20632062 }
20642063
20652064 /// Removes a named value in the Lua registry.
@@ -2082,22 +2081,21 @@ impl Lua {
20822081 ///
20832082 /// [`RegistryKey`]: crate::RegistryKey
20842083 pub fn create_registry_value < ' lua , T : IntoLua < ' lua > > ( & ' lua self , t : T ) -> Result < RegistryKey > {
2085- let t = t. into_lua ( self ) ?;
2086- if t == Value :: Nil {
2087- // Special case to skip calling `luaL_ref` and use `LUA_REFNIL` instead
2088- let unref_list = unsafe { ( * self . extra . get ( ) ) . registry_unref_list . clone ( ) } ;
2089- return Ok ( RegistryKey :: new ( ffi:: LUA_REFNIL , unref_list) ) ;
2090- }
2091-
20922084 let state = self . state ( ) ;
20932085 unsafe {
20942086 let _sg = StackGuard :: new ( state) ;
20952087 check_stack ( state, 4 ) ?;
20962088
2097- self . push_value ( t) ?;
2089+ self . push ( t) ?;
20982090
2099- // Try to reuse previously allocated slot
21002091 let unref_list = ( * self . extra . get ( ) ) . registry_unref_list . clone ( ) ;
2092+
2093+ // Check if the value is nil (no need to store it in the registry)
2094+ if ffi:: lua_isnil ( state, -1 ) != 0 {
2095+ return Ok ( RegistryKey :: new ( ffi:: LUA_REFNIL , unref_list) ) ;
2096+ }
2097+
2098+ // Try to reuse previously allocated slot
21012099 let free_registry_id = mlua_expect ! ( unref_list. lock( ) , "unref list poisoned" )
21022100 . as_mut ( )
21032101 . and_then ( |x| x. pop ( ) ) ;
@@ -2107,7 +2105,7 @@ impl Lua {
21072105 return Ok ( RegistryKey :: new ( registry_id, unref_list) ) ;
21082106 }
21092107
2110- // Allocate a new RegistryKey
2108+ // Allocate a new RegistryKey slot
21112109 let registry_id = if self . unlikely_memory_error ( ) {
21122110 ffi:: luaL_ref ( state, ffi:: LUA_REGISTRYINDEX )
21132111 } else {
@@ -2131,18 +2129,16 @@ impl Lua {
21312129 }
21322130
21332131 let state = self . state ( ) ;
2134- let value = match key. is_nil ( ) {
2135- true => Value :: Nil ,
2136- false => unsafe {
2132+ match key. id ( ) {
2133+ ffi :: LUA_REFNIL => T :: from_lua ( Value :: Nil , self ) ,
2134+ registry_id => unsafe {
21372135 let _sg = StackGuard :: new ( state) ;
21382136 check_stack ( state, 1 ) ?;
21392137
2140- let id = key. registry_id as Integer ;
2141- ffi:: lua_rawgeti ( state, ffi:: LUA_REGISTRYINDEX , id) ;
2142- self . pop_value ( )
2138+ ffi:: lua_rawgeti ( state, ffi:: LUA_REGISTRYINDEX , registry_id as Integer ) ;
2139+ T :: from_stack ( -1 , self )
21432140 } ,
2144- } ;
2145- T :: from_lua ( value, self )
2141+ }
21462142 }
21472143
21482144 /// Removes a value from the Lua registry.
@@ -2180,29 +2176,32 @@ impl Lua {
21802176 }
21812177
21822178 let t = t. into_lua ( self ) ?;
2183- if t == Value :: Nil && key. is_nil ( ) {
2184- // Nothing to replace
2185- return Ok ( ( ) ) ;
2186- } else if t != Value :: Nil && key. registry_id == ffi:: LUA_REFNIL {
2187- // We cannot update `LUA_REFNIL` slot
2188- return Err ( Error :: runtime ( "cannot replace nil value with non-nil" ) ) ;
2189- }
21902179
21912180 let state = self . state ( ) ;
21922181 unsafe {
21932182 let _sg = StackGuard :: new ( state) ;
21942183 check_stack ( state, 2 ) ?;
21952184
2196- let id = key. registry_id as Integer ;
2197- if t == Value :: Nil {
2198- self . push_value ( Value :: Integer ( id) ) ?;
2199- key. set_nil ( true ) ;
2200- } else {
2201- self . push_value ( t) ?;
2202- key. set_nil ( false ) ;
2185+ match ( t, key. id ( ) ) {
2186+ ( Value :: Nil , ffi:: LUA_REFNIL ) => {
2187+ // Do nothing, no need to replace nil with nil
2188+ }
2189+ ( Value :: Nil , registry_id) => {
2190+ // Remove the value
2191+ ffi:: luaL_unref ( state, ffi:: LUA_REGISTRYINDEX , registry_id) ;
2192+ key. set_id ( ffi:: LUA_REFNIL ) ;
2193+ }
2194+ ( value, ffi:: LUA_REFNIL ) => {
2195+ // Allocate a new `RegistryKey`
2196+ let new_key = self . create_registry_value ( value) ?;
2197+ key. set_id ( new_key. take ( ) ) ;
2198+ }
2199+ ( value, registry_id) => {
2200+ // It must be safe to replace the value without triggering memory error
2201+ self . push_value ( value) ?;
2202+ ffi:: lua_rawseti ( state, ffi:: LUA_REGISTRYINDEX , registry_id as Integer ) ;
2203+ }
22032204 }
2204- // It must be safe to replace the value without triggering memory error
2205- ffi:: lua_rawseti ( state, ffi:: LUA_REGISTRYINDEX , id) ;
22062205 }
22072206 Ok ( ( ) )
22082207 }
0 commit comments