11use std:: cell:: Cell ;
22use std:: rc:: Rc ;
3+ use std:: sync:: Arc ;
34
45use mlua:: {
56 AnyUserData , Error , Function , Lua , MetaMethod , Result , String , UserData , UserDataFields ,
@@ -26,84 +27,13 @@ fn scope_func() -> Result<()> {
2627 assert_eq ! ( Rc :: strong_count( & rc) , 1 ) ;
2728
2829 match lua. globals ( ) . get :: < _ , Function > ( "bad" ) ?. call :: < _ , ( ) > ( ( ) ) {
29- Err ( Error :: CallbackError { .. } ) => { }
30- r => panic ! ( "improper return for destructed function: {:?}" , r) ,
31- } ;
32-
33- Ok ( ( ) )
34- }
35-
36- #[ test]
37- fn scope_drop ( ) -> Result < ( ) > {
38- let lua = Lua :: new ( ) ;
39-
40- struct MyUserdata ( Rc < ( ) > ) ;
41- impl UserData for MyUserdata {
42- fn add_methods < ' lua , M : UserDataMethods < ' lua , Self > > ( methods : & mut M ) {
43- methods. add_method ( "method" , |_, _, ( ) | Ok ( ( ) ) ) ;
44- }
45- }
46-
47- let rc = Rc :: new ( ( ) ) ;
48-
49- lua. scope ( |scope| {
50- lua. globals ( )
51- . set ( "static_ud" , scope. create_userdata ( MyUserdata ( rc. clone ( ) ) ) ?) ?;
52- assert_eq ! ( Rc :: strong_count( & rc) , 2 ) ;
53- Ok ( ( ) )
54- } ) ?;
55- assert_eq ! ( Rc :: strong_count( & rc) , 1 ) ;
56-
57- match lua. load ( "static_ud:method()" ) . exec ( ) {
58- Err ( Error :: CallbackError { ref cause, .. } ) => match cause. as_ref ( ) {
59- Error :: CallbackDestructed => { }
60- e => panic ! ( "expected CallbackDestructed, got {:?}" , e) ,
61- } ,
62- r => panic ! ( "improper return for destructed userdata: {:?}" , r) ,
63- } ;
64-
65- let static_ud = lua. globals ( ) . get :: < _ , AnyUserData > ( "static_ud" ) ?;
66- match static_ud. borrow :: < MyUserdata > ( ) {
67- Ok ( _) => panic ! ( "borrowed destructed userdata" ) ,
68- Err ( Error :: UserDataDestructed ) => { }
69- Err ( e) => panic ! ( "expected UserDataDestructed, got {:?}" , e) ,
70- }
71-
72- // Check non-static UserData drop
73- struct MyUserDataRef < ' a > ( & ' a Cell < i64 > ) ;
74-
75- impl < ' a > UserData for MyUserDataRef < ' a > {
76- fn add_methods < ' lua , M : UserDataMethods < ' lua , Self > > ( methods : & mut M ) {
77- methods. add_method ( "inc" , |_, data, ( ) | {
78- data. 0 . set ( data. 0 . get ( ) + 1 ) ;
79- Ok ( ( ) )
80- } ) ;
81- }
82- }
83-
84- let i = Cell :: new ( 1 ) ;
85- lua. scope ( |scope| {
86- lua. globals ( ) . set (
87- "nonstatic_ud" ,
88- scope. create_nonstatic_userdata ( MyUserDataRef ( & i) ) ?,
89- )
90- } ) ?;
91-
92- match lua. load ( "nonstatic_ud:inc(1)" ) . exec ( ) {
93- Err ( Error :: CallbackError { ref cause, .. } ) => match cause. as_ref ( ) {
30+ Err ( Error :: CallbackError { ref cause, .. } ) => match * cause. as_ref ( ) {
9431 Error :: CallbackDestructed => { }
95- e => panic ! ( "expected CallbackDestructed, got {:?}" , e ) ,
32+ ref err => panic ! ( "wrong error type {:?}" , err ) ,
9633 } ,
97- r => panic ! ( "improper return for destructed userdata : {:?}" , r) ,
34+ r => panic ! ( "improper return for destructed function : {:?}" , r) ,
9835 } ;
9936
100- let nonstatic_ud = lua. globals ( ) . get :: < _ , AnyUserData > ( "nonstatic_ud" ) ?;
101- match nonstatic_ud. borrow :: < MyUserDataRef > ( ) {
102- Ok ( _) => panic ! ( "borrowed destructed userdata" ) ,
103- Err ( Error :: UserDataDestructed ) => { }
104- Err ( e) => panic ! ( "expected UserDataDestructed, got {:?}" , e) ,
105- }
106-
10737 Ok ( ( ) )
10838}
10939
@@ -126,7 +56,7 @@ fn scope_capture() -> Result<()> {
12656}
12757
12858#[ test]
129- fn outer_lua_access ( ) -> Result < ( ) > {
59+ fn scope_outer_lua_access ( ) -> Result < ( ) > {
13060 let lua = Lua :: new ( ) ;
13161
13262 let table = lua. create_table ( ) ?;
@@ -309,3 +239,103 @@ fn scope_userdata_mismatch() -> Result<()> {
309239
310240 Ok ( ( ) )
311241}
242+
243+ #[ test]
244+ fn scope_userdata_drop ( ) -> Result < ( ) > {
245+ let lua = Lua :: new ( ) ;
246+
247+ struct MyUserData ( Rc < ( ) > ) ;
248+
249+ impl UserData for MyUserData {
250+ fn add_methods < ' lua , M : UserDataMethods < ' lua , Self > > ( methods : & mut M ) {
251+ methods. add_method ( "method" , |_, _, ( ) | Ok ( ( ) ) ) ;
252+ }
253+ }
254+
255+ struct MyUserDataArc ( Arc < ( ) > ) ;
256+
257+ impl UserData for MyUserDataArc { }
258+
259+ let rc = Rc :: new ( ( ) ) ;
260+ let arc = Arc :: new ( ( ) ) ;
261+ lua. scope ( |scope| {
262+ let ud = scope. create_userdata ( MyUserData ( rc. clone ( ) ) ) ?;
263+ ud. set_user_value ( MyUserDataArc ( arc. clone ( ) ) ) ?;
264+ lua. globals ( ) . set ( "ud" , ud) ?;
265+ assert_eq ! ( Rc :: strong_count( & rc) , 2 ) ;
266+ assert_eq ! ( Arc :: strong_count( & arc) , 2 ) ;
267+ Ok ( ( ) )
268+ } ) ?;
269+
270+ lua. gc_collect ( ) ?;
271+ assert_eq ! ( Rc :: strong_count( & rc) , 1 ) ;
272+ assert_eq ! ( Arc :: strong_count( & arc) , 1 ) ;
273+
274+ match lua. load ( "ud:method()" ) . exec ( ) {
275+ Err ( Error :: CallbackError { ref cause, .. } ) => match cause. as_ref ( ) {
276+ Error :: CallbackDestructed => { }
277+ err => panic ! ( "expected CallbackDestructed, got {:?}" , err) ,
278+ } ,
279+ r => panic ! ( "improper return for destructed userdata: {:?}" , r) ,
280+ } ;
281+
282+ let ud = lua. globals ( ) . get :: < _ , AnyUserData > ( "ud" ) ?;
283+ match ud. borrow :: < MyUserData > ( ) {
284+ Ok ( _) => panic ! ( "succesfull borrow for destructed userdata" ) ,
285+ Err ( Error :: UserDataDestructed ) => { }
286+ Err ( err) => panic ! ( "improper borrow error for destructed userdata: {:?}" , err) ,
287+ }
288+
289+ Ok ( ( ) )
290+ }
291+
292+ #[ test]
293+ fn scope_nonstatic_userdata_drop ( ) -> Result < ( ) > {
294+ let lua = Lua :: new ( ) ;
295+
296+ struct MyUserData < ' a > ( & ' a Cell < i64 > ) ;
297+
298+ impl < ' a > UserData for MyUserData < ' a > {
299+ fn add_methods < ' lua , M : UserDataMethods < ' lua , Self > > ( methods : & mut M ) {
300+ methods. add_method ( "inc" , |_, data, ( ) | {
301+ data. 0 . set ( data. 0 . get ( ) + 1 ) ;
302+ Ok ( ( ) )
303+ } ) ;
304+ }
305+ }
306+
307+ struct MyUserDataArc ( Arc < ( ) > ) ;
308+
309+ impl UserData for MyUserDataArc { }
310+
311+ let i = Cell :: new ( 1 ) ;
312+ let arc = Arc :: new ( ( ) ) ;
313+ lua. scope ( |scope| {
314+ let ud = scope. create_nonstatic_userdata ( MyUserData ( & i) ) ?;
315+ ud. set_user_value ( MyUserDataArc ( arc. clone ( ) ) ) ?;
316+ lua. globals ( ) . set ( "ud" , ud) ?;
317+ lua. load ( "ud:inc()" ) . exec ( ) ?;
318+ assert_eq ! ( Arc :: strong_count( & arc) , 2 ) ;
319+ Ok ( ( ) )
320+ } ) ?;
321+
322+ lua. gc_collect ( ) ?;
323+ assert_eq ! ( Arc :: strong_count( & arc) , 1 ) ;
324+
325+ match lua. load ( "ud:inc()" ) . exec ( ) {
326+ Err ( Error :: CallbackError { ref cause, .. } ) => match cause. as_ref ( ) {
327+ Error :: CallbackDestructed => { }
328+ err => panic ! ( "expected CallbackDestructed, got {:?}" , err) ,
329+ } ,
330+ r => panic ! ( "improper return for destructed userdata: {:?}" , r) ,
331+ } ;
332+
333+ let ud = lua. globals ( ) . get :: < _ , AnyUserData > ( "ud" ) ?;
334+ match ud. borrow :: < MyUserData > ( ) {
335+ Ok ( _) => panic ! ( "succesfull borrow for destructed userdata" ) ,
336+ Err ( Error :: UserDataDestructed ) => { }
337+ Err ( err) => panic ! ( "improper borrow error for destructed userdata: {:?}" , err) ,
338+ }
339+
340+ Ok ( ( ) )
341+ }
0 commit comments