Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/tests/all/structs.rs
1691 views
1
use super::gc_store;
2
use wasmtime::*;
3
use wasmtime_test_macros::wasmtime_test;
4
5
#[test]
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]
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]
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"]
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"]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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)]
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)]
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)]
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)]
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)]
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)]
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]
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]
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)]
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)]
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
790