@@ -605,8 +605,8 @@ where
605605 }
606606
607607 /// Pop a reference type from the operand stack.
608- fn pop_ref ( & mut self ) -> Result < Option < RefType > > {
609- match self . pop_operand ( None ) ? {
608+ fn pop_ref ( & mut self , expected : Option < RefType > ) -> Result < Option < RefType > > {
609+ match self . pop_operand ( expected . map ( |t| t . into ( ) ) ) ? {
610610 MaybeType :: Bot | MaybeType :: HeapBot => Ok ( None ) ,
611611 MaybeType :: Type ( ValType :: Ref ( rt) ) => Ok ( Some ( rt) ) ,
612612 MaybeType :: Type ( ty) => bail ! (
@@ -626,7 +626,7 @@ where
626626 & mut self ,
627627 expected : AbstractHeapType ,
628628 ) -> Result < Option < ( RefType , bool ) > > {
629- let actual = match self . pop_ref ( ) ? {
629+ let actual = match self . pop_ref ( None ) ? {
630630 Some ( rt) => rt,
631631 None => return Ok ( None ) ,
632632 } ;
@@ -881,18 +881,8 @@ where
881881 let unpacked_index = UnpackedIndex :: Module ( type_index) ;
882882 let mut hty = HeapType :: Concrete ( unpacked_index) ;
883883 self . resources . check_heap_type ( & mut hty, self . offset ) ?;
884- // If `None` is popped then that means a "bottom" type was popped which
885- // is always considered equivalent to the `hty` tag.
886- if let Some ( rt) = self . pop_ref ( ) ? {
887- let expected = RefType :: new ( true , hty) . expect ( "hty should be previously validated" ) ;
888- let expected = ValType :: Ref ( expected) ;
889- if !self . resources . is_subtype ( ValType :: Ref ( rt) , expected) {
890- bail ! (
891- self . offset,
892- "type mismatch: funcref on stack does not match specified type" ,
893- ) ;
894- }
895- }
884+ let expected = RefType :: new ( true , hty) . expect ( "hty should be previously validated" ) ;
885+ self . pop_ref ( Some ( expected) ) ?;
896886 self . func_type_at ( type_index)
897887 }
898888
@@ -1130,51 +1120,31 @@ where
11301120
11311121 /// Common helper for `ref.test` and `ref.cast` downcasting/checking
11321122 /// instructions. Returns the given `heap_type` as a `ValType`.
1133- fn check_downcast (
1134- & mut self ,
1135- nullable : bool ,
1136- mut heap_type : HeapType ,
1137- inst_name : & str ,
1138- ) -> Result < ValType > {
1123+ fn check_downcast ( & mut self , nullable : bool , mut heap_type : HeapType ) -> Result < RefType > {
11391124 self . resources
11401125 . check_heap_type ( & mut heap_type, self . offset ) ?;
11411126
1142- let sub_ty = RefType :: new ( nullable, heap_type)
1143- . map ( ValType :: from)
1144- . ok_or_else ( || {
1145- BinaryReaderError :: new ( "implementation limit: type index too large" , self . offset )
1146- } ) ?;
1147-
1148- let sup_ty = self . pop_ref ( ) ?. unwrap_or_else ( || {
1149- sub_ty
1150- . as_reference_type ( )
1151- . expect ( "we created this as a reference just above" )
1152- } ) ;
1153- let sup_ty = RefType :: new ( true , self . resources . top_type ( & sup_ty. heap_type ( ) ) )
1127+ let sub_ty = RefType :: new ( nullable, heap_type) . ok_or_else ( || {
1128+ BinaryReaderError :: new ( "implementation limit: type index too large" , self . offset )
1129+ } ) ?;
1130+ let sup_ty = RefType :: new ( true , self . resources . top_type ( & heap_type) )
11541131 . expect ( "can't panic with non-concrete heap types" ) ;
11551132
1156- if !self . resources . is_subtype ( sub_ty, sup_ty. into ( ) ) {
1157- bail ! (
1158- self . offset,
1159- "{inst_name}'s heap type must be a sub type of the type on the stack: \
1160- {sub_ty} is not a sub type of {sup_ty}"
1161- ) ;
1162- }
1163-
1133+ self . pop_ref ( Some ( sup_ty) ) ?;
11641134 Ok ( sub_ty)
11651135 }
11661136
11671137 /// Common helper for both nullable and non-nullable variants of `ref.test`
11681138 /// instructions.
11691139 fn check_ref_test ( & mut self , nullable : bool , heap_type : HeapType ) -> Result < ( ) > {
1170- self . check_downcast ( nullable, heap_type, "ref.test" ) ?;
1140+ self . check_downcast ( nullable, heap_type) ?;
11711141 self . push_operand ( ValType :: I32 )
11721142 }
11731143
11741144 /// Common helper for both nullable and non-nullable variants of `ref.cast`
11751145 /// instructions.
11761146 fn check_ref_cast ( & mut self , nullable : bool , heap_type : HeapType ) -> Result < ( ) > {
1177- let sub_ty = self . check_downcast ( nullable, heap_type, "ref.cast" ) ?;
1147+ let sub_ty = self . check_downcast ( nullable, heap_type) ?;
11781148 self . push_operand ( sub_ty)
11791149 }
11801150
@@ -2696,15 +2666,15 @@ where
26962666 }
26972667
26982668 fn visit_ref_as_non_null ( & mut self ) -> Self :: Output {
2699- let ty = match self . pop_ref ( ) ? {
2669+ let ty = match self . pop_ref ( None ) ? {
27002670 Some ( ty) => MaybeType :: Type ( ValType :: Ref ( ty. as_non_null ( ) ) ) ,
27012671 None => MaybeType :: HeapBot ,
27022672 } ;
27032673 self . push_operand ( ty) ?;
27042674 Ok ( ( ) )
27052675 }
27062676 fn visit_br_on_null ( & mut self , relative_depth : u32 ) -> Self :: Output {
2707- let ref_ty = match self . pop_ref ( ) ? {
2677+ let ref_ty = match self . pop_ref ( None ) ? {
27082678 None => MaybeType :: HeapBot ,
27092679 Some ( ty) => MaybeType :: Type ( ValType :: Ref ( ty. as_non_null ( ) ) ) ,
27102680 } ;
@@ -2715,41 +2685,27 @@ where
27152685 Ok ( ( ) )
27162686 }
27172687 fn visit_br_on_non_null ( & mut self , relative_depth : u32 ) -> Self :: Output {
2718- let ty = self . pop_ref ( ) ?;
27192688 let ( ft, kind) = self . jump ( relative_depth) ?;
27202689
27212690 let mut label_types = self . label_types ( ft, kind) ?;
2722- match ( label_types. next_back ( ) , ty ) {
2723- ( None , _ ) => bail ! (
2691+ let expected = match label_types. next_back ( ) {
2692+ None => bail ! (
27242693 self . offset,
27252694 "type mismatch: br_on_non_null target has no label types" ,
27262695 ) ,
2727- ( Some ( ValType :: Ref ( _) ) , None ) => { }
2728- ( Some ( rt1 @ ValType :: Ref ( _) ) , Some ( rt0) ) => {
2729- // Switch rt0, our popped type, to a non-nullable type and
2730- // perform the match because if the branch is taken it's a
2731- // non-null value.
2732- let ty = rt0. as_non_null ( ) ;
2733- if !self . resources . is_subtype ( ty. into ( ) , rt1) {
2734- bail ! (
2735- self . offset,
2736- "type mismatch: expected {} but found {}" ,
2737- ty_to_str( rt0. into( ) ) ,
2738- ty_to_str( rt1)
2739- )
2740- }
2741- }
2742- ( Some ( _) , _) => bail ! (
2696+ Some ( ValType :: Ref ( ty) ) => ty,
2697+ Some ( _) => bail ! (
27432698 self . offset,
27442699 "type mismatch: br_on_non_null target does not end with heap type" ,
27452700 ) ,
2746- }
2701+ } ;
2702+ self . pop_ref ( Some ( expected. nullable ( ) ) ) ?;
27472703
27482704 self . pop_push_label_types ( label_types) ?;
27492705 Ok ( ( ) )
27502706 }
27512707 fn visit_ref_is_null ( & mut self ) -> Self :: Output {
2752- self . pop_ref ( ) ?;
2708+ self . pop_ref ( None ) ?;
27532709 self . push_operand ( ValType :: I32 ) ?;
27542710 Ok ( ( ) )
27552711 }
0 commit comments