Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/tests/all/linker.rs
1690 views
1
use std::cell::Cell;
2
use std::rc::Rc;
3
use std::sync::Arc;
4
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
5
use wasmtime::*;
6
7
#[test]
8
#[cfg_attr(miri, ignore)]
9
fn link_undefined() -> Result<()> {
10
let mut store = Store::<()>::default();
11
let linker = Linker::new(store.engine());
12
let module = Module::new(store.engine(), r#"(module (import "" "" (func)))"#)?;
13
assert!(linker.instantiate(&mut store, &module).is_err());
14
let module = Module::new(store.engine(), r#"(module (import "" "" (global i32)))"#)?;
15
assert!(linker.instantiate(&mut store, &module).is_err());
16
let module = Module::new(store.engine(), r#"(module (import "" "" (memory 1)))"#)?;
17
assert!(linker.instantiate(&mut store, &module).is_err());
18
let module = Module::new(
19
store.engine(),
20
r#"(module (import "" "" (table 1 funcref)))"#,
21
)?;
22
assert!(linker.instantiate(&mut store, &module).is_err());
23
Ok(())
24
}
25
26
#[test]
27
#[cfg_attr(miri, ignore)]
28
fn test_unknown_import_error() -> Result<()> {
29
let mut store = Store::<()>::default();
30
let linker = Linker::new(store.engine());
31
let module = Module::new(
32
store.engine(),
33
r#"(module (import "unknown-module" "unknown-name" (func)))"#,
34
)?;
35
let err = linker
36
.instantiate(&mut store, &module)
37
.expect_err("should fail");
38
let unknown_import: UnknownImportError = err.downcast()?;
39
assert_eq!(unknown_import.module(), "unknown-module");
40
assert_eq!(unknown_import.name(), "unknown-name");
41
unknown_import.ty().unwrap_func();
42
Ok(())
43
}
44
45
#[test]
46
fn link_twice_bad() -> Result<()> {
47
let mut store = Store::<()>::default();
48
let mut linker = Linker::<()>::new(store.engine());
49
50
// functions
51
linker.func_wrap("f", "", || {})?;
52
assert!(linker.func_wrap("f", "", || {}).is_err());
53
assert!(
54
linker
55
.func_wrap("f", "", || -> Result<()> { loop {} })
56
.is_err()
57
);
58
59
// globals
60
let ty = GlobalType::new(ValType::I32, Mutability::Const);
61
let global = Global::new(&mut store, ty, Val::I32(0))?;
62
linker.define(&mut store, "g", "1", global)?;
63
assert!(linker.define(&mut store, "g", "1", global).is_err());
64
65
let ty = GlobalType::new(ValType::I32, Mutability::Var);
66
let global = Global::new(&mut store, ty, Val::I32(0))?;
67
linker.define(&mut store, "g", "2", global)?;
68
assert!(linker.define(&mut store, "g", "2", global).is_err());
69
70
let ty = GlobalType::new(ValType::I64, Mutability::Const);
71
let global = Global::new(&mut store, ty, Val::I64(0))?;
72
linker.define(&mut store, "g", "3", global)?;
73
assert!(linker.define(&mut store, "g", "3", global).is_err());
74
75
// memories
76
let ty = MemoryType::new(1, None);
77
let memory = Memory::new(&mut store, ty)?;
78
linker.define(&mut store, "m", "", memory)?;
79
assert!(linker.define(&mut store, "m", "", memory).is_err());
80
let ty = MemoryType::new(2, None);
81
let memory = Memory::new(&mut store, ty)?;
82
assert!(linker.define(&mut store, "m", "", memory).is_err());
83
84
// tables
85
let ty = TableType::new(RefType::FUNCREF, 1, None);
86
let table = Table::new(&mut store, ty, Ref::Func(None))?;
87
linker.define(&mut store, "t", "", table)?;
88
assert!(linker.define(&mut store, "t", "", table).is_err());
89
let ty = TableType::new(RefType::FUNCREF, 2, None);
90
let table = Table::new(&mut store, ty, Ref::Func(None))?;
91
assert!(linker.define(&mut store, "t", "", table).is_err());
92
Ok(())
93
}
94
95
#[test]
96
#[cfg_attr(miri, ignore)]
97
fn function_interposition() -> Result<()> {
98
let mut store = Store::<()>::default();
99
let mut linker = Linker::new(store.engine());
100
linker.allow_shadowing(true);
101
let mut module = Module::new(
102
store.engine(),
103
r#"(module (func (export "green") (result i32) (i32.const 7)))"#,
104
)?;
105
for _ in 0..4 {
106
let instance = linker.instantiate(&mut store, &module)?;
107
let green = instance.get_export(&mut store, "green").unwrap().clone();
108
linker.define(&mut store, "red", "green", green)?;
109
module = Module::new(
110
store.engine(),
111
r#"(module
112
(import "red" "green" (func (result i32)))
113
(func (export "green") (result i32) (i32.mul (call 0) (i32.const 2)))
114
)"#,
115
)?;
116
}
117
let instance = linker.instantiate(&mut store, &module)?;
118
let func = instance
119
.get_export(&mut store, "green")
120
.unwrap()
121
.into_func()
122
.unwrap();
123
let func = func.typed::<(), i32>(&store)?;
124
assert_eq!(func.call(&mut store, ())?, 112);
125
Ok(())
126
}
127
128
// Same as `function_interposition`, but the linker's name for the function
129
// differs from the module's name.
130
#[test]
131
#[cfg_attr(miri, ignore)]
132
fn function_interposition_renamed() -> Result<()> {
133
let mut store = Store::<()>::default();
134
let mut linker = Linker::new(store.engine());
135
linker.allow_shadowing(true);
136
let mut module = Module::new(
137
store.engine(),
138
r#"(module (func (export "export") (result i32) (i32.const 7)))"#,
139
)?;
140
for _ in 0..4 {
141
let instance = linker.instantiate(&mut store, &module)?;
142
let export = instance.get_export(&mut store, "export").unwrap().clone();
143
linker.define(&mut store, "red", "green", export)?;
144
module = Module::new(
145
store.engine(),
146
r#"(module
147
(import "red" "green" (func (result i32)))
148
(func (export "export") (result i32) (i32.mul (call 0) (i32.const 2)))
149
)"#,
150
)?;
151
}
152
let instance = linker.instantiate(&mut store, &module)?;
153
let func = instance.get_func(&mut store, "export").unwrap();
154
let func = func.typed::<(), i32>(&store)?;
155
assert_eq!(func.call(&mut store, ())?, 112);
156
Ok(())
157
}
158
159
// Similar to `function_interposition`, but use `Linker::instance` instead of
160
// `Linker::define`.
161
#[test]
162
#[cfg_attr(miri, ignore)]
163
fn module_interposition() -> Result<()> {
164
let mut store = Store::<()>::default();
165
let mut linker = Linker::new(store.engine());
166
linker.allow_shadowing(true);
167
let mut module = Module::new(
168
store.engine(),
169
r#"(module (func (export "export") (result i32) (i32.const 7)))"#,
170
)?;
171
for _ in 0..4 {
172
let instance = linker.instantiate(&mut store, &module)?;
173
linker.instance(&mut store, "instance", instance)?;
174
module = Module::new(
175
store.engine(),
176
r#"(module
177
(import "instance" "export" (func (result i32)))
178
(func (export "export") (result i32) (i32.mul (call 0) (i32.const 2)))
179
)"#,
180
)?;
181
}
182
let instance = linker.instantiate(&mut store, &module)?;
183
let func = instance
184
.get_export(&mut store, "export")
185
.unwrap()
186
.into_func()
187
.unwrap();
188
let func = func.typed::<(), i32>(&store)?;
189
assert_eq!(func.call(&mut store, ())?, 112);
190
Ok(())
191
}
192
193
#[test]
194
#[cfg_attr(miri, ignore)]
195
fn allow_unknown_exports() -> Result<()> {
196
let mut store = Store::<()>::default();
197
let mut linker = Linker::new(store.engine());
198
let module = Module::new(
199
store.engine(),
200
r#"(module (func (export "_start")) (global (export "g") i32 (i32.const 0)))"#,
201
)?;
202
203
assert!(linker.module(&mut store, "module", &module).is_err());
204
205
let mut linker = Linker::new(store.engine());
206
linker.allow_unknown_exports(true);
207
linker.module(&mut store, "module", &module)?;
208
209
Ok(())
210
}
211
212
#[test]
213
#[cfg_attr(miri, ignore)]
214
fn no_leak() -> Result<()> {
215
struct DropMe(Rc<Cell<bool>>);
216
217
impl Drop for DropMe {
218
fn drop(&mut self) {
219
self.0.set(true);
220
}
221
}
222
223
let flag = Rc::new(Cell::new(false));
224
{
225
let mut store = Store::new(&Engine::default(), DropMe(flag.clone()));
226
let mut linker = Linker::new(store.engine());
227
let module = Module::new(
228
store.engine(),
229
r#"
230
(module
231
(func (export "_start"))
232
)
233
"#,
234
)?;
235
linker.module(&mut store, "a", &module)?;
236
}
237
assert!(flag.get(), "store was leaked");
238
Ok(())
239
}
240
241
#[test]
242
#[cfg_attr(miri, ignore)]
243
fn no_leak_with_imports() -> Result<()> {
244
struct DropMe(Arc<AtomicUsize>);
245
246
impl Drop for DropMe {
247
fn drop(&mut self) {
248
self.0.fetch_add(1, SeqCst);
249
}
250
}
251
252
let flag = Arc::new(AtomicUsize::new(0));
253
{
254
let mut store = Store::new(&Engine::default(), DropMe(flag.clone()));
255
let mut linker = Linker::new(store.engine());
256
let drop_me = DropMe(flag.clone());
257
linker.func_wrap("", "", move || {
258
let _ = &drop_me;
259
})?;
260
let module = Module::new(
261
store.engine(),
262
r#"
263
(module
264
(import "" "" (func))
265
(func (export "_start"))
266
)
267
"#,
268
)?;
269
linker.module(&mut store, "a", &module)?;
270
}
271
assert!(flag.load(SeqCst) == 2, "something was leaked");
272
Ok(())
273
}
274
275
#[test]
276
#[cfg_attr(miri, ignore)]
277
fn get_host_function() -> Result<()> {
278
let engine = Engine::default();
279
let module = Module::new(&engine, r#"(module (import "mod" "f1" (func)))"#)?;
280
281
let mut linker = Linker::new(&engine);
282
linker.func_wrap("mod", "f1", || {})?;
283
let mut store = Store::new(&engine, ());
284
assert!(
285
linker
286
.get_by_import(&mut store, &module.imports().nth(0).unwrap())
287
.is_some()
288
);
289
290
Ok(())
291
}
292
293
#[test]
294
fn funcs_live_on_to_fight_another_day() -> Result<()> {
295
struct DropMe(Arc<AtomicUsize>);
296
297
impl Drop for DropMe {
298
fn drop(&mut self) {
299
self.0.fetch_add(1, SeqCst);
300
}
301
}
302
303
let flag = Arc::new(AtomicUsize::new(0));
304
let engine = Engine::default();
305
let mut linker = Linker::new(&engine);
306
let drop_me = DropMe(flag.clone());
307
linker.func_wrap("", "", move || {
308
let _ = &drop_me;
309
})?;
310
assert_eq!(flag.load(SeqCst), 0);
311
312
let get_and_call = || -> Result<()> {
313
assert_eq!(flag.load(SeqCst), 0);
314
let mut store = Store::new(&engine, ());
315
let func = linker.get(&mut store, "", "").unwrap();
316
func.into_func().unwrap().call(&mut store, &[], &mut [])?;
317
assert_eq!(flag.load(SeqCst), 0);
318
Ok(())
319
};
320
321
get_and_call()?;
322
get_and_call()?;
323
drop(linker);
324
assert_eq!(flag.load(SeqCst), 1);
325
Ok(())
326
}
327
328
#[test]
329
fn alias_one() -> Result<()> {
330
let mut store = Store::<()>::default();
331
let mut linker = Linker::new(store.engine());
332
assert!(linker.alias("a", "b", "c", "d").is_err());
333
linker.func_wrap("a", "b", || {})?;
334
assert!(linker.alias("a", "b", "c", "d").is_ok());
335
assert!(linker.get(&mut store, "a", "b").is_some());
336
assert!(linker.get(&mut store, "c", "d").is_some());
337
Ok(())
338
}
339
340
#[test]
341
#[cfg_attr(miri, ignore)]
342
fn instance_pre() -> Result<()> {
343
let engine = Engine::default();
344
let mut linker = Linker::new(&engine);
345
linker.func_wrap("", "", || {})?;
346
347
let module = Module::new(&engine, r#"(module (import "" "" (func)))"#)?;
348
let instance_pre = linker.instantiate_pre(&module)?;
349
instance_pre.instantiate(&mut Store::new(&engine, ()))?;
350
instance_pre.instantiate(&mut Store::new(&engine, ()))?;
351
352
let mut store = Store::new(&engine, ());
353
let global = Global::new(
354
&mut store,
355
GlobalType::new(ValType::I32, Mutability::Const),
356
1.into(),
357
)?;
358
linker.define(&mut store, "", "g", global)?;
359
360
let module = Module::new(
361
&engine,
362
r#"(module
363
(import "" "" (func))
364
(import "" "g" (global i32))
365
)"#,
366
)?;
367
let instance_pre = linker.instantiate_pre(&module)?;
368
instance_pre.instantiate(&mut store)?;
369
instance_pre.instantiate(&mut store)?;
370
Ok(())
371
}
372
373
#[test]
374
#[cfg_attr(miri, ignore)]
375
fn test_trapping_unknown_import() -> Result<()> {
376
const WAT: &str = r#"
377
(module
378
(type $t0 (func))
379
(import "" "imp" (func $.imp (type $t0)))
380
(func $run call $.imp)
381
(func $other)
382
(export "run" (func $run))
383
(export "other" (func $other))
384
)
385
"#;
386
387
let mut store = Store::<()>::default();
388
let module = Module::new(store.engine(), WAT).expect("failed to create module");
389
let mut linker = Linker::new(store.engine());
390
391
linker.define_unknown_imports_as_traps(&module)?;
392
let instance = linker.instantiate(&mut store, &module)?;
393
394
// "run" calls an import function which will not be defined, so it should trap
395
let run_func = instance
396
.get_func(&mut store, "run")
397
.expect("expected a run func in the module");
398
399
let err = run_func.call(&mut store, &[], &mut []).unwrap_err();
400
assert!(err.is::<UnknownImportError>());
401
402
// "other" does not call the import function, so it should not trap
403
let other_func = instance
404
.get_func(&mut store, "other")
405
.expect("expected an other func in the module");
406
407
other_func.call(&mut store, &[], &mut [])?;
408
409
Ok(())
410
}
411
412
#[test]
413
#[cfg_attr(miri, ignore)]
414
fn test_default_value_unknown_import() -> Result<()> {
415
const WAT: &str = r#"
416
(module
417
(import "unknown" "func" (func $unknown_func (result i64 f32 externref)))
418
(func (export "run") (result i64 f32 externref)
419
call $unknown_func
420
)
421
)
422
"#;
423
424
let mut store = Store::<()>::default();
425
let module = Module::new(store.engine(), WAT).expect("failed to create module");
426
let mut linker = Linker::new(store.engine());
427
428
linker.define_unknown_imports_as_default_values(&mut store, &module)?;
429
let instance = linker.instantiate(&mut store, &module)?;
430
431
// "run" calls an import function which will not be defined, so it should
432
// return default values.
433
let run_func = instance
434
.get_func(&mut store, "run")
435
.expect("expected a run func in the module");
436
437
let mut results = vec![Val::I32(1), Val::I32(2), Val::I32(3)];
438
run_func.call(&mut store, &[], &mut results)?;
439
440
assert_eq!(results[0].i64(), Some(0));
441
assert_eq!(results[1].f32(), Some(0.0));
442
assert!(results[2].externref().unwrap().is_none());
443
444
Ok(())
445
}
446
447
#[test]
448
#[cfg_attr(miri, ignore)]
449
fn linker_instantiate_with_concrete_func_refs() -> Result<()> {
450
let mut config = Config::new();
451
config.wasm_function_references(true);
452
let engine = Engine::new(&config)?;
453
454
let module = Module::new(
455
&engine,
456
r#"
457
(module
458
(type $a (func (result i32)))
459
(type $b (func (result (ref null $a))))
460
(type $c (func (result (ref null $b))))
461
462
(import "env" "f" (func $f (result (ref null $c))))
463
464
(func (export "g") (result funcref)
465
call $f
466
)
467
)
468
"#,
469
)?;
470
471
let a = FuncType::new(&engine, None, Some(ValType::I32));
472
let ref_null_a = ValType::from(RefType::new(true, HeapType::ConcreteFunc(a.clone())));
473
474
let b = FuncType::new(&engine, None, Some(ref_null_a));
475
let ref_null_b = ValType::from(RefType::new(true, HeapType::ConcreteFunc(b.clone())));
476
477
let c = FuncType::new(&engine, None, Some(ref_null_b));
478
let ref_null_c = ValType::from(RefType::new(true, HeapType::ConcreteFunc(c.clone())));
479
480
let mut store = Store::new(&engine, ());
481
let a_func = Func::new(&mut store, a, |_caller, _args, results| {
482
results[0] = Val::I32(0x1234_5678);
483
Ok(())
484
});
485
486
let b_func = Func::new(&mut store, b, move |_caller, _args, results| {
487
results[0] = Val::FuncRef(Some(a_func));
488
Ok(())
489
});
490
491
let c_func = Func::new(&mut store, c, move |_caller, _args, results| {
492
results[0] = Val::FuncRef(Some(b_func));
493
Ok(())
494
});
495
496
let mut linker = Linker::new(&engine);
497
linker.func_new(
498
"env",
499
"f",
500
FuncType::new(&engine, None, Some(ref_null_c)),
501
move |_caller, _args, results| {
502
results[0] = Val::FuncRef(Some(c_func));
503
Ok(())
504
},
505
)?;
506
507
let instance = linker.instantiate(&mut store, &module)?;
508
509
let g = instance.get_typed_func::<(), Option<Func>>(&mut store, "g")?;
510
511
let c = g.call(&mut store, ())?;
512
let c = c.expect("func ref c is non null");
513
let c = c.typed::<(), Option<Func>>(&mut store)?;
514
515
let b = c.call(&mut store, ())?;
516
let b = b.expect("func ref b is non null");
517
let b = b.typed::<(), Option<Func>>(&mut store)?;
518
519
let a = b.call(&mut store, ())?;
520
let a = a.expect("func ref a is non null");
521
let a = a.typed::<(), u32>(&mut store)?;
522
523
let x = a.call(&mut store, ())?;
524
assert_eq!(x, 0x1234_5678);
525
526
Ok(())
527
}
528
529
#[test]
530
#[cfg_attr(miri, ignore)]
531
fn linker_defines_func_subtype() -> Result<()> {
532
let _ = env_logger::try_init();
533
534
let mut config = Config::new();
535
config.wasm_function_references(true);
536
config.wasm_gc(true);
537
let engine = Engine::new(&config)?;
538
539
let ft0 = FuncType::with_finality_and_supertype(
540
&engine,
541
Finality::NonFinal,
542
None,
543
[ValType::NULLFUNCREF],
544
[],
545
)?;
546
let ft1 = FuncType::with_finality_and_supertype(
547
&engine,
548
Finality::NonFinal,
549
Some(&ft0),
550
[ValType::FUNCREF],
551
[],
552
)?;
553
554
let ft2 = FuncType::with_finality_and_supertype(
555
&engine,
556
Finality::NonFinal,
557
None,
558
[],
559
[ValType::FUNCREF],
560
)?;
561
let ft3 = FuncType::with_finality_and_supertype(
562
&engine,
563
Finality::NonFinal,
564
Some(&ft2),
565
[],
566
[ValType::NULLFUNCREF],
567
)?;
568
569
let nop = FuncType::new(&engine, [], []);
570
let ft4 = FuncType::with_finality_and_supertype(
571
&engine,
572
Finality::NonFinal,
573
None,
574
[ValType::NULLFUNCREF],
575
[ValType::FUNCREF],
576
)?;
577
let ft5 = FuncType::with_finality_and_supertype(
578
&engine,
579
Finality::NonFinal,
580
Some(&ft4),
581
[ValType::Ref(RefType::new(
582
true,
583
HeapType::ConcreteFunc(nop.clone()),
584
))],
585
[ValType::Ref(RefType::new(
586
true,
587
HeapType::ConcreteFunc(nop.clone()),
588
))],
589
)?;
590
591
let mut linker = Linker::new(&engine);
592
linker.func_new("env", "f", ft1, |_caller, _args, _results| Ok(()))?;
593
linker.func_new("env", "g", ft3, |_caller, _args, _results| Ok(()))?;
594
linker.func_new("env", "h", ft5, |_caller, _args, _results| Ok(()))?;
595
596
let module = Module::new(
597
&engine,
598
r#"
599
(module
600
(type $ft0 (sub (func (param nullfuncref))))
601
(type $ft2 (sub (func (result funcref))))
602
(type $ft4 (sub (func (param nullfuncref) (result funcref))))
603
604
(import "env" "f" (func (type $ft0)))
605
(import "env" "g" (func (type $ft2)))
606
(import "env" "h" (func (type $ft4)))
607
)
608
"#,
609
)?;
610
611
let mut store = Store::new(&engine, ());
612
let _ = linker.instantiate(&mut store, &module)?;
613
614
Ok(())
615
}
616
617
#[test]
618
#[cfg_attr(miri, ignore)]
619
fn linker_defines_global_subtype_const_ok() -> Result<()> {
620
let mut config = Config::new();
621
config.wasm_function_references(true);
622
let engine = Engine::new(&config)?;
623
let mut store = Store::new(&engine, ());
624
let mut linker = Linker::new(&engine);
625
626
let module = Module::new(
627
&engine,
628
r#"
629
(module
630
(import "env" "g" (global funcref))
631
)
632
"#,
633
)?;
634
635
let g = Global::new(
636
&mut store,
637
GlobalType::new(ValType::NULLFUNCREF, Mutability::Const),
638
Val::FuncRef(None),
639
)?;
640
linker.define(&store, "env", "g", g)?;
641
642
let _ = linker.instantiate(&mut store, &module)?;
643
Ok(())
644
}
645
646
#[test]
647
#[cfg_attr(miri, ignore)]
648
fn linker_defines_global_subtype_const_err() -> Result<()> {
649
let mut config = Config::new();
650
config.wasm_function_references(true);
651
config.wasm_gc(true);
652
let engine = Engine::new(&config)?;
653
let mut store = Store::new(&engine, ());
654
let mut linker = Linker::new(&engine);
655
656
let module = Module::new(
657
&engine,
658
r#"
659
(module
660
(import "env" "g" (global nullfuncref))
661
)
662
"#,
663
)?;
664
665
// funcref </: nullfuncref
666
let g = Global::new(
667
&mut store,
668
GlobalType::new(ValType::FUNCREF, Mutability::Const),
669
Val::FuncRef(None),
670
)?;
671
linker.define(&store, "env", "g", g)?;
672
673
let e = linker.instantiate(&mut store, &module).unwrap_err();
674
assert_eq!(e.to_string(), "incompatible import type for `env::g`");
675
676
Ok(())
677
}
678
679
#[test]
680
#[cfg_attr(miri, ignore)]
681
fn linker_defines_global_subtype_mut_err() -> Result<()> {
682
let mut config = Config::new();
683
config.wasm_function_references(true);
684
let engine = Engine::new(&config)?;
685
let mut store = Store::new(&engine, ());
686
687
let module = Module::new(
688
&engine,
689
r#"
690
(module
691
(type $nop (func))
692
(import "env" "g" (global (mut (ref null $nop))))
693
)
694
"#,
695
)?;
696
697
// Supertype, not precise type.
698
let mut linker = Linker::new(&engine);
699
let g = Global::new(
700
&mut store,
701
GlobalType::new(ValType::FUNCREF, Mutability::Var),
702
Val::FuncRef(None),
703
)?;
704
linker.define(&store, "env", "g", g)?;
705
let e = linker.instantiate(&mut store, &module).unwrap_err();
706
assert_eq!(e.to_string(), "incompatible import type for `env::g`");
707
708
// Subtype, not precise type.
709
let mut linker = Linker::new(&engine);
710
let g = Global::new(
711
&mut store,
712
GlobalType::new(ValType::NULLFUNCREF, Mutability::Var),
713
Val::FuncRef(None),
714
)?;
715
linker.define(&store, "env", "g", g)?;
716
let e = linker.instantiate(&mut store, &module).unwrap_err();
717
assert_eq!(e.to_string(), "incompatible import type for `env::g`");
718
719
// Not mutable.
720
let mut linker = Linker::new(&engine);
721
let nop = FuncType::new(&engine, None, None);
722
let ref_null_nop = ValType::from(RefType::new(true, HeapType::ConcreteFunc(nop)));
723
let g = Global::new(
724
&mut store,
725
GlobalType::new(ref_null_nop, Mutability::Const),
726
Val::FuncRef(None),
727
)?;
728
linker.define(&store, "env", "g", g)?;
729
let e = linker.instantiate(&mut store, &module).unwrap_err();
730
assert_eq!(e.to_string(), "incompatible import type for `env::g`");
731
732
Ok(())
733
}
734
735
#[test]
736
#[cfg_attr(miri, ignore)]
737
fn linker_defines_table_subtype_err() -> Result<()> {
738
let mut config = Config::new();
739
config.wasm_function_references(true);
740
let engine = Engine::new(&config)?;
741
let mut store = Store::new(&engine, ());
742
743
let module = Module::new(
744
&engine,
745
r#"
746
(module
747
(type $nop (func))
748
(import "env" "t" (table 0 (ref null $nop)))
749
)
750
"#,
751
)?;
752
753
// Supertype, not precise type.
754
let mut linker = Linker::new(&engine);
755
let t = Table::new(
756
&mut store,
757
TableType::new(RefType::FUNCREF, 0, None),
758
Ref::Func(None),
759
)?;
760
linker.define(&store, "env", "t", t)?;
761
let e = linker.instantiate(&mut store, &module).unwrap_err();
762
assert_eq!(e.to_string(), "incompatible import type for `env::t`");
763
764
// Subtype, not precise type.
765
let mut linker = Linker::new(&engine);
766
let t = Table::new(
767
&mut store,
768
TableType::new(RefType::NULLFUNCREF, 0, None),
769
Ref::Func(None),
770
)?;
771
linker.define(&store, "env", "t", t)?;
772
let e = linker.instantiate(&mut store, &module).unwrap_err();
773
assert_eq!(e.to_string(), "incompatible import type for `env::t`");
774
775
Ok(())
776
}
777
778