@@ -589,36 +589,38 @@ impl Jvm {
589589 self . is_assignable ( & instance. class_definition ( ) . name ( ) , class_name)
590590 }
591591
592- // aastore: whether value may be stored into array (JVMS 6.5 aastore); array component is always a reference type
592+ // aastore: whether value may be stored into array (JVMS 6.5 aastore)
593593 pub fn array_store_allowed ( & self , array : & dyn ClassInstance , value : & dyn ClassInstance ) -> bool {
594- let component = component_name ( & array. class_definition ( ) . name ( ) [ 1 ..] ) ;
594+ let JavaType :: Array ( component) = JavaType :: parse ( & array. class_definition ( ) . name ( ) ) else {
595+ return true ;
596+ } ;
595597
596- self . is_assignable ( & value. class_definition ( ) . name ( ) , & component)
598+ self . is_type_assignable ( & name_to_type ( & value. class_definition ( ) . name ( ) ) , & component)
597599 }
598600
599601 // JVMS 4.10.3 subtyping, including array covariance. Names are in internal form: classes as
600602 // binary names (java/lang/String), arrays as descriptors ([Ljava/lang/String;, [I).
601603 pub fn is_assignable ( & self , source : & str , target : & str ) -> bool {
604+ self . is_type_assignable ( & name_to_type ( source) , & name_to_type ( target) )
605+ }
606+
607+ fn is_type_assignable ( & self , source : & JavaType , target : & JavaType ) -> bool {
602608 if source == target {
603609 return true ;
604610 }
605611
606- // a primitive array component only matches its exact type
607- if is_primitive_descriptor ( source) {
608- return false ;
609- }
610-
611- if let Some ( source_component) = source. strip_prefix ( '[' ) {
612- if target == "java/lang/Object" || target == "java/lang/Cloneable" || target == "java/io/Serializable" {
613- return true ;
612+ match ( source, target) {
613+ ( JavaType :: Array ( source_component) , JavaType :: Array ( target_component) ) => self . is_type_assignable ( source_component, target_component) ,
614+ // every array type is a subtype of Object, Cloneable, and java.io.Serializable (JLS 4.10.3)
615+ ( JavaType :: Array ( _) , JavaType :: Class ( name) ) => {
616+ name == "java/lang/Object" || name == "java/lang/Cloneable" || name == "java/io/Serializable"
614617 }
615-
616- return match target. strip_prefix ( '[' ) {
617- Some ( target_component) => self . is_assignable ( & component_name ( source_component) , & component_name ( target_component) ) ,
618- None => false ,
619- } ;
618+ ( JavaType :: Class ( source) , JavaType :: Class ( target) ) => self . is_class_assignable ( source, target) ,
619+ _ => false ,
620620 }
621+ }
621622
623+ fn is_class_assignable ( & self , source : & str , target : & str ) -> bool {
622624 match self . get_class ( source) {
623625 Some ( class) => self . is_inherited_from ( & * class. definition , target) ,
624626 None => false ,
@@ -949,15 +951,11 @@ impl Jvm {
949951 }
950952}
951953
952- fn is_primitive_descriptor ( name : & str ) -> bool {
953- matches ! ( name, "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z" )
954- }
955-
956- // converts an array component descriptor to internal name form: Lfoo/Bar; -> foo/Bar, [X and primitives unchanged
957- fn component_name ( descriptor : & str ) -> String {
958- if let Some ( class) = descriptor. strip_prefix ( 'L' ) . and_then ( |x| x. strip_suffix ( ';' ) ) {
959- class. to_owned ( )
954+ // a class binary name (java/lang/String) or an array descriptor ([Ljava/lang/String;, [I) as a JavaType
955+ fn name_to_type ( name : & str ) -> JavaType {
956+ if name. starts_with ( '[' ) {
957+ JavaType :: parse ( name)
960958 } else {
961- descriptor . to_owned ( )
959+ JavaType :: Class ( name . to_owned ( ) )
962960 }
963961}
0 commit comments