@@ -249,13 +249,50 @@ pub(crate) struct SubType {
249
249
pub ( crate ) composite_type : CompositeType ,
250
250
}
251
251
252
+ impl SubType {
253
+ fn unwrap_struct ( & self ) -> & StructType {
254
+ self . composite_type . unwrap_struct ( )
255
+ }
256
+
257
+ fn unwrap_func ( & self ) -> & Rc < FuncType > {
258
+ self . composite_type . unwrap_func ( )
259
+ }
260
+
261
+ fn unwrap_array ( & self ) -> & ArrayType {
262
+ self . composite_type . unwrap_array ( )
263
+ }
264
+ }
265
+
252
266
#[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
253
267
pub ( crate ) enum CompositeType {
254
268
Array ( ArrayType ) ,
255
269
Func ( Rc < FuncType > ) ,
256
270
Struct ( StructType ) ,
257
271
}
258
272
273
+ impl CompositeType {
274
+ fn unwrap_struct ( & self ) -> & StructType {
275
+ match self {
276
+ CompositeType :: Struct ( s) => s,
277
+ _ => panic ! ( "not a struct" ) ,
278
+ }
279
+ }
280
+
281
+ fn unwrap_func ( & self ) -> & Rc < FuncType > {
282
+ match self {
283
+ CompositeType :: Func ( f) => f,
284
+ _ => panic ! ( "not a func" ) ,
285
+ }
286
+ }
287
+
288
+ fn unwrap_array ( & self ) -> & ArrayType {
289
+ match self {
290
+ CompositeType :: Array ( a) => a,
291
+ _ => panic ! ( "not an array" ) ,
292
+ }
293
+ }
294
+ }
295
+
259
296
/// A function signature.
260
297
#[ derive( Clone , Debug , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
261
298
pub ( crate ) struct FuncType {
@@ -392,6 +429,96 @@ impl Module {
392
429
Ok ( ( ) )
393
430
}
394
431
432
+ #[ inline]
433
+ fn val_type_is_sub_type ( & self , a : ValType , b : ValType ) -> bool {
434
+ match ( a, b) {
435
+ ( a, b) if a == b => true ,
436
+ ( ValType :: Ref ( a) , ValType :: Ref ( b) ) => self . ref_type_is_sub_type ( a, b) ,
437
+ _ => false ,
438
+ }
439
+ }
440
+
441
+ /// Is `a` a subtype of `b`?
442
+ fn ref_type_is_sub_type ( & self , a : RefType , b : RefType ) -> bool {
443
+ if a == b {
444
+ return true ;
445
+ }
446
+
447
+ if a. nullable && !b. nullable {
448
+ return false ;
449
+ }
450
+
451
+ self . heap_type_is_sub_type ( a. heap_type , b. heap_type )
452
+ }
453
+
454
+ fn heap_type_is_sub_type ( & self , a : HeapType , b : HeapType ) -> bool {
455
+ use HeapType as HT ;
456
+ match ( a, b) {
457
+ ( a, b) if a == b => true ,
458
+
459
+ ( HT :: Eq | HT :: I31 | HT :: Struct | HT :: Array | HT :: None , HT :: Any ) => true ,
460
+ ( HT :: I31 | HT :: Struct | HT :: Array | HT :: None , HT :: Eq ) => true ,
461
+ ( HT :: NoExtern , HT :: Extern ) => true ,
462
+ ( HT :: NoFunc , HT :: Func ) => true ,
463
+ ( HT :: None , HT :: I31 | HT :: Array | HT :: Struct ) => true ,
464
+
465
+ ( HT :: Concrete ( a) , HT :: Eq | HT :: Any ) => matches ! (
466
+ self . ty( a) . composite_type,
467
+ CompositeType :: Array ( _) | CompositeType :: Struct ( _)
468
+ ) ,
469
+
470
+ ( HT :: Concrete ( a) , HT :: Struct ) => {
471
+ matches ! ( self . ty( a) . composite_type, CompositeType :: Struct ( _) )
472
+ }
473
+
474
+ ( HT :: Concrete ( a) , HT :: Array ) => {
475
+ matches ! ( self . ty( a) . composite_type, CompositeType :: Array ( _) )
476
+ }
477
+
478
+ ( HT :: Concrete ( a) , HT :: Func ) => {
479
+ matches ! ( self . ty( a) . composite_type, CompositeType :: Func ( _) )
480
+ }
481
+
482
+ ( HT :: Concrete ( mut a) , HT :: Concrete ( b) ) => loop {
483
+ if a == b {
484
+ return true ;
485
+ }
486
+ if let Some ( supertype) = self . ty ( a) . supertype {
487
+ a = supertype;
488
+ } else {
489
+ return false ;
490
+ }
491
+ } ,
492
+
493
+ ( HT :: None , HT :: Concrete ( b) ) => matches ! (
494
+ self . ty( b) . composite_type,
495
+ CompositeType :: Array ( _) | CompositeType :: Struct ( _)
496
+ ) ,
497
+
498
+ ( HT :: NoFunc , HT :: Concrete ( b) ) => {
499
+ matches ! ( self . ty( b) . composite_type, CompositeType :: Func ( _) )
500
+ }
501
+
502
+ // Nothing else matches. (Avoid full wildcard matches so that
503
+ // adding/modifying variants is easier in the future.)
504
+ ( HT :: Concrete ( _) , _)
505
+ | ( HT :: Func , _)
506
+ | ( HT :: Extern , _)
507
+ | ( HT :: Any , _)
508
+ | ( HT :: None , _)
509
+ | ( HT :: NoExtern , _)
510
+ | ( HT :: NoFunc , _)
511
+ | ( HT :: Eq , _)
512
+ | ( HT :: Struct , _)
513
+ | ( HT :: Array , _)
514
+ | ( HT :: I31 , _) => false ,
515
+
516
+ // TODO: `exn` probably will be its own type hierarchy and will
517
+ // probably get `noexn` as well.
518
+ ( HT :: Exn , _) => false ,
519
+ }
520
+ }
521
+
395
522
fn arbitrary_types ( & mut self , u : & mut Unstructured ) -> Result < ( ) > {
396
523
assert ! ( self . config. min_types <= self . config. max_types) ;
397
524
while self . types . len ( ) < self . config . min_types {
@@ -601,28 +728,17 @@ impl Module {
601
728
}
602
729
}
603
730
604
- fn arbitrary_matching_ref_type (
605
- & mut self ,
606
- u : & mut Unstructured ,
607
- ty : RefType ,
608
- ) -> Result < RefType > {
731
+ fn arbitrary_matching_ref_type ( & self , u : & mut Unstructured , ty : RefType ) -> Result < RefType > {
609
732
Ok ( RefType {
610
- // TODO: For now, only create allow nullable reference
611
- // types. Eventually we should support non-nullable reference types,
612
- // but this means that we will also need to recognize when it is
613
- // impossible to create an instance of the reference (eg `(ref
614
- // nofunc)` has no instances, and self-referential types that
615
- // contain a non-null self-reference are also impossible to create).
616
- nullable : true ,
733
+ nullable : ty. nullable ,
617
734
heap_type : self . arbitrary_matching_heap_type ( u, ty. heap_type ) ?,
618
735
} )
619
736
}
620
737
621
- fn arbitrary_matching_heap_type (
622
- & mut self ,
623
- u : & mut Unstructured ,
624
- ty : HeapType ,
625
- ) -> Result < HeapType > {
738
+ fn arbitrary_matching_heap_type ( & self , u : & mut Unstructured , ty : HeapType ) -> Result < HeapType > {
739
+ if !self . config . gc_enabled {
740
+ return Ok ( ty) ;
741
+ }
626
742
use HeapType as HT ;
627
743
let mut choices = vec ! [ ty] ;
628
744
match ty {
@@ -716,7 +832,7 @@ impl Module {
716
832
}
717
833
718
834
fn arbitrary_super_type_of_ref_type (
719
- & mut self ,
835
+ & self ,
720
836
u : & mut Unstructured ,
721
837
ty : RefType ,
722
838
) -> Result < RefType > {
@@ -733,10 +849,13 @@ impl Module {
733
849
}
734
850
735
851
fn arbitrary_super_type_of_heap_type (
736
- & mut self ,
852
+ & self ,
737
853
u : & mut Unstructured ,
738
854
ty : HeapType ,
739
855
) -> Result < HeapType > {
856
+ if !self . config . gc_enabled {
857
+ return Ok ( ty) ;
858
+ }
740
859
use HeapType as HT ;
741
860
let mut choices = vec ! [ ty] ;
742
861
match ty {
@@ -860,6 +979,45 @@ impl Module {
860
979
}
861
980
}
862
981
982
+ fn arbitrary_ref_type ( & self , u : & mut Unstructured ) -> Result < RefType > {
983
+ Ok ( RefType {
984
+ nullable : true ,
985
+ heap_type : self . arbitrary_heap_type ( u) ?,
986
+ } )
987
+ }
988
+
989
+ fn arbitrary_heap_type ( & self , u : & mut Unstructured ) -> Result < HeapType > {
990
+ assert ! ( self . config. reference_types_enabled) ;
991
+
992
+ if self . config . gc_enabled && !self . types . is_empty ( ) && u. arbitrary ( ) ? {
993
+ let type_ref_limit = u32:: try_from ( self . types . len ( ) ) . unwrap ( ) ;
994
+ let idx = u. int_in_range ( 0 ..=type_ref_limit) ?;
995
+ return Ok ( HeapType :: Concrete ( idx) ) ;
996
+ }
997
+
998
+ let mut choices = vec ! [ HeapType :: Func , HeapType :: Extern ] ;
999
+ if self . config . exceptions_enabled {
1000
+ choices. push ( HeapType :: Exn ) ;
1001
+ }
1002
+ if self . config . gc_enabled {
1003
+ choices. extend (
1004
+ [
1005
+ HeapType :: Any ,
1006
+ HeapType :: None ,
1007
+ HeapType :: NoExtern ,
1008
+ HeapType :: NoFunc ,
1009
+ HeapType :: Eq ,
1010
+ HeapType :: Struct ,
1011
+ HeapType :: Array ,
1012
+ HeapType :: I31 ,
1013
+ ]
1014
+ . iter ( )
1015
+ . copied ( ) ,
1016
+ ) ;
1017
+ }
1018
+ u. choose ( & choices) . copied ( )
1019
+ }
1020
+
863
1021
fn arbitrary_func_type (
864
1022
& mut self ,
865
1023
u : & mut Unstructured ,
@@ -2212,6 +2370,7 @@ flags! {
2212
2370
Table ,
2213
2371
Memory ,
2214
2372
Control ,
2373
+ Aggregate ,
2215
2374
}
2216
2375
}
2217
2376
0 commit comments