xref: /wasmtime-44.0.1/tests/all/structs.rs (revision c22b3cb9)
1 use super::gc_store;
2 use wasmtime::*;
3 use wasmtime_test_macros::wasmtime_test;
4 
5 #[test]
struct_new_empty() -> Result<()>6 fn struct_new_empty() -> Result<()> {
7     let mut store = gc_store()?;
8     let struct_ty = StructType::new(store.engine(), [])?;
9     let pre = StructRefPre::new(&mut store, struct_ty);
10     StructRef::new(&mut store, &pre, &[])?;
11     Ok(())
12 }
13 
14 #[test]
struct_new_with_fields() -> Result<()>15 fn struct_new_with_fields() -> Result<()> {
16     let mut store = gc_store()?;
17     let struct_ty = StructType::new(
18         store.engine(),
19         [
20             FieldType::new(Mutability::Const, StorageType::I8),
21             FieldType::new(Mutability::Const, StorageType::ValType(ValType::I32)),
22             FieldType::new(Mutability::Var, StorageType::ValType(ValType::ANYREF)),
23         ],
24     )?;
25     let pre = StructRefPre::new(&mut store, struct_ty);
26     StructRef::new(
27         &mut store,
28         &pre,
29         &[Val::I32(1), Val::I32(2), Val::null_any_ref()],
30     )?;
31     Ok(())
32 }
33 
34 #[test]
struct_new_unrooted_field() -> Result<()>35 fn struct_new_unrooted_field() -> Result<()> {
36     let mut store = gc_store()?;
37     let struct_ty = StructType::new(
38         store.engine(),
39         [FieldType::new(
40             Mutability::Var,
41             StorageType::ValType(ValType::ANYREF),
42         )],
43     )?;
44     // Passing an unrooted `anyref` to `StructRef::new` results in an error.
45     let anyref = {
46         let mut scope = RootScope::new(&mut store);
47         AnyRef::from_i31(&mut scope, I31::new_i32(1234).unwrap())
48     };
49     assert!(anyref.is_i31(&store).is_err());
50     let pre = StructRefPre::new(&mut store, struct_ty);
51     assert!(StructRef::new(&mut store, &pre, &[anyref.into()]).is_err());
52     Ok(())
53 }
54 
55 #[test]
56 #[should_panic = "wrong store"]
struct_new_cross_store_field()57 fn struct_new_cross_store_field() {
58     let mut store = gc_store().unwrap();
59     let struct_ty = StructType::new(
60         store.engine(),
61         [FieldType::new(
62             Mutability::Var,
63             StorageType::ValType(ValType::ANYREF),
64         )],
65     )
66     .unwrap();
67 
68     let mut other_store = gc_store().unwrap();
69     let anyref = AnyRef::from_i31(&mut other_store, I31::new_i32(1234).unwrap());
70 
71     let pre = StructRefPre::new(&mut store, struct_ty);
72 
73     // This should panic.
74     let _ = StructRef::new(&mut store, &pre, &[anyref.into()]);
75 }
76 
77 #[test]
78 #[should_panic = "wrong store"]
struct_new_cross_store_pre()79 fn struct_new_cross_store_pre() {
80     let mut store = gc_store().unwrap();
81     let struct_ty = StructType::new(store.engine(), []).unwrap();
82 
83     let mut other_store = gc_store().unwrap();
84     let pre = StructRefPre::new(&mut other_store, struct_ty);
85 
86     // This should panic.
87     let _ = StructRef::new(&mut store, &pre, &[]);
88 }
89 
90 #[test]
anyref_as_struct() -> Result<()>91 fn anyref_as_struct() -> Result<()> {
92     let mut store = gc_store()?;
93 
94     let struct_ty = StructType::new(
95         store.engine(),
96         [FieldType::new(Mutability::Const, StorageType::I8)],
97     )?;
98     let pre = StructRefPre::new(&mut store, struct_ty.clone());
99     let s0 = StructRef::new(&mut store, &pre, &[Val::I32(42)])?;
100 
101     let anyref: Rooted<AnyRef> = s0.into();
102     assert!(anyref.is_struct(&store)?);
103     let s1 = anyref.as_struct(&store)?.unwrap();
104     assert_eq!(s1.field(&mut store, 0)?.unwrap_i32(), 42);
105     assert!(Rooted::ref_eq(&store, &s0, &s1)?);
106 
107     let anyref: Rooted<AnyRef> = AnyRef::from_i31(&mut store, I31::new_i32(42).unwrap());
108     assert!(!anyref.is_struct(&store)?);
109     assert!(anyref.as_struct(&store)?.is_none());
110 
111     Ok(())
112 }
113 
114 #[test]
struct_field_simple() -> Result<()>115 fn struct_field_simple() -> Result<()> {
116     let mut store = gc_store()?;
117     let struct_ty = StructType::new(
118         store.engine(),
119         [FieldType::new(
120             Mutability::Var,
121             StorageType::ValType(ValType::I32),
122         )],
123     )?;
124     let pre = StructRefPre::new(&mut store, struct_ty);
125     let s = StructRef::new(&mut store, &pre, &[Val::I32(1234)])?;
126     let val = s.field(&mut store, 0)?;
127     assert_eq!(val.unwrap_i32(), 1234);
128     Ok(())
129 }
130 
131 #[test]
struct_field_out_of_bounds() -> Result<()>132 fn struct_field_out_of_bounds() -> Result<()> {
133     let mut store = gc_store()?;
134     let struct_ty = StructType::new(
135         store.engine(),
136         [FieldType::new(
137             Mutability::Var,
138             StorageType::ValType(ValType::I32),
139         )],
140     )?;
141     let pre = StructRefPre::new(&mut store, struct_ty);
142     let s = StructRef::new(&mut store, &pre, &[Val::I32(1234)])?;
143     assert!(s.field(&mut store, 1).is_err());
144     Ok(())
145 }
146 
147 #[test]
struct_field_on_unrooted() -> Result<()>148 fn struct_field_on_unrooted() -> Result<()> {
149     let mut store = gc_store()?;
150     let struct_ty = StructType::new(
151         store.engine(),
152         [FieldType::new(
153             Mutability::Var,
154             StorageType::ValType(ValType::I32),
155         )],
156     )?;
157     let pre = StructRefPre::new(&mut store, struct_ty);
158     let s = {
159         let mut scope = RootScope::new(&mut store);
160         StructRef::new(&mut scope, &pre, &[Val::I32(1234)])?
161     };
162     // The root scope ended and unrooted `s`.
163     assert!(s.field(&mut store, 0).is_err());
164     Ok(())
165 }
166 
167 #[test]
struct_set_field_simple() -> Result<()>168 fn struct_set_field_simple() -> Result<()> {
169     let mut store = gc_store()?;
170     let struct_ty = StructType::new(
171         store.engine(),
172         [FieldType::new(
173             Mutability::Var,
174             StorageType::ValType(ValType::I32),
175         )],
176     )?;
177     let pre = StructRefPre::new(&mut store, struct_ty);
178     let s = StructRef::new(&mut store, &pre, &[Val::I32(1234)])?;
179     s.set_field(&mut store, 0, Val::I32(5678))?;
180     let val = s.field(&mut store, 0)?;
181     assert_eq!(val.unwrap_i32(), 5678);
182     Ok(())
183 }
184 
185 #[test]
struct_set_field_out_of_bounds() -> Result<()>186 fn struct_set_field_out_of_bounds() -> Result<()> {
187     let mut store = gc_store()?;
188     let struct_ty = StructType::new(
189         store.engine(),
190         [FieldType::new(
191             Mutability::Var,
192             StorageType::ValType(ValType::I32),
193         )],
194     )?;
195     let pre = StructRefPre::new(&mut store, struct_ty);
196     let s = StructRef::new(&mut store, &pre, &[Val::I32(1234)])?;
197     assert!(s.set_field(&mut store, 1, Val::I32(1)).is_err());
198     Ok(())
199 }
200 
201 #[test]
struct_set_field_on_unrooted() -> Result<()>202 fn struct_set_field_on_unrooted() -> Result<()> {
203     let mut store = gc_store()?;
204     let struct_ty = StructType::new(
205         store.engine(),
206         [FieldType::new(
207             Mutability::Var,
208             StorageType::ValType(ValType::I32),
209         )],
210     )?;
211     let pre = StructRefPre::new(&mut store, struct_ty);
212     let s = {
213         let mut scope = RootScope::new(&mut store);
214         StructRef::new(&mut scope, &pre, &[Val::I32(1234)])?
215     };
216     // The root scope ended and unrooted `s`.
217     assert!(s.set_field(&mut store, 0, Val::I32(1)).is_err());
218     Ok(())
219 }
220 
221 #[test]
struct_set_field_with_unrooted() -> Result<()>222 fn struct_set_field_with_unrooted() -> Result<()> {
223     let mut store = gc_store()?;
224     let struct_ty = StructType::new(
225         store.engine(),
226         [FieldType::new(
227             Mutability::Var,
228             StorageType::ValType(ValType::ANYREF),
229         )],
230     )?;
231     let pre = StructRefPre::new(&mut store, struct_ty);
232     let s = StructRef::new(&mut store, &pre, &[Val::null_any_ref()])?;
233     let anyref = {
234         let mut scope = RootScope::new(&mut store);
235         AnyRef::from_i31(&mut scope, I31::wrapping_i32(42))
236     };
237     // The root scope ended and `anyref` is unrooted.
238     assert!(s.set_field(&mut store, 0, anyref.into()).is_err());
239     Ok(())
240 }
241 
242 #[test]
struct_set_field_cross_store_value() -> Result<()>243 fn struct_set_field_cross_store_value() -> Result<()> {
244     let mut store = gc_store()?;
245     let struct_ty = StructType::new(
246         store.engine(),
247         [FieldType::new(
248             Mutability::Var,
249             StorageType::ValType(ValType::EXTERNREF),
250         )],
251     )?;
252     let pre = StructRefPre::new(&mut store, struct_ty);
253     let s = StructRef::new(&mut store, &pre, &[Val::null_extern_ref()])?;
254 
255     let mut other_store = gc_store()?;
256     let externref = ExternRef::new(&mut other_store, "blah")?;
257 
258     assert!(s.set_field(&mut store, 0, externref.into()).is_err());
259     Ok(())
260 }
261 
262 #[test]
struct_set_field_immutable() -> Result<()>263 fn struct_set_field_immutable() -> Result<()> {
264     let mut store = gc_store()?;
265     let struct_ty = StructType::new(
266         store.engine(),
267         [FieldType::new(
268             Mutability::Const,
269             StorageType::ValType(ValType::I32),
270         )],
271     )?;
272     let pre = StructRefPre::new(&mut store, struct_ty);
273     let s = StructRef::new(&mut store, &pre, &[Val::I32(1234)])?;
274     assert!(s.set_field(&mut store, 0, Val::I32(5678)).is_err());
275     Ok(())
276 }
277 
278 #[test]
struct_set_field_wrong_type() -> Result<()>279 fn struct_set_field_wrong_type() -> Result<()> {
280     let mut store = gc_store()?;
281     let struct_ty = StructType::new(
282         store.engine(),
283         [FieldType::new(
284             Mutability::Const,
285             StorageType::ValType(ValType::I32),
286         )],
287     )?;
288     let pre = StructRefPre::new(&mut store, struct_ty);
289     let s = StructRef::new(&mut store, &pre, &[Val::I32(1234)])?;
290     assert!(s.set_field(&mut store, 0, Val::I64(5678)).is_err());
291     Ok(())
292 }
293 
294 #[test]
struct_ty() -> Result<()>295 fn struct_ty() -> Result<()> {
296     let mut store = gc_store()?;
297     let struct_ty = StructType::new(store.engine(), [])?;
298     let pre = StructRefPre::new(&mut store, struct_ty.clone());
299     let s = StructRef::new(&mut store, &pre, &[])?;
300     assert!(StructType::eq(&struct_ty, &s.ty(&store)?));
301     Ok(())
302 }
303 
304 #[test]
struct_ty_unrooted() -> Result<()>305 fn struct_ty_unrooted() -> Result<()> {
306     let mut store = gc_store()?;
307     let struct_ty = StructType::new(store.engine(), [])?;
308     let pre = StructRefPre::new(&mut store, struct_ty);
309     let s = {
310         let mut scope = RootScope::new(&mut store);
311         StructRef::new(&mut scope, &pre, &[])?
312     };
313     // The root scope ended and `s` is unrooted.
314     assert!(s.ty(&mut store).is_err());
315     Ok(())
316 }
317 
318 #[test]
struct_fields_empty() -> Result<()>319 fn struct_fields_empty() -> Result<()> {
320     let mut store = gc_store()?;
321     let struct_ty = StructType::new(store.engine(), [])?;
322     let pre = StructRefPre::new(&mut store, struct_ty.clone());
323     let s = StructRef::new(&mut store, &pre, &[])?;
324     let fields = s.fields(&mut store)?;
325     assert_eq!(fields.len(), 0);
326     assert!(fields.collect::<Vec<_>>().is_empty());
327     Ok(())
328 }
329 
330 #[test]
struct_fields_non_empty() -> Result<()>331 fn struct_fields_non_empty() -> Result<()> {
332     let mut store = gc_store()?;
333     let struct_ty = StructType::new(
334         store.engine(),
335         [
336             FieldType::new(Mutability::Const, StorageType::I8),
337             FieldType::new(Mutability::Var, StorageType::ValType(ValType::ANYREF)),
338         ],
339     )?;
340     let pre = StructRefPre::new(&mut store, struct_ty.clone());
341     let s = StructRef::new(&mut store, &pre, &[Val::I32(36), Val::null_any_ref()])?;
342     let mut fields = s.fields(&mut store)?;
343     assert_eq!(fields.len(), 2);
344     assert_eq!(fields.next().unwrap().unwrap_i32(), 36);
345     assert!(fields.next().unwrap().unwrap_any_ref().is_none());
346     assert!(fields.next().is_none());
347     Ok(())
348 }
349 
350 #[test]
struct_fields_unrooted() -> Result<()>351 fn struct_fields_unrooted() -> Result<()> {
352     let mut store = gc_store()?;
353     let struct_ty = StructType::new(store.engine(), [])?;
354     let pre = StructRefPre::new(&mut store, struct_ty);
355     let s = {
356         let mut scope = RootScope::new(&mut store);
357         StructRef::new(&mut scope, &pre, &[])?
358     };
359     // The root scope ended and `s` is unrooted.
360     assert!(s.fields(&mut store).is_err());
361     Ok(())
362 }
363 
364 #[test]
365 #[cfg_attr(miri, ignore)]
passing_structs_through_wasm_with_untyped_calls() -> Result<()>366 fn passing_structs_through_wasm_with_untyped_calls() -> Result<()> {
367     let mut store = gc_store()?;
368 
369     let module = Module::new(
370         store.engine(),
371         r#"
372             (module
373                 (type (struct (field i8)))
374                 (import "" "" (func $f (param (ref 0)) (result (ref 0))))
375                 (func (export "run") (param (ref 0)) (result (ref 0))
376                     (call $f (local.get 0))
377                 )
378             )
379         "#,
380     )?;
381 
382     let struct_ty = StructType::new(
383         store.engine(),
384         [FieldType::new(Mutability::Const, StorageType::I8)],
385     )?;
386 
387     let ref_ty = RefType::new(false, HeapType::ConcreteStruct(struct_ty.clone()));
388     let func_ty = FuncType::new(store.engine(), [ref_ty.clone().into()], [ref_ty.into()]);
389 
390     let func = Func::new(&mut store, func_ty, |mut caller, args, results| {
391         let s = args[0].unwrap_any_ref().unwrap();
392         let s = s.unwrap_struct(&mut caller)?;
393         assert_eq!(s.field(&mut caller, 0)?.unwrap_i32(), 42);
394         results[0] = args[0];
395         Ok(())
396     });
397 
398     let instance = Instance::new(&mut store, &module, &[func.into()])?;
399     let run = instance.get_func(&mut store, "run").unwrap();
400 
401     let pre = StructRefPre::new(&mut store, struct_ty.clone());
402     let s = StructRef::new(&mut store, &pre, &[Val::I32(42)])?;
403 
404     let mut results = vec![Val::null_any_ref()];
405     run.call(&mut store, &[s.into()], &mut results)?;
406 
407     let t = results[0].unwrap_any_ref().unwrap();
408     let t = t.unwrap_struct(&mut store)?;
409     assert_eq!(t.field(&mut store, 0)?.unwrap_i32(), 42);
410     assert!(Rooted::ref_eq(&store, &s, &t)?);
411 
412     Ok(())
413 }
414 
415 #[test]
416 #[cfg_attr(miri, ignore)]
passing_structs_through_wasm_with_typed_calls() -> Result<()>417 fn passing_structs_through_wasm_with_typed_calls() -> Result<()> {
418     let mut store = gc_store()?;
419 
420     let module = Module::new(
421         store.engine(),
422         r#"
423             (module
424                 (type (struct (field i8)))
425                 (import "" "" (func $f (param (ref struct)) (result (ref struct))))
426                 (func (export "run") (param (ref 0)) (result (ref struct))
427                     (call $f (local.get 0))
428                 )
429             )
430         "#,
431     )?;
432 
433     let struct_ty = StructType::new(
434         store.engine(),
435         [FieldType::new(Mutability::Const, StorageType::I8)],
436     )?;
437 
438     let func = Func::wrap(
439         &mut store,
440         |mut caller: Caller<()>, s: Rooted<StructRef>| -> Result<Rooted<StructRef>> {
441             assert_eq!(s.field(&mut caller, 0)?.unwrap_i32(), 42);
442             Ok(s)
443         },
444     );
445 
446     let instance = Instance::new(&mut store, &module, &[func.into()])?;
447     let run = instance.get_typed_func::<Rooted<StructRef>, Rooted<StructRef>>(&mut store, "run")?;
448 
449     let pre = StructRefPre::new(&mut store, struct_ty.clone());
450     let s = StructRef::new(&mut store, &pre, &[Val::I32(42)])?;
451 
452     let t = run.call(&mut store, s)?;
453 
454     assert_eq!(t.field(&mut store, 0)?.unwrap_i32(), 42);
455     assert!(Rooted::ref_eq(&store, &s, &t)?);
456 
457     Ok(())
458 }
459 
460 #[test]
461 #[cfg_attr(miri, ignore)]
host_sets_struct_global() -> Result<()>462 fn host_sets_struct_global() -> Result<()> {
463     let mut store = gc_store()?;
464 
465     let module = Module::new(
466         store.engine(),
467         r#"
468             (module
469                 (type (struct (field i8)))
470                 (global $g (export "g") (mut (ref null 0)) (ref.null 0))
471                 (func (export "f") (result (ref null 0))
472                     global.get $g
473                 )
474             )
475         "#,
476     )?;
477 
478     let instance = Instance::new(&mut store, &module, &[])?;
479     let g = instance.get_global(&mut store, "g").unwrap();
480 
481     let struct_ty = StructType::new(
482         store.engine(),
483         [FieldType::new(Mutability::Const, StorageType::I8)],
484     )?;
485     let pre = StructRefPre::new(&mut store, struct_ty.clone());
486     let s0 = StructRef::new(&mut store, &pre, &[Val::I32(42)])?;
487     g.set(&mut store, s0.into())?;
488 
489     // Get the global from the host.
490     let val = g.get(&mut store);
491     let anyref = val.unwrap_anyref().expect("non-null");
492     let s1 = anyref.unwrap_struct(&store)?;
493     assert_eq!(s1.field(&mut store, 0)?.unwrap_i32(), 42);
494     assert!(Rooted::ref_eq(&store, &s0, &s1)?);
495 
496     // Get the global from the guest.
497     let f = instance.get_typed_func::<(), Option<Rooted<StructRef>>>(&mut store, "f")?;
498     let s2 = f.call(&mut store, ())?.expect("non-null");
499     assert_eq!(s2.field(&mut store, 0)?.unwrap_i32(), 42);
500     assert!(Rooted::ref_eq(&store, &s0, &s2)?);
501 
502     Ok(())
503 }
504 
505 #[test]
506 #[cfg_attr(miri, ignore)]
wasm_sets_struct_global() -> Result<()>507 fn wasm_sets_struct_global() -> Result<()> {
508     let mut store = gc_store()?;
509 
510     let module = Module::new(
511         store.engine(),
512         r#"
513             (module
514                 (type (struct (field i8)))
515                 (global $g (export "g") (mut (ref null 0)) (ref.null 0))
516                 (func (export "get") (result (ref null 0))
517                     global.get $g
518                 )
519                 (func (export "set") (param (ref null 0))
520                     local.get 0
521                     global.set $g
522                 )
523             )
524         "#,
525     )?;
526 
527     let struct_ty = StructType::new(
528         store.engine(),
529         [FieldType::new(Mutability::Const, StorageType::I8)],
530     )?;
531     let pre = StructRefPre::new(&mut store, struct_ty.clone());
532     let s0 = StructRef::new(&mut store, &pre, &[Val::I32(42)])?;
533 
534     let instance = Instance::new(&mut store, &module, &[])?;
535     let set = instance.get_func(&mut store, "set").unwrap();
536     set.call(&mut store, &[s0.into()], &mut [])?;
537 
538     // Get the global from the host.
539     let g = instance.get_global(&mut store, "g").unwrap();
540     let val = g.get(&mut store);
541     let anyref = val.unwrap_anyref().expect("non-null");
542     let s1 = anyref.unwrap_struct(&store)?;
543     assert_eq!(s1.field(&mut store, 0)?.unwrap_i32(), 42);
544     assert!(Rooted::ref_eq(&store, &s0, &s1)?);
545 
546     // Get the global from the guest.
547     let f = instance.get_typed_func::<(), Option<Rooted<StructRef>>>(&mut store, "get")?;
548     let s2 = f.call(&mut store, ())?.expect("non-null");
549     assert_eq!(s2.field(&mut store, 0)?.unwrap_i32(), 42);
550     assert!(Rooted::ref_eq(&store, &s0, &s2)?);
551 
552     Ok(())
553 }
554 
555 #[test]
556 #[cfg_attr(miri, ignore)]
host_sets_struct_in_table() -> Result<()>557 fn host_sets_struct_in_table() -> Result<()> {
558     let mut store = gc_store()?;
559 
560     let module = Module::new(
561         store.engine(),
562         r#"
563             (module
564                 (type (struct (field i8)))
565                 (table $t (export "t") 1 1 (ref null 0) (ref.null 0))
566                 (func (export "f") (result (ref null 0))
567                     i32.const 0
568                     table.get $t
569                 )
570             )
571         "#,
572     )?;
573 
574     let instance = Instance::new(&mut store, &module, &[])?;
575     let t = instance.get_table(&mut store, "t").unwrap();
576 
577     let struct_ty = StructType::new(
578         store.engine(),
579         [FieldType::new(Mutability::Const, StorageType::I8)],
580     )?;
581     let pre = StructRefPre::new(&mut store, struct_ty.clone());
582     let s0 = StructRef::new(&mut store, &pre, &[Val::I32(42)])?;
583     t.set(&mut store, 0, s0.into())?;
584 
585     // Get the global from the host.
586     let val = t.get(&mut store, 0).expect("in bounds");
587     let anyref = val.unwrap_any().expect("non-null");
588     let s1 = anyref.unwrap_struct(&store)?;
589     assert_eq!(s1.field(&mut store, 0)?.unwrap_i32(), 42);
590     assert!(Rooted::ref_eq(&store, &s0, &s1)?);
591 
592     // Get the global from the guest.
593     let f = instance.get_typed_func::<(), Option<Rooted<StructRef>>>(&mut store, "f")?;
594     let s2 = f.call(&mut store, ())?.expect("non-null");
595     assert_eq!(s2.field(&mut store, 0)?.unwrap_i32(), 42);
596     assert!(Rooted::ref_eq(&store, &s0, &s2)?);
597 
598     Ok(())
599 }
600 
601 #[test]
602 #[cfg_attr(miri, ignore)]
wasm_sets_struct_in_table() -> Result<()>603 fn wasm_sets_struct_in_table() -> Result<()> {
604     let mut store = gc_store()?;
605 
606     let module = Module::new(
607         store.engine(),
608         r#"
609             (module
610                 (type (struct (field i8)))
611                 (table $t (export "t") 1 1 (ref null 0) (ref.null 0))
612                 (func (export "get") (result (ref null 0))
613                     i32.const 0
614                     table.get $t
615                 )
616                 (func (export "set") (param (ref null 0))
617                     i32.const 0
618                     local.get 0
619                     table.set $t
620                 )
621             )
622         "#,
623     )?;
624 
625     let struct_ty = StructType::new(
626         store.engine(),
627         [FieldType::new(Mutability::Const, StorageType::I8)],
628     )?;
629     let pre = StructRefPre::new(&mut store, struct_ty.clone());
630     let s0 = StructRef::new(&mut store, &pre, &[Val::I32(42)])?;
631 
632     let instance = Instance::new(&mut store, &module, &[])?;
633     let set = instance.get_func(&mut store, "set").unwrap();
634     set.call(&mut store, &[s0.into()], &mut [])?;
635 
636     // Get the global from the host.
637     let t = instance.get_table(&mut store, "t").unwrap();
638     let val = t.get(&mut store, 0).expect("in bounds");
639     let anyref = val.unwrap_any().expect("non-null");
640     let s1 = anyref.unwrap_struct(&store)?;
641     assert_eq!(s1.field(&mut store, 0)?.unwrap_i32(), 42);
642     assert!(Rooted::ref_eq(&store, &s0, &s1)?);
643 
644     // Get the global from the guest.
645     let f = instance.get_typed_func::<(), Option<Rooted<StructRef>>>(&mut store, "get")?;
646     let s2 = f.call(&mut store, ())?.expect("non-null");
647     assert_eq!(s2.field(&mut store, 0)?.unwrap_i32(), 42);
648     assert!(Rooted::ref_eq(&store, &s0, &s2)?);
649 
650     Ok(())
651 }
652 
653 #[test]
instantiate_with_struct_global() -> Result<()>654 fn instantiate_with_struct_global() -> Result<()> {
655     let mut store = gc_store()?;
656 
657     let module = Module::new(
658         store.engine(),
659         r#"
660             (module
661                 (type (struct (field i8)))
662                 (import "" "" (global (ref null 0)))
663                 (export "g" (global 0))
664             )
665         "#,
666     )?;
667 
668     let struct_ty = StructType::new(
669         store.engine(),
670         [FieldType::new(Mutability::Const, StorageType::I8)],
671     )?;
672     let global_ty = GlobalType::new(
673         ValType::Ref(RefType::new(
674             true,
675             HeapType::ConcreteStruct(struct_ty.clone()),
676         )),
677         Mutability::Const,
678     );
679 
680     // Instantiate with a null-ref global.
681     let g = Global::new(&mut store, global_ty.clone(), Val::AnyRef(None))?;
682     let instance = Instance::new(&mut store, &module, &[g.into()])?;
683     let g = instance.get_global(&mut store, "g").expect("export exists");
684     let val = g.get(&mut store);
685     assert!(val.unwrap_anyref().is_none());
686 
687     // Instantiate with a non-null-ref global.
688     let pre = StructRefPre::new(&mut store, struct_ty);
689     let s0 = StructRef::new(&mut store, &pre, &[Val::I32(42)])?;
690     let g = Global::new(&mut store, global_ty, s0.into())?;
691     let instance = Instance::new(&mut store, &module, &[g.into()])?;
692     let g = instance.get_global(&mut store, "g").expect("export exists");
693     let val = g.get(&mut store);
694     let anyref = val.unwrap_anyref().expect("non-null");
695     let s1 = anyref.unwrap_struct(&store)?;
696     assert_eq!(s1.field(&mut store, 0)?.unwrap_i32(), 42);
697     assert!(Rooted::ref_eq(&store, &s0, &s1)?);
698 
699     Ok(())
700 }
701 
702 #[test]
can_put_funcrefs_in_structs() -> Result<()>703 fn can_put_funcrefs_in_structs() -> Result<()> {
704     let mut store = gc_store()?;
705 
706     let struct_ty = StructType::new(
707         store.engine(),
708         [FieldType::new(Mutability::Var, RefType::FUNCREF.into())],
709     )?;
710 
711     let f0 = Func::wrap(&mut store, |_caller: Caller<()>| -> u32 { 0x1234 });
712     let f1 = Func::wrap(&mut store, |_caller: Caller<()>| -> u32 { 0x5678 });
713 
714     let pre = StructRefPre::new(&mut store, struct_ty.clone());
715     let s = StructRef::new(&mut store, &pre, &[f0.into()])?;
716 
717     let f = s.field(&mut store, 0)?;
718     let f = f.unwrap_funcref().unwrap();
719     let f = f.typed::<(), u32>(&store)?;
720     assert_eq!(f.call(&mut store, ())?, 0x1234);
721 
722     s.set_field(&mut store, 0, f1.into())?;
723 
724     let f = s.field(&mut store, 0)?;
725     let f = f.unwrap_funcref().unwrap();
726     let f = f.typed::<(), u32>(&store)?;
727     assert_eq!(f.call(&mut store, ())?, 0x5678);
728 
729     Ok(())
730 }
731 
732 #[test]
733 #[cfg_attr(miri, ignore)]
struct_ref_struct_in_same_rec_group_in_global() -> Result<()>734 fn struct_ref_struct_in_same_rec_group_in_global() -> Result<()> {
735     let mut store = gc_store()?;
736     let module = Module::new(
737         store.engine(),
738         r#"
739             (module
740                 (rec
741                     (type $b (struct))
742                     (type $a (struct (field (ref $b))))
743                 )
744                 (global (ref $a)
745                     struct.new_default $b
746                     struct.new $a
747                 )
748             )
749         "#,
750     )?;
751     let _instance = Instance::new(&mut store, &module, &[])?;
752     Ok(())
753 }
754 
755 #[wasmtime_test(wasm_features(function_references, gc))]
756 #[cfg_attr(miri, ignore)]
issue_9714(config: &mut Config) -> Result<()>757 fn issue_9714(config: &mut Config) -> Result<()> {
758     let engine = Engine::new(config)?;
759 
760     let module = Module::new(
761         &engine,
762         r#"
763             (module
764               (rec (type $a (struct))
765                    (type $b (struct)))
766               (rec (type $c (struct)))
767 
768               (func (export "fa") (result (ref null $a)) unreachable)
769               (func (export "fb") (result (ref null $b)) unreachable)
770               (func (export "fc") (result (ref null $c)) unreachable)
771             )
772         "#,
773     )?;
774 
775     let mut store = Store::new(&engine, ());
776 
777     for exp in module.exports() {
778         let res_ty = exp.ty().unwrap_func().result(0).unwrap();
779         let struct_ty = res_ty
780             .unwrap_ref()
781             .heap_type()
782             .unwrap_concrete_struct()
783             .clone();
784         let _ = StructRefPre::new(&mut store, struct_ty);
785     }
786 
787     Ok(())
788 }
789