1 #![cfg(not(miri))]
2 
3 use wasmtime::Result;
4 use wasmtime::component::*;
5 use wasmtime::{Config, Engine, Store, Trap};
6 
7 #[test]
8 fn host_resource_types() -> Result<()> {
9     let engine = super::engine();
10     let c = Component::new(
11         &engine,
12         r#"
13             (component
14                 (import "t" (type $t (sub resource)))
15                 (import "u" (type $u (sub resource)))
16 
17                 (export "t1" (type $t))
18                 (export "t2" (type $t))
19                 (export "u1" (type $u))
20                 (export "u2" (type $u))
21 
22                 (component $c
23                     (import "r" (type $r (sub resource)))
24                     (export "r1" (type $r))
25                 )
26                 (instance $i1 (instantiate $c (with "r" (type $t))))
27                 (instance $i2 (instantiate $c (with "r" (type $t))))
28                 (export "t3" (type $i1 "r1"))
29                 (export "t4" (type $i2 "r1"))
30             )
31         "#,
32     )?;
33 
34     struct T;
35     struct U;
36     assert!(ResourceType::host::<T>() != ResourceType::host::<U>());
37 
38     let mut store = Store::new(&engine, ());
39     let mut linker = Linker::new(&engine);
40     linker
41         .root()
42         .resource("t", ResourceType::host::<T>(), |_, _| Ok(()))?;
43     linker
44         .root()
45         .resource("u", ResourceType::host::<U>(), |_, _| Ok(()))?;
46     let i = linker.instantiate(&mut store, &c)?;
47     let t1 = i.get_resource(&mut store, "t1").unwrap();
48     let t2 = i.get_resource(&mut store, "t2").unwrap();
49     let t3 = i.get_resource(&mut store, "t3").unwrap();
50     let t4 = i.get_resource(&mut store, "t4").unwrap();
51     let u1 = i.get_resource(&mut store, "u1").unwrap();
52     let u2 = i.get_resource(&mut store, "u2").unwrap();
53 
54     assert_eq!(t1, ResourceType::host::<T>());
55     assert_eq!(t2, ResourceType::host::<T>());
56     assert_eq!(t3, ResourceType::host::<T>());
57     assert_eq!(t4, ResourceType::host::<T>());
58     assert_eq!(u1, ResourceType::host::<U>());
59     assert_eq!(u2, ResourceType::host::<U>());
60     Ok(())
61 }
62 
63 #[test]
64 fn guest_resource_types() -> Result<()> {
65     let engine = super::engine();
66     let c = Component::new(
67         &engine,
68         r#"
69             (component
70                 (type $t (resource (rep i32)))
71                 (type $u (resource (rep i32)))
72 
73                 (export "t1" (type $t))
74                 (export "t2" (type $t))
75                 (export "u1" (type $u))
76                 (export "u2" (type $u))
77 
78                 (component $c
79                     (import "r" (type $r (sub resource)))
80                     (export "r1" (type $r))
81                 )
82                 (instance $i1 (instantiate $c (with "r" (type $t))))
83                 (instance $i2 (instantiate $c (with "r" (type $t))))
84                 (export "t3" (type $i1 "r1"))
85                 (export "t4" (type $i2 "r1"))
86             )
87         "#,
88     )?;
89 
90     let mut store = Store::new(&engine, ());
91     let linker = Linker::new(&engine);
92     let i = linker.instantiate(&mut store, &c)?;
93     let t1 = i.get_resource(&mut store, "t1").unwrap();
94     let t2 = i.get_resource(&mut store, "t2").unwrap();
95     let t3 = i.get_resource(&mut store, "t3").unwrap();
96     let t4 = i.get_resource(&mut store, "t4").unwrap();
97     let u1 = i.get_resource(&mut store, "u1").unwrap();
98     let u2 = i.get_resource(&mut store, "u2").unwrap();
99 
100     assert_ne!(t1, u1);
101     assert_eq!(t1, t2);
102     assert_eq!(t1, t3);
103     assert_eq!(t1, t4);
104     assert_eq!(u1, u2);
105     Ok(())
106 }
107 
108 #[test]
109 fn resource_any() -> Result<()> {
110     let engine = super::engine();
111     let c = Component::new(
112         &engine,
113         r#"
114             (component
115                 (type $t' (resource (rep i32)))
116                 (type $u' (resource (rep i32)))
117 
118                 (export $t "t" (type $t'))
119                 (export $u "u" (type $u'))
120 
121                 (core func $t_ctor (canon resource.new $t))
122                 (core func $u_ctor (canon resource.new $u))
123 
124                 (func (export "[constructor]t") (param "x" u32) (result (own $t))
125                     (canon lift (core func $t_ctor)))
126                 (func (export "[constructor]u") (param "x" u32) (result (own $u))
127                     (canon lift (core func $u_ctor)))
128 
129                 (core func $t_drop (canon resource.drop $t))
130                 (core func $u_drop (canon resource.drop $u))
131 
132                 (func (export "drop-t") (param "x" (own $t))
133                     (canon lift (core func $t_drop)))
134                 (func (export "drop-u") (param "x" (own $u))
135                     (canon lift (core func $u_drop)))
136             )
137         "#,
138     )?;
139 
140     let linker = Linker::new(&engine);
141     {
142         let mut store = Store::new(&engine, ());
143         let i = linker.instantiate(&mut store, &c)?;
144         let t = i.get_resource(&mut store, "t").unwrap();
145         let u = i.get_resource(&mut store, "u").unwrap();
146 
147         assert_ne!(t, u);
148 
149         let t_ctor = i.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "[constructor]t")?;
150         let u_ctor = i.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "[constructor]u")?;
151         let t_dtor = i.get_typed_func::<(ResourceAny,), ()>(&mut store, "drop-t")?;
152         let u_dtor = i.get_typed_func::<(ResourceAny,), ()>(&mut store, "drop-u")?;
153 
154         let (t1,) = t_ctor.call(&mut store, (100,))?;
155         let (t2,) = t_ctor.call(&mut store, (200,))?;
156         let (u1,) = u_ctor.call(&mut store, (300,))?;
157         let (u2,) = u_ctor.call(&mut store, (400,))?;
158 
159         assert_eq!(t1.ty(), t);
160         assert_eq!(t2.ty(), t);
161         assert_eq!(u1.ty(), u);
162         assert_eq!(u2.ty(), u);
163 
164         u_dtor.call(&mut store, (u2,))?;
165 
166         u_dtor.call(&mut store, (u1,))?;
167 
168         t_dtor.call(&mut store, (t1,))?;
169 
170         t_dtor.call(&mut store, (t2,))?;
171     }
172 
173     {
174         let mut store = Store::new(&engine, ());
175         let i = linker.instantiate(&mut store, &c)?;
176         let t_ctor = i.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "[constructor]t")?;
177         let u_ctor = i.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "[constructor]u")?;
178         let t_dtor = i.get_typed_func::<(ResourceAny,), ()>(&mut store, "drop-t")?;
179 
180         // `t` is placed at host index 0
181         let (t,) = t_ctor.call(&mut store, (100,))?;
182         t_dtor.call(&mut store, (t,))?;
183 
184         // `u` is also placed at host index 0 since `t` was deallocated
185         let (_u,) = u_ctor.call(&mut store, (100,))?;
186 
187         // reuse of `t` should fail, despite it pointing to a valid resource
188         assert_eq!(
189             t_dtor.call(&mut store, (t,)).unwrap_err().to_string(),
190             "host-owned resource is being used with the wrong type"
191         );
192     }
193 
194     Ok(())
195 }
196 
197 #[test]
198 fn mismatch_intrinsics() -> Result<()> {
199     let engine = super::engine();
200     let c = Component::new(
201         &engine,
202         r#"
203             (component
204                 (type $t' (resource (rep i32)))
205                 (type $u' (resource (rep i32)))
206 
207                 (export $t "t" (type $t'))
208                 (export $u "u" (type $u'))
209 
210                 ;; note the mismatch where this is an intrinsic for `u` but
211                 ;; we're typing it as `t`
212                 (core func $t_ctor (canon resource.new $u))
213 
214                 (func (export "ctor") (param "x" u32) (result (own $t))
215                     (canon lift (core func $t_ctor)))
216             )
217         "#,
218     )?;
219 
220     let mut store = Store::new(&engine, ());
221     let i = Linker::new(&engine).instantiate(&mut store, &c)?;
222     let ctor = i.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "ctor")?;
223     assert_eq!(
224         ctor.call(&mut store, (100,)).unwrap_err().to_string(),
225         "handle index 1 used with the wrong type, expected guest-defined \
226          resource but found a different guest-defined resource",
227     );
228 
229     Ok(())
230 }
231 
232 #[test]
233 fn mismatch_resource_types() -> Result<()> {
234     let engine = super::engine();
235     let c = Component::new(
236         &engine,
237         r#"
238             (component
239                 (type $t' (resource (rep i32)))
240                 (type $u' (resource (rep i32)))
241 
242                 (export $t "t" (type $t'))
243                 (export $u "u" (type $u'))
244 
245                 (core func $t_ctor (canon resource.new $t))
246                 (func (export "ctor") (param "x" u32) (result (own $t))
247                     (canon lift (core func $t_ctor)))
248 
249                 (core func $u_dtor (canon resource.drop $u))
250                 (func (export "dtor") (param "x" (own $u))
251                     (canon lift (core func $u_dtor)))
252             )
253         "#,
254     )?;
255 
256     let mut store = Store::new(&engine, ());
257     let i = Linker::new(&engine).instantiate(&mut store, &c)?;
258     let ctor = i.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "ctor")?;
259     let dtor = i.get_typed_func::<(ResourceAny,), ()>(&mut store, "dtor")?;
260 
261     let (t,) = ctor.call(&mut store, (100,))?;
262     assert_eq!(
263         dtor.call(&mut store, (t,)).unwrap_err().to_string(),
264         "mismatched resource types"
265     );
266 
267     Ok(())
268 }
269 
270 #[test]
271 fn drop_in_different_places() -> Result<()> {
272     let engine = super::engine();
273     let c = Component::new(
274         &engine,
275         r#"
276             (component
277                 (type $t' (resource (rep i32)))
278 
279                 (export $t "t" (type $t'))
280 
281                 (core func $ctor (canon resource.new $t))
282                 (func (export "ctor") (param "x" u32) (result (own $t))
283                     (canon lift (core func $ctor)))
284 
285                 (core func $dtor (canon resource.drop $t))
286                 (func (export "dtor1") (param "x" (own $t))
287                     (canon lift (core func $dtor)))
288 
289                 (component $c
290                     (import "t" (type $t (sub resource)))
291                     (core func $dtor (canon resource.drop $t))
292                     (func (export "dtor") (param "x" (own $t))
293                         (canon lift (core func $dtor)))
294                 )
295                 (instance $i1 (instantiate $c (with "t" (type $t))))
296                 (instance $i2 (instantiate $c (with "t" (type $t))))
297 
298                 (export "dtor2" (func $i1 "dtor"))
299                 (export "dtor3" (func $i2 "dtor"))
300             )
301         "#,
302     )?;
303 
304     let mut store = Store::new(&engine, ());
305     let i = Linker::new(&engine).instantiate(&mut store, &c)?;
306     let ctor = i.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "ctor")?;
307     let dtor1 = i.get_typed_func::<(ResourceAny,), ()>(&mut store, "dtor1")?;
308     let dtor2 = i.get_typed_func::<(ResourceAny,), ()>(&mut store, "dtor2")?;
309     let dtor3 = i.get_typed_func::<(ResourceAny,), ()>(&mut store, "dtor3")?;
310 
311     let (t,) = ctor.call(&mut store, (100,))?;
312     dtor1.call(&mut store, (t,))?;
313 
314     let (t,) = ctor.call(&mut store, (200,))?;
315     dtor2.call(&mut store, (t,))?;
316 
317     let (t,) = ctor.call(&mut store, (300,))?;
318     dtor3.call(&mut store, (t,))?;
319 
320     Ok(())
321 }
322 
323 #[test]
324 fn drop_guest_twice() -> Result<()> {
325     let engine = super::engine();
326     let c = Component::new(
327         &engine,
328         r#"
329             (component
330                 (type $t' (resource (rep i32)))
331 
332                 (export $t "t" (type $t'))
333 
334                 (core func $ctor (canon resource.new $t))
335                 (func (export "ctor") (param "x" u32) (result (own $t))
336                     (canon lift (core func $ctor)))
337 
338                 (core func $dtor (canon resource.drop $t))
339                 (func (export "dtor") (param "x" (own $t))
340                     (canon lift (core func $dtor)))
341             )
342         "#,
343     )?;
344 
345     let mut store = Store::new(&engine, ());
346     let i = Linker::new(&engine).instantiate(&mut store, &c)?;
347     let ctor = i.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "ctor")?;
348     let dtor = i.get_typed_func::<(&ResourceAny,), ()>(&mut store, "dtor")?;
349 
350     let (t,) = ctor.call(&mut store, (100,))?;
351     dtor.call(&mut store, (&t,))?;
352 
353     assert_eq!(
354         dtor.call(&mut store, (&t,)).unwrap_err().to_string(),
355         "unknown handle index 1"
356     );
357 
358     Ok(())
359 }
360 
361 #[test]
362 fn drop_host_twice() -> Result<()> {
363     let engine = super::engine();
364     let c = Component::new(
365         &engine,
366         r#"
367             (component
368                 (import "t" (type $t (sub resource)))
369 
370                 (core func $dtor (canon resource.drop $t))
371                 (func (export "dtor") (param "x" (own $t))
372                     (canon lift (core func $dtor)))
373             )
374         "#,
375     )?;
376 
377     struct MyType;
378 
379     let mut store = Store::new(&engine, ());
380     let mut linker = Linker::new(&engine);
381     linker
382         .root()
383         .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
384     let i = linker.instantiate(&mut store, &c)?;
385     let dtor = i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "dtor")?;
386 
387     let t = Resource::new_own(100);
388     dtor.call(&mut store, (&t,))?;
389 
390     assert_eq!(
391         dtor.call(&mut store, (&t,)).unwrap_err().to_string(),
392         "host resource already consumed"
393     );
394 
395     Ok(())
396 }
397 
398 #[test]
399 fn manually_destroy() -> Result<()> {
400     let engine = super::engine();
401     let c = Component::new(
402         &engine,
403         r#"
404             (component
405                 (import "t1" (type $t1 (sub resource)))
406 
407                 (core module $m
408                   (global $drops (mut i32) i32.const 0)
409                   (global $last-drop (mut i32) i32.const 0)
410 
411                   (func (export "dtor") (param i32)
412                     (global.set $drops (i32.add (global.get $drops) (i32.const 1)))
413                     (global.set $last-drop (local.get 0))
414                   )
415                   (func (export "drops") (result i32) global.get $drops)
416                   (func (export "last-drop") (result i32) global.get $last-drop)
417                   (func (export "pass") (param i32) (result i32) local.get 0)
418                 )
419                 (core instance $i (instantiate $m))
420                 (type $t2' (resource (rep i32) (dtor (func $i "dtor"))))
421                 (export $t2 "t2" (type $t2'))
422                 (core func $ctor (canon resource.new $t2))
423                 (func (export "[constructor]t2") (param "rep" u32) (result (own $t2))
424                   (canon lift (core func $ctor)))
425                 (func (export "[static]t2.drops") (result u32)
426                   (canon lift (core func $i "drops")))
427                 (func (export "[static]t2.last-drop") (result u32)
428                   (canon lift (core func $i "last-drop")))
429 
430                 (func (export "t1-pass") (param "t" (own $t1)) (result (own $t1))
431                   (canon lift (core func $i "pass")))
432             )
433         "#,
434     )?;
435 
436     struct MyType;
437 
438     #[derive(Default)]
439     struct Data {
440         drops: u32,
441         last_drop: Option<u32>,
442     }
443 
444     let mut store = Store::new(&engine, Data::default());
445     let mut linker = Linker::new(&engine);
446     linker
447         .root()
448         .resource("t1", ResourceType::host::<MyType>(), |mut cx, rep| {
449             let data: &mut Data = cx.data_mut();
450             data.drops += 1;
451             data.last_drop = Some(rep);
452             Ok(())
453         })?;
454     let i = linker.instantiate(&mut store, &c)?;
455     let t2_ctor = i.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "[constructor]t2")?;
456     let t2_drops = i.get_typed_func::<(), (u32,)>(&mut store, "[static]t2.drops")?;
457     let t2_last_drop = i.get_typed_func::<(), (u32,)>(&mut store, "[static]t2.last-drop")?;
458     let t1_pass = i.get_typed_func::<(Resource<MyType>,), (ResourceAny,)>(&mut store, "t1-pass")?;
459 
460     // Host resources can be destroyed through `resource_drop`
461     let t1 = Resource::new_own(100);
462     let (t1,) = t1_pass.call(&mut store, (t1,))?;
463     assert_eq!(store.data().drops, 0);
464     assert_eq!(store.data().last_drop, None);
465     t1.resource_drop(&mut store)?;
466     assert_eq!(store.data().drops, 1);
467     assert_eq!(store.data().last_drop, Some(100));
468 
469     // Guest resources can be destroyed through `resource_drop`
470     let (t2,) = t2_ctor.call(&mut store, (200,))?;
471     assert_eq!(t2_drops.call(&mut store, ())?, (0,));
472     assert_eq!(t2_last_drop.call(&mut store, ())?, (0,));
473     t2.resource_drop(&mut store)?;
474     assert_eq!(t2_drops.call(&mut store, ())?, (1,));
475     assert_eq!(t2_last_drop.call(&mut store, ())?, (200,));
476 
477     // Wires weren't crossed to drop more resources
478     assert_eq!(store.data().drops, 1);
479     assert_eq!(store.data().last_drop, Some(100));
480 
481     Ok(())
482 }
483 
484 #[test]
485 fn dynamic_type() -> Result<()> {
486     let engine = super::engine();
487     let c = Component::new(
488         &engine,
489         r#"
490             (component
491                 (import "t1" (type $t1 (sub resource)))
492                 (type $t2' (resource (rep i32)))
493                 (export $t2 "t2" (type $t2'))
494                 (core func $f (canon resource.drop $t2))
495 
496                 (func (export "a") (param "x" (own $t1))
497                     (canon lift (core func $f)))
498                 (func (export "b") (param "x" (tuple (own $t2)))
499                     (canon lift (core func $f)))
500             )
501         "#,
502     )?;
503 
504     struct MyType;
505 
506     let mut store = Store::new(&engine, ());
507     let mut linker = Linker::new(&engine);
508     linker
509         .root()
510         .resource("t1", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
511     let i = linker.instantiate(&mut store, &c)?;
512 
513     let a = i.get_func(&mut store, "a").unwrap();
514     let b = i.get_func(&mut store, "b").unwrap();
515     let t2 = i.get_resource(&mut store, "t2").unwrap();
516 
517     let aty = a.ty(&store);
518     assert_eq!(
519         aty.params().next().unwrap(),
520         ("x", Type::Own(ResourceType::host::<MyType>()))
521     );
522     let bty = b.ty(&store);
523     match bty.params().next().unwrap() {
524         (name, Type::Tuple(t)) => {
525             assert_eq!(name, "x");
526             assert_eq!(t.types().len(), 1);
527             let t0 = t.types().next().unwrap();
528             assert_eq!(t0, Type::Own(t2));
529         }
530         _ => unreachable!(),
531     }
532 
533     Ok(())
534 }
535 
536 #[test]
537 fn dynamic_val() -> Result<()> {
538     let engine = super::engine();
539     let c = Component::new(
540         &engine,
541         r#"
542             (component
543                 (import "t1" (type $t1 (sub resource)))
544                 (type $t2' (resource (rep i32)))
545                 (export $t2 "t2" (type $t2'))
546                 (core func $f (canon resource.new $t2))
547 
548                 (core module $m
549                     (func (export "pass") (param i32) (result i32)
550                         (local.get 0)))
551                 (core instance $i (instantiate $m))
552 
553                 (func (export "a") (param "x" (own $t1)) (result (own $t1))
554                     (canon lift (core func $i "pass")))
555                 (func (export "b") (param "x" u32) (result (own $t2))
556                     (canon lift (core func $f)))
557             )
558         "#,
559     )?;
560 
561     struct MyType;
562 
563     let mut store = Store::new(&engine, ());
564     let mut linker = Linker::new(&engine);
565     linker
566         .root()
567         .resource("t1", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
568     let i_pre = linker.instantiate_pre(&c)?;
569     let i = i_pre.instantiate(&mut store)?;
570 
571     let a = i.get_func(&mut store, "a").unwrap();
572     let a_typed = i.get_typed_func::<(Resource<MyType>,), (ResourceAny,)>(&mut store, "a")?;
573     let a_typed_result =
574         i.get_typed_func::<(Resource<MyType>,), (Resource<MyType>,)>(&mut store, "a")?;
575     let b = i.get_func(&mut store, "b").unwrap();
576     let t2 = i.get_resource(&mut store, "t2").unwrap();
577 
578     let t1 = Resource::new_own(100);
579     let (t1,) = a_typed.call(&mut store, (t1,))?;
580     assert_eq!(t1.ty(), ResourceType::host::<MyType>());
581 
582     let mut results = [Val::Bool(false)];
583     a.call(&mut store, &[Val::Resource(t1)], &mut results)?;
584     match &results[0] {
585         Val::Resource(resource) => {
586             assert_eq!(resource.ty(), ResourceType::host::<MyType>());
587             assert!(resource.owned());
588 
589             let resource = resource.try_into_resource::<MyType>(&mut store)?;
590             assert_eq!(resource.rep(), 100);
591             assert!(resource.owned());
592 
593             let resource = resource.try_into_resource_any(&mut store)?;
594             assert_eq!(resource.ty(), ResourceType::host::<MyType>());
595             assert!(resource.owned());
596         }
597         _ => unreachable!(),
598     }
599 
600     let t1_any = Resource::<MyType>::new_own(100).try_into_resource_any(&mut store)?;
601     let mut results = [Val::Bool(false)];
602     a.call(&mut store, &[Val::Resource(t1_any)], &mut results)?;
603     match &results[0] {
604         Val::Resource(resource) => {
605             assert_eq!(resource.ty(), ResourceType::host::<MyType>());
606             assert!(resource.owned());
607 
608             let resource = resource.try_into_resource::<MyType>(&mut store)?;
609             assert_eq!(resource.rep(), 100);
610             assert!(resource.owned());
611 
612             let resource = resource.try_into_resource_any(&mut store)?;
613             assert_eq!(resource.ty(), ResourceType::host::<MyType>());
614             assert!(resource.owned());
615         }
616         _ => unreachable!(),
617     }
618 
619     let t1 = Resource::<MyType>::new_own(100)
620         .try_into_resource_any(&mut store)?
621         .try_into_resource(&mut store)?;
622     let (t1,) = a_typed_result.call(&mut store, (t1,))?;
623     assert_eq!(t1.rep(), 100);
624     assert!(t1.owned());
625 
626     let t1_any = t1
627         .try_into_resource_any(&mut store)?
628         .try_into_resource::<MyType>(&mut store)?
629         .try_into_resource_any(&mut store)?;
630     let mut results = [Val::Bool(false)];
631     a.call(&mut store, &[Val::Resource(t1_any)], &mut results)?;
632     match &results[0] {
633         Val::Resource(resource) => {
634             assert_eq!(resource.ty(), ResourceType::host::<MyType>());
635             assert!(resource.owned());
636 
637             let resource = resource.try_into_resource::<MyType>(&mut store)?;
638             assert_eq!(resource.rep(), 100);
639             assert!(resource.owned());
640 
641             let resource = resource.try_into_resource_any(&mut store)?;
642             assert_eq!(resource.ty(), ResourceType::host::<MyType>());
643             assert!(resource.owned());
644         }
645         _ => unreachable!(),
646     }
647 
648     b.call(&mut store, &[Val::U32(200)], &mut results)?;
649     match &results[0] {
650         Val::Resource(resource) => {
651             assert_eq!(resource.ty(), t2);
652         }
653         _ => unreachable!(),
654     }
655 
656     Ok(())
657 }
658 
659 #[test]
660 fn cannot_reenter_during_import() -> Result<()> {
661     let engine = super::engine();
662     let c = Component::new(
663         &engine,
664         r#"
665             (component
666                 (import "f" (func $f))
667 
668                 (core func $f (canon lower (func $f)))
669 
670                 (core module $m
671                     (import "" "f" (func $f))
672                     (func (export "call") call $f)
673                     (func (export "dtor") (param i32) unreachable)
674                 )
675 
676                 (core instance $i (instantiate $m
677                     (with "" (instance
678                         (export "f" (func $f))
679                     ))
680                 ))
681 
682                 (type $t2' (resource (rep i32) (dtor (func $i "dtor"))))
683                 (export $t2 "t" (type $t2'))
684                 (core func $ctor (canon resource.new $t2))
685                 (func (export "ctor") (param "x" u32) (result (own $t2))
686                     (canon lift (core func $ctor)))
687 
688                 (func (export "call") (canon lift (core func $i "call")))
689             )
690         "#,
691     )?;
692 
693     let mut store = Store::new(&engine, None);
694     let mut linker = Linker::new(&engine);
695     linker.root().func_wrap("f", |mut cx, ()| {
696         let data: &mut Option<ResourceAny> = cx.data_mut();
697         let err = data.take().unwrap().resource_drop(cx).unwrap_err();
698         assert_eq!(
699             err.downcast_ref(),
700             Some(&Trap::CannotEnterComponent),
701             "bad error: {err:?}"
702         );
703         Ok(())
704     })?;
705     let i = linker.instantiate(&mut store, &c)?;
706 
707     let ctor = i.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "ctor")?;
708     let call = i.get_typed_func::<(), ()>(&mut store, "call")?;
709 
710     let (resource,) = ctor.call(&mut store, (100,))?;
711     *store.data_mut() = Some(resource);
712     call.call(&mut store, ())?;
713 
714     Ok(())
715 }
716 
717 #[test]
718 fn active_borrows_at_end_of_call() -> Result<()> {
719     let engine = super::engine();
720     let c = Component::new(
721         &engine,
722         r#"
723             (component
724                 (import "t" (type $t (sub resource)))
725 
726                 (core module $m
727                     (func (export "f") (param i32))
728                 )
729                 (core instance $i (instantiate $m))
730 
731                 (func (export "f") (param "x" (borrow $t))
732                     (canon lift (core func $i "f")))
733             )
734         "#,
735     )?;
736 
737     struct MyType;
738 
739     let mut store = Store::new(&engine, ());
740     let mut linker = Linker::new(&engine);
741     linker
742         .root()
743         .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
744     let i = linker.instantiate(&mut store, &c)?;
745 
746     let f = i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "f")?;
747 
748     let resource = Resource::new_own(1);
749     let err = f.call(&mut store, (&resource,)).unwrap_err();
750     assert_eq!(
751         err.to_string(),
752         "borrow handles still remain at the end of the call",
753     );
754 
755     Ok(())
756 }
757 
758 #[test]
759 fn thread_through_borrow() -> Result<()> {
760     let engine = super::engine();
761     let c = Component::new(
762         &engine,
763         r#"
764             (component
765                 (import "t" (type $t (sub resource)))
766                 (import "f" (func $f (param "x" (borrow $t))))
767 
768                 (core func $f (canon lower (func $f)))
769                 (core func $drop (canon resource.drop $t))
770 
771                 (core module $m
772                     (import "" "f" (func $f (param i32)))
773                     (import "" "drop" (func $drop (param i32)))
774                     (func (export "f2") (param i32)
775                         (call $f (local.get 0))
776                         (call $f (local.get 0))
777                         (call $drop (local.get 0))
778                     )
779                 )
780                 (core instance $i (instantiate $m
781                     (with "" (instance
782                         (export "f" (func $f))
783                         (export "drop" (func $drop))
784                     ))
785                 ))
786 
787                 (func (export "f2") (param "x" (borrow $t))
788                     (canon lift (core func $i "f2")))
789             )
790         "#,
791     )?;
792 
793     struct MyType;
794 
795     let mut store = Store::new(&engine, ());
796     let mut linker = Linker::new(&engine);
797     linker
798         .root()
799         .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
800     linker
801         .root()
802         .func_wrap("f", |_cx, (r,): (Resource<MyType>,)| {
803             assert!(!r.owned());
804             assert_eq!(r.rep(), 100);
805             Ok(())
806         })?;
807     let i = linker.instantiate(&mut store, &c)?;
808 
809     let f = i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "f2")?;
810 
811     let resource = Resource::new_own(100);
812     f.call(&mut store, (&resource,))?;
813     Ok(())
814 }
815 
816 #[test]
817 fn cannot_use_borrow_for_own() -> Result<()> {
818     let engine = super::engine();
819     let c = Component::new(
820         &engine,
821         r#"
822             (component
823                 (import "t" (type $t (sub resource)))
824 
825                 (core module $m
826                     (func (export "f") (param i32) (result i32)
827                         local.get 0
828                     )
829                 )
830                 (core instance $i (instantiate $m))
831 
832                 (func (export "f") (param "x" (borrow $t)) (result (own $t))
833                     (canon lift (core func $i "f")))
834             )
835         "#,
836     )?;
837 
838     struct MyType;
839 
840     let mut store = Store::new(&engine, ());
841     let mut linker = Linker::new(&engine);
842     linker
843         .root()
844         .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
845     let i = linker.instantiate(&mut store, &c)?;
846 
847     let f = i.get_typed_func::<(&Resource<MyType>,), (Resource<MyType>,)>(&mut store, "f")?;
848 
849     let resource = Resource::new_own(100);
850     let err = f.call(&mut store, (&resource,)).unwrap_err();
851     assert_eq!(err.to_string(), "cannot lift own resource from a borrow");
852     Ok(())
853 }
854 
855 #[test]
856 fn can_use_own_for_borrow() -> Result<()> {
857     let engine = super::engine();
858     let c = Component::new(
859         &engine,
860         r#"
861             (component
862                 (import "t" (type $t (sub resource)))
863 
864                 (core func $drop (canon resource.drop $t))
865 
866                 (core module $m
867                     (import "" "drop" (func $drop (param i32)))
868                     (func (export "f") (param i32)
869                         (call $drop (local.get 0))
870                     )
871                 )
872                 (core instance $i (instantiate $m
873                     (with "" (instance
874                         (export "drop" (func $drop))
875                     ))
876                 ))
877 
878                 (func (export "f") (param "x" (borrow $t))
879                     (canon lift (core func $i "f")))
880             )
881         "#,
882     )?;
883 
884     struct MyType;
885 
886     let mut store = Store::new(&engine, ());
887     let mut linker = Linker::new(&engine);
888     linker
889         .root()
890         .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
891     let i_pre = linker.instantiate_pre(&c)?;
892     let i = i_pre.instantiate(&mut store)?;
893 
894     let f = i.get_func(&mut store, "f").unwrap();
895     let f_typed = i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "f")?;
896 
897     let resource = Resource::new_own(100);
898     f_typed.call(&mut store, (&resource,))?;
899 
900     let resource = Resource::new_borrow(200);
901     f_typed.call(&mut store, (&resource,))?;
902 
903     let resource = Resource::<MyType>::new_own(300).try_into_resource_any(&mut store)?;
904     f.call(&mut store, &[Val::Resource(resource)], &mut [])?;
905     resource.resource_drop(&mut store)?;
906 
907     // TODO: Enable once https://github.com/bytecodealliance/wasmtime/issues/7793 is fixed
908     //let resource =
909     //    Resource::<MyType>::new_borrow(400).try_into_resource_any(&mut store, &i_pre, ty_idx)?;
910     //f.call(&mut store, &[Val::Resource(resource)], &mut [])?;
911     //resource.resource_drop(&mut store)?;
912 
913     Ok(())
914 }
915 
916 #[test]
917 fn passthrough_wrong_type() -> Result<()> {
918     let engine = super::engine();
919     let c = Component::new(
920         &engine,
921         r#"
922             (component
923                 (import "t" (type $t (sub resource)))
924                 (import "f" (func $f (param "a" (borrow $t)) (result (own $t))))
925 
926                 (core func $f (canon lower (func $f)))
927 
928                 (core module $m
929                     (import "" "f" (func $f (param i32) (result i32)))
930                     (func (export "f2") (param i32)
931                         (drop (call $f (local.get 0)))
932                     )
933                 )
934                 (core instance $i (instantiate $m
935                     (with "" (instance
936                         (export "f" (func $f))
937                     ))
938                 ))
939 
940                 (func (export "f2") (param "x" (borrow $t))
941                     (canon lift (core func $i "f2")))
942             )
943         "#,
944     )?;
945 
946     struct MyType;
947 
948     let mut store = Store::new(&engine, ());
949     let mut linker = Linker::new(&engine);
950     linker
951         .root()
952         .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
953     linker
954         .root()
955         .func_wrap("f", |_cx, (r,): (Resource<MyType>,)| Ok((r,)))?;
956     let i = linker.instantiate(&mut store, &c)?;
957 
958     let f = i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "f2")?;
959 
960     let resource = Resource::new_own(100);
961     let err = f.call(&mut store, (&resource,)).unwrap_err();
962     assert!(
963         format!("{err:?}").contains("cannot lower a `borrow` resource into an `own`"),
964         "bad error: {err:?}"
965     );
966     Ok(())
967 }
968 
969 #[test]
970 fn pass_moved_resource() -> Result<()> {
971     let engine = super::engine();
972     let c = Component::new(
973         &engine,
974         r#"
975             (component
976                 (import "t" (type $t (sub resource)))
977                 (core module $m
978                     (func (export "f") (param i32 i32))
979                 )
980                 (core instance $i (instantiate $m))
981 
982                 (func (export "f") (param "x" (own $t)) (param "y" (borrow $t))
983                     (canon lift (core func $i "f")))
984             )
985         "#,
986     )?;
987 
988     struct MyType;
989 
990     let mut store = Store::new(&engine, ());
991     let mut linker = Linker::new(&engine);
992     linker
993         .root()
994         .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
995     let i = linker.instantiate(&mut store, &c)?;
996 
997     let f = i.get_typed_func::<(&Resource<MyType>, &Resource<MyType>), ()>(&mut store, "f")?;
998 
999     let resource = Resource::new_own(100);
1000     let err = f.call(&mut store, (&resource, &resource)).unwrap_err();
1001     assert!(
1002         format!("{err:?}").contains("host resource already consumed"),
1003         "bad error: {err:?}"
1004     );
1005     Ok(())
1006 }
1007 
1008 #[test]
1009 fn type_mismatch() -> Result<()> {
1010     let engine = super::engine();
1011     let c = Component::new(
1012         &engine,
1013         r#"
1014             (component
1015                 (type $t' (resource (rep i32)))
1016                 (export $t "t" (type $t'))
1017 
1018                 (core func $drop (canon resource.drop $t))
1019 
1020                 (func (export "f1") (param "x" (own $t))
1021                     (canon lift (core func $drop)))
1022                 (func (export "f2") (param "x" (borrow $t))
1023                     (canon lift (core func $drop)))
1024                 (func (export "f3") (param "x" u32)
1025                     (canon lift (core func $drop)))
1026             )
1027         "#,
1028     )?;
1029 
1030     struct MyType;
1031 
1032     let mut store = Store::new(&engine, ());
1033     let i = Linker::new(&engine).instantiate(&mut store, &c)?;
1034 
1035     assert!(
1036         i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "f1")
1037             .is_err()
1038     );
1039     assert!(
1040         i.get_typed_func::<(&ResourceAny,), ()>(&mut store, "f1")
1041             .is_ok()
1042     );
1043 
1044     assert!(
1045         i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "f2")
1046             .is_err()
1047     );
1048     assert!(
1049         i.get_typed_func::<(&ResourceAny,), ()>(&mut store, "f2")
1050             .is_ok()
1051     );
1052 
1053     assert!(
1054         i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "f3")
1055             .is_err()
1056     );
1057     assert!(
1058         i.get_typed_func::<(&ResourceAny,), ()>(&mut store, "f3")
1059             .is_err()
1060     );
1061     assert!(i.get_typed_func::<(u32,), ()>(&mut store, "f3").is_ok());
1062 
1063     Ok(())
1064 }
1065 
1066 #[test]
1067 fn drop_no_dtor() -> Result<()> {
1068     let engine = super::engine();
1069     let c = Component::new(
1070         &engine,
1071         r#"
1072             (component
1073                 (type $t' (resource (rep i32)))
1074                 (export $t "t" (type $t'))
1075 
1076                 (core func $ctor (canon resource.new $t))
1077 
1078                 (func (export "ctor") (param "x" u32) (result (own $t))
1079                     (canon lift (core func $ctor)))
1080             )
1081         "#,
1082     )?;
1083 
1084     let mut store = Store::new(&engine, ());
1085     let i = Linker::new(&engine).instantiate(&mut store, &c)?;
1086     let ctor = i.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "ctor")?;
1087     let (resource,) = ctor.call(&mut store, (100,))?;
1088     resource.resource_drop(&mut store)?;
1089 
1090     Ok(())
1091 }
1092 
1093 #[test]
1094 fn host_borrow_as_resource_any() -> Result<()> {
1095     let engine = super::engine();
1096     let c = Component::new(
1097         &engine,
1098         r#"
1099             (component
1100                 (import "t" (type $t (sub resource)))
1101                 (import "f" (func $f (param "f" (borrow $t))))
1102 
1103                 (core func $f (canon lower (func $f)))
1104                 (core func $drop (canon resource.drop $t))
1105 
1106                 (core module $m
1107                     (import "" "f" (func $f (param i32)))
1108                     (import "" "drop" (func $drop (param i32)))
1109                     (func (export "f2") (param i32)
1110                         (call $f (local.get 0))
1111                         (call $drop (local.get 0))
1112                     )
1113                 )
1114                 (core instance $i (instantiate $m
1115                     (with "" (instance
1116                         (export "f" (func $f))
1117                         (export "drop" (func $drop))
1118                     ))
1119                 ))
1120 
1121                 (func (export "f2") (param "x" (borrow $t))
1122                     (canon lift (core func $i "f2")))
1123             )
1124         "#,
1125     )?;
1126 
1127     struct MyType;
1128 
1129     let mut store = Store::new(&engine, ());
1130 
1131     // First test the above component where the host properly drops the argument
1132     {
1133         let mut linker = Linker::new(&engine);
1134         linker
1135             .root()
1136             .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
1137         linker
1138             .root()
1139             .func_wrap("f", |mut cx, (r,): (ResourceAny,)| {
1140                 r.resource_drop(&mut cx)?;
1141                 Ok(())
1142             })?;
1143         let i = linker.instantiate(&mut store, &c)?;
1144 
1145         let f = i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "f2")?;
1146 
1147         let resource = Resource::new_own(100);
1148         f.call(&mut store, (&resource,))?;
1149     }
1150 
1151     // Then also test the case where the host forgets a drop
1152     {
1153         let mut linker = Linker::new(&engine);
1154         linker
1155             .root()
1156             .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
1157         linker.root().func_wrap("f", |_cx, (_r,): (ResourceAny,)| {
1158             // ... no drop here
1159             Ok(())
1160         })?;
1161         let i = linker.instantiate(&mut store, &c)?;
1162 
1163         let f = i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "f2")?;
1164 
1165         let resource = Resource::new_own(100);
1166         let err = f.call(&mut store, (&resource,)).unwrap_err();
1167         assert!(
1168             format!("{err:?}").contains("borrow handles still remain at the end of the call"),
1169             "bad error: {err:?}"
1170         );
1171     }
1172     Ok(())
1173 }
1174 
1175 #[test]
1176 fn pass_guest_back_as_borrow() -> Result<()> {
1177     let engine = super::engine();
1178     let c = Component::new(
1179         &engine,
1180         r#"
1181             (component
1182                 (type $t' (resource (rep i32)))
1183 
1184                 (export $t "t" (type $t'))
1185 
1186                 (core func $new (canon resource.new $t))
1187 
1188                 (core module $m
1189                     (import "" "new" (func $new (param i32) (result i32)))
1190 
1191                     (func (export "mk") (result i32)
1192                         (call $new (i32.const 100))
1193                     )
1194 
1195                     (func (export "take") (param i32)
1196                         (if (i32.ne (local.get 0) (i32.const 100)) (then (unreachable)))
1197                     )
1198                 )
1199                 (core instance $i (instantiate $m
1200                     (with "" (instance
1201                         (export "new" (func $new))
1202                     ))
1203                 ))
1204 
1205                 (func (export "mk") (result (own $t))
1206                     (canon lift (core func $i "mk")))
1207                 (func (export "take") (param "x" (borrow $t))
1208                     (canon lift (core func $i "take")))
1209             )
1210         "#,
1211     )?;
1212 
1213     let mut store = Store::new(&engine, ());
1214     let i = Linker::new(&engine).instantiate(&mut store, &c)?;
1215     let mk = i.get_typed_func::<(), (ResourceAny,)>(&mut store, "mk")?;
1216     let take = i.get_typed_func::<(&ResourceAny,), ()>(&mut store, "take")?;
1217 
1218     let (resource,) = mk.call(&mut store, ())?;
1219     take.call(&mut store, (&resource,))?;
1220 
1221     resource.resource_drop(&mut store)?;
1222 
1223     // Should not be valid to use `resource` again
1224     let err = take.call(&mut store, (&resource,)).unwrap_err();
1225     assert_eq!(err.to_string(), "unknown handle index 1");
1226 
1227     Ok(())
1228 }
1229 
1230 #[test]
1231 fn pass_host_borrow_to_guest() -> Result<()> {
1232     let engine = super::engine();
1233     let c = Component::new(
1234         &engine,
1235         r#"
1236             (component
1237                 (import "t" (type $t (sub resource)))
1238 
1239                 (core func $drop (canon resource.drop $t))
1240 
1241                 (core module $m
1242                     (import "" "drop" (func $drop (param i32)))
1243                     (func (export "take") (param i32)
1244                       (call $drop (local.get 0))
1245                     )
1246                 )
1247                 (core instance $i (instantiate $m
1248                     (with "" (instance
1249                         (export "drop" (func $drop))
1250                     ))
1251                 ))
1252 
1253                 (func (export "take") (param "x" (borrow $t))
1254                     (canon lift (core func $i "take")))
1255             )
1256         "#,
1257     )?;
1258 
1259     struct MyType;
1260 
1261     let mut store = Store::new(&engine, ());
1262     let mut linker = Linker::new(&engine);
1263     linker
1264         .root()
1265         .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
1266     let i = linker.instantiate(&mut store, &c)?;
1267     let take = i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "take")?;
1268 
1269     let resource = Resource::new_borrow(100);
1270     take.call(&mut store, (&resource,))?;
1271 
1272     Ok(())
1273 }
1274 
1275 #[tokio::test]
1276 async fn drop_on_owned_resource() -> Result<()> {
1277     let mut config = wasmtime::Config::new();
1278     config.wasm_component_model_async(true);
1279     let engine = &wasmtime::Engine::new(&config)?;
1280     let c = Component::new(
1281         &engine,
1282         r#"
1283             (component
1284                 (import "t" (type $t (sub resource)))
1285                 (import "[constructor]t" (func $ctor (result (own $t))))
1286                 (import "[method]t.foo" (func $foo async (param "self" (borrow $t))))
1287 
1288                 (core func $ctor (canon lower (func $ctor)))
1289                 (core func $drop (canon resource.drop $t))
1290                 (core func $foo (canon lower (func $foo) async))
1291 
1292                 (core module $m
1293                     (import "" "ctor" (func $ctor (result i32)))
1294                     (import "" "foo" (func $foo (param i32) (result i32)))
1295                     (import "" "drop" (func $drop (param i32)))
1296 
1297                     (func (export "f")
1298                         (local $r i32)
1299                         (local $status i32)
1300                         (local.set $r (call $ctor))
1301                         (local.set $status (call $foo (local.get $r)))
1302                         (if (i32.ne (i32.const 1 (; STARTED ;)) (i32.and (local.get $status) (i32.const 0xf)))
1303                            (then unreachable))
1304                         (call $drop (local.get $r))
1305                         (unreachable)
1306                     )
1307                 )
1308                 (core instance $i (instantiate $m
1309                     (with "" (instance
1310                         (export "ctor" (func $ctor))
1311                         (export "foo" (func $foo))
1312                         (export "drop" (func $drop))
1313                     ))
1314                 ))
1315                 (func (export "f") async (canon lift (core func $i "f")))
1316             )
1317         "#,
1318     )?;
1319 
1320     struct MyType;
1321 
1322     let mut store = Store::new(&engine, ());
1323     let mut linker = Linker::new(&engine);
1324     linker
1325         .root()
1326         .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
1327     linker.root().func_wrap("[constructor]t", |_, ()| {
1328         Ok((Resource::<MyType>::new_own(300),))
1329     })?;
1330     linker
1331         .root()
1332         .func_wrap_concurrent("[method]t.foo", |_cx, (r,): (Resource<MyType>,)| {
1333             assert!(!r.owned());
1334             Box::pin(core::future::pending::<Result<()>>())
1335         })?;
1336     let i = linker.instantiate_async(&mut store, &c).await?;
1337     let f = i.get_typed_func::<(), ()>(&mut store, "f")?;
1338 
1339     let err = f.call_async(&mut store, ()).await.unwrap_err();
1340     assert!(
1341         format!("{err:?}").contains("cannot remove owned resource while borrowed"),
1342         "bad error: {err:?}"
1343     );
1344 
1345     Ok(())
1346 }
1347 
1348 #[test]
1349 fn guest_different_host_same() -> Result<()> {
1350     let engine = super::engine();
1351     let c = Component::new(
1352         &engine,
1353         r#"
1354             (component
1355                 (import "t1" (type $t1 (sub resource)))
1356                 (import "t2" (type $t2 (sub resource)))
1357 
1358                 (import "f" (func $f (param "a" (borrow $t1)) (param "b" (borrow $t2))))
1359 
1360                 (export $g1 "g1" (type $t1))
1361                 (export $g2 "g2" (type $t2))
1362 
1363                 (core func $f (canon lower (func $f)))
1364                 (core func $drop1 (canon resource.drop $t1))
1365                 (core func $drop2 (canon resource.drop $t2))
1366 
1367                 (core module $m
1368                     (import "" "f" (func $f (param i32 i32)))
1369                     (import "" "drop1" (func $drop1 (param i32)))
1370                     (import "" "drop2" (func $drop2 (param i32)))
1371 
1372                     (func (export "f") (param i32 i32)
1373                         ;; different types, but everything goes into the same
1374                         ;; handle index namespace
1375                         (if (i32.ne (local.get 0) (i32.const 1)) (then (unreachable)))
1376                         (if (i32.ne (local.get 1) (i32.const 2)) (then (unreachable)))
1377 
1378                         ;; host should end up getting the same resource
1379                         (call $f (local.get 0) (local.get 1))
1380 
1381                         ;; drop our borrows
1382                         (call $drop1 (local.get 0))
1383                         (call $drop2 (local.get 1))
1384                     )
1385                 )
1386                 (core instance $i (instantiate $m
1387                     (with "" (instance
1388                         (export "f" (func $f))
1389                         (export "drop1" (func $drop1))
1390                         (export "drop2" (func $drop2))
1391                     ))
1392                 ))
1393 
1394                 (func (export "f2") (param "a" (borrow $g1)) (param "b" (borrow $g2))
1395                     (canon lift (core func $i "f")))
1396             )
1397         "#,
1398     )?;
1399 
1400     struct MyType;
1401 
1402     let mut store = Store::new(&engine, ());
1403     let mut linker = Linker::new(&engine);
1404     linker
1405         .root()
1406         .resource("t1", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
1407     linker
1408         .root()
1409         .resource("t2", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
1410     linker.root().func_wrap(
1411         "f",
1412         |_cx, (r1, r2): (Resource<MyType>, Resource<MyType>)| {
1413             assert!(!r1.owned());
1414             assert!(!r2.owned());
1415             assert_eq!(r1.rep(), 100);
1416             assert_eq!(r2.rep(), 100);
1417             Ok(())
1418         },
1419     )?;
1420     let i = linker.instantiate(&mut store, &c)?;
1421     let f = i.get_typed_func::<(&Resource<MyType>, &Resource<MyType>), ()>(&mut store, "f2")?;
1422 
1423     let t1 = i.get_resource(&mut store, "g1").unwrap();
1424     let t2 = i.get_resource(&mut store, "g2").unwrap();
1425     assert_eq!(t1, t2);
1426     assert_eq!(t1, ResourceType::host::<MyType>());
1427 
1428     let resource = Resource::new_own(100);
1429     f.call(&mut store, (&resource, &resource))?;
1430 
1431     Ok(())
1432 }
1433 
1434 #[test]
1435 fn resource_any_to_typed_handles_borrow() -> Result<()> {
1436     let engine = super::engine();
1437     let c = Component::new(
1438         &engine,
1439         r#"
1440             (component
1441                 (import "t" (type $t (sub resource)))
1442 
1443                 (import "f" (func $f (param "a" (borrow $t))))
1444 
1445                 (core func $f (canon lower (func $f)))
1446 
1447                 (core module $m
1448                     (import "" "f" (func $f (param i32)))
1449 
1450                     (func (export "f") (param i32)
1451                         (call $f (local.get 0))
1452                     )
1453                 )
1454                 (core instance $i (instantiate $m
1455                     (with "" (instance
1456                         (export "f" (func $f))
1457                     ))
1458                 ))
1459 
1460                 (func (export "f") (param "a" (own $t))
1461                     (canon lift (core func $i "f")))
1462             )
1463         "#,
1464     )?;
1465 
1466     struct MyType;
1467 
1468     let mut store = Store::new(&engine, ());
1469     let mut linker = Linker::new(&engine);
1470     linker
1471         .root()
1472         .resource("t", ResourceType::host::<MyType>(), |_, _| Ok(()))?;
1473     linker
1474         .root()
1475         .func_wrap("f", |mut cx, (r,): (ResourceAny,)| {
1476             let r = r.try_into_resource::<MyType>(&mut cx).unwrap();
1477             assert_eq!(r.rep(), 100);
1478             assert!(!r.owned());
1479             Ok(())
1480         })?;
1481     let i = linker.instantiate(&mut store, &c)?;
1482     let f = i.get_typed_func::<(&Resource<MyType>,), ()>(&mut store, "f")?;
1483 
1484     let resource = Resource::new_own(100);
1485     f.call(&mut store, (&resource,))?;
1486 
1487     Ok(())
1488 }
1489 
1490 #[test]
1491 fn resource_dynamic() -> Result<()> {
1492     let r = ResourceDynamic::new_own(1, 2);
1493     assert_eq!(r.rep(), 1);
1494     assert!(r.owned());
1495     assert_eq!(r.ty(), 2);
1496 
1497     let engine = super::engine();
1498     let mut store = Store::new(&engine, ());
1499 
1500     let r2 = r.try_into_resource_any(&mut store)?;
1501     assert_eq!(r2.ty(), ResourceType::host_dynamic(2));
1502     assert!(r2.owned());
1503 
1504     let r3 = r2.try_into_resource_dynamic(&mut store)?;
1505     assert_eq!(r3.rep(), 1);
1506     assert_eq!(r3.ty(), 2);
1507 
1508     let c = Component::new(
1509         &engine,
1510         r#"
1511             (component
1512                 (import "t" (type $t (sub resource)))
1513                 (import "u" (type $u (sub resource)))
1514 
1515                 (core func $t_drop (canon resource.drop $t))
1516                 (core func $u_drop (canon resource.drop $u))
1517 
1518                 (func (export "drop-t") (param "x" (own $t))
1519                     (canon lift (core func $t_drop)))
1520                 (func (export "drop-u") (param "x" (own $u))
1521                     (canon lift (core func $u_drop)))
1522             )
1523         "#,
1524     )?;
1525     let mut linker = Linker::new(&engine);
1526     linker
1527         .root()
1528         .resource("t", ResourceType::host_dynamic(2), |_, _| Ok(()))?;
1529     linker
1530         .root()
1531         .resource("u", ResourceType::host_dynamic(3), |_, _| Ok(()))?;
1532     let instance = linker.instantiate(&mut store, &c)?;
1533 
1534     let drop_t = instance.get_typed_func::<(ResourceDynamic,), ()>(&mut store, "drop-t")?;
1535     let drop_u = instance.get_typed_func::<(ResourceDynamic,), ()>(&mut store, "drop-u")?;
1536 
1537     drop_t.call(&mut store, (ResourceDynamic::new_own(1, 2),))?;
1538 
1539     drop_u.call(&mut store, (ResourceDynamic::new_own(2, 3),))?;
1540 
1541     assert!(
1542         drop_t
1543             .call(&mut store, (ResourceDynamic::new_own(1, 1),))
1544             .is_err()
1545     );
1546 
1547     Ok(())
1548 }
1549 
1550 #[test]
1551 fn resource_dynamic_not_static() -> Result<()> {
1552     let engine = super::engine();
1553     let mut store = Store::new(&engine, ());
1554     let c = Component::new(
1555         &engine,
1556         r#"
1557             (component
1558                 (import "t" (type $t (sub resource)))
1559                 (core func $t_drop (canon resource.drop $t))
1560                 (func (export "drop-t") (param "x" (own $t))
1561                     (canon lift (core func $t_drop)))
1562             )
1563         "#,
1564     )?;
1565 
1566     struct T;
1567 
1568     {
1569         let mut linker = Linker::new(&engine);
1570         linker
1571             .root()
1572             .resource("t", ResourceType::host_dynamic(2), |_, _| Ok(()))?;
1573         let instance = linker.instantiate(&mut store, &c)?;
1574         instance.get_typed_func::<(ResourceDynamic,), ()>(&mut store, "drop-t")?;
1575         assert!(
1576             instance
1577                 .get_typed_func::<(Resource<T>,), ()>(&mut store, "drop-t")
1578                 .is_err()
1579         );
1580     }
1581 
1582     {
1583         let mut linker = Linker::new(&engine);
1584         linker
1585             .root()
1586             .resource("t", ResourceType::host::<T>(), |_, _| Ok(()))?;
1587         let instance = linker.instantiate(&mut store, &c)?;
1588         assert!(
1589             instance
1590                 .get_typed_func::<(ResourceDynamic,), ()>(&mut store, "drop-t")
1591                 .is_err()
1592         );
1593         instance.get_typed_func::<(Resource<T>,), ()>(&mut store, "drop-t")?;
1594     }
1595 
1596     Ok(())
1597 }
1598 
1599 #[test]
1600 fn intrinsic_trampolines() -> Result<()> {
1601     let engine = super::engine();
1602     let mut store = Store::new(&engine, ());
1603     let linker = Linker::new(&engine);
1604     let c = Component::new(
1605         &engine,
1606         r#"
1607 (component
1608   (type $r' (resource (rep i32)))
1609   (export $r "r" (type $r'))
1610 
1611   (core func $new (canon resource.new $r))
1612   (core func $rep (canon resource.rep $r))
1613 
1614   (func (export "new") (param "x" u32) (result (own $r))
1615     (canon lift (core func $new)))
1616   (func (export "rep") (param "x" (borrow $r)) (result u32)
1617     (canon lift (core func $rep)))
1618 )
1619 "#,
1620     )?;
1621     let i = linker.instantiate(&mut store, &c)?;
1622     let new = i.get_typed_func::<(u32,), (ResourceAny,)>(&mut store, "new")?;
1623     let rep = i.get_typed_func::<(ResourceAny,), (u32,)>(&mut store, "rep")?;
1624 
1625     let r = new.call(&mut store, (42,))?.0;
1626     assert!(rep.call(&mut store, (r,)).is_err());
1627     Ok(())
1628 }
1629 
1630 #[tokio::test]
1631 async fn drop_after_sync_lowered_async_host_function() -> Result<()> {
1632     let mut config = Config::new();
1633     config.wasm_component_model_async(true);
1634     let engine = Engine::new(&config)?;
1635     let mut store = Store::new(&engine, ());
1636     let mut linker = Linker::new(&engine);
1637     let c = Component::new(
1638         &engine,
1639         r#"
1640 (component
1641   (import "r" (type $r (sub resource)))
1642   ;;(import "f" (func $f async (param "x" (borrow $r)) (param "y" (borrow $r))))
1643   ;;(import "n" (func $n (result (own $r))))
1644   (import "f" (func $f async))
1645 
1646 
1647   (component $A
1648     (import "f" (func $f async))
1649     (core module $m
1650       (import "" "f" (func $f))
1651       (func (export "call") (result i32) call $f i32.const 0)
1652       (func (export "cb") (param i32 i32 i32) (result i32) unreachable)
1653     )
1654     (core func $f (canon lower (func $f)))
1655     (core instance $i (instantiate $m
1656         (with "" (instance (export "f" (func $f))))
1657     ))
1658     (func (export "call") async
1659       (canon lift (core func $i "call")
1660         async
1661         (callback (func $i "cb"))))
1662   )
1663 
1664   (component $B
1665     (import "r" (type $r (sub resource)))
1666     (import "f" (func $f async))
1667     (core module $m
1668       (import "" "f" (func $f (result i32)))
1669       (import "" "r" (func $r))
1670       (import "" "drop" (func $drop (param i32)))
1671       (func (export "call") (param i32) (result i32)
1672         ;; Call into component `$A` which is an async-lifted function. This
1673         ;; function will call a sync-lowered async function from the host. In
1674         ;; effect this means that the task started here by calling `$f` is
1675         ;; blocked.
1676         call $f
1677         drop ;; ignore the `SUBTASK_STARTED` status code
1678 
1679         ;; Now drop our borrow that this function was provided. This is
1680         ;; entirely disconnected from `$A` and it should be using the borrow
1681         ;; tracking of this task, no other task.
1682         (call $drop (local.get 0))
1683 
1684         ;; Now finish up this task without actually waiting on `$A`.
1685         call $r
1686         i32.const 0
1687       )
1688       (func (export "cb") (param i32 i32 i32) (result i32) unreachable)
1689     )
1690     (core func $f (canon lower (func $f) async))
1691     (core func $r (canon task.return))
1692     (core func $drop (canon resource.drop $r))
1693     (core instance $i (instantiate $m
1694       (with "" (instance
1695         (export "f" (func $f))
1696         (export "r" (func $r))
1697         (export "drop" (func $drop))
1698       ))
1699     ))
1700     (func (export "call") async (param "x" (borrow $r))
1701         (canon lift (core func $i "call")
1702             async
1703             (callback (func $i "cb"))))
1704   )
1705   (instance $a (instantiate $A (with "f" (func $f))))
1706   (instance $b (instantiate $B
1707     (with "f" (func $a "call"))
1708     (with "r" (type $r))
1709 ))
1710   (export "call" (func $b "call"))
1711 )
1712 "#,
1713     )?;
1714 
1715     let mut root = linker.root();
1716     root.resource("r", ResourceType::host::<u32>(), |_, _| Ok(()))?;
1717     root.func_wrap_concurrent("f", |_accessor, ()| {
1718         Box::pin(async move { std::future::pending::<Result<()>>().await })
1719     })?;
1720 
1721     let i = linker.instantiate_async(&mut store, &c).await?;
1722     let call = i.get_typed_func::<(Resource<u32>,), ()>(&mut store, "call")?;
1723     let r = Resource::new_borrow(3);
1724     call.call_async(&mut store, (r,)).await?;
1725     Ok(())
1726 }
1727