@@ -685,10 +685,8 @@ struct Inhabitator {
685
685
//
686
686
// An invariant field of a heaptype must have the same type in subtypes of
687
687
// that heaptype. A covariant field of a heaptype must be typed with a subtype
688
- // of its original type in subtypes of the heaptype. A contravariant field of
689
- // a heap type must be typed with a supertype of its original type in subtypes
690
- // of the heaptype.
691
- enum Variance { Invariant, Covariant, Contravariant };
688
+ // of its original type in subtypes of the heaptype.
689
+ enum Variance { Invariant, Covariant };
692
690
693
691
// The input types.
694
692
const std::vector<HeapType>& types;
@@ -712,7 +710,7 @@ struct Inhabitator {
712
710
713
711
Inhabitator::Variance Inhabitator::getVariance (FieldPos field) {
714
712
auto [type, idx] = field;
715
- assert (!type.isBasic ());
713
+ assert (!type.isBasic () && !type. isSignature () );
716
714
if (type.isStruct ()) {
717
715
if (type.getStruct ().fields [idx].mutable_ == Mutable) {
718
716
return Invariant;
@@ -727,13 +725,6 @@ Inhabitator::Variance Inhabitator::getVariance(FieldPos field) {
727
725
return Covariant;
728
726
}
729
727
}
730
- if (type.isSignature ()) {
731
- if (idx < type.getSignature ().params .size ()) {
732
- return Contravariant;
733
- } else {
734
- return Covariant;
735
- }
736
- }
737
728
WASM_UNREACHABLE (" unexpected kind" );
738
729
}
739
730
@@ -768,8 +759,6 @@ void Inhabitator::markNullable(FieldPos field) {
768
759
curr = *super;
769
760
}
770
761
}
771
- [[fallthrough]];
772
- case Contravariant:
773
762
// Mark the field nullable in all subtypes. If the subtype field is
774
763
// already nullable, that's ok and this will have no effect. TODO: Remove
775
764
// this extra `index` variable once we have C++20. It's a workaround for
@@ -784,6 +773,11 @@ void Inhabitator::markNullable(FieldPos field) {
784
773
785
774
void Inhabitator::markBottomRefsNullable () {
786
775
for (auto type : types) {
776
+ if (type.isSignature ()) {
777
+ // Functions can always be instantiated, even if their types refer to
778
+ // uninhabitable types.
779
+ continue ;
780
+ }
787
781
auto children = type.getTypeChildren ();
788
782
for (size_t i = 0 ; i < children.size (); ++i) {
789
783
auto child = children[i];
@@ -801,6 +795,11 @@ void Inhabitator::markExternRefsNullable() {
801
795
// TODO: Remove this once the fuzzer imports externref globals or gets some
802
796
// other way to instantiate externrefs.
803
797
for (auto type : types) {
798
+ if (type.isSignature ()) {
799
+ // Functions can always be instantiated, even if their types refer to
800
+ // uninhabitable types.
801
+ continue ;
802
+ }
804
803
auto children = type.getTypeChildren ();
805
804
for (size_t i = 0 ; i < children.size (); ++i) {
806
805
auto child = children[i];
@@ -863,6 +862,14 @@ void Inhabitator::breakNonNullableCycles() {
863
862
++idx;
864
863
continue ;
865
864
}
865
+ // Skip references to function types. Functions types can always be
866
+ // instantiated since functions can be created even with uninhabitable
867
+ // params or results. Function references therefore break cycles that
868
+ // would otherwise produce uninhabitability.
869
+ if (heapType.isSignature ()) {
870
+ ++idx;
871
+ continue ;
872
+ }
866
873
// If this ref forms a cycle, break the cycle by marking it nullable and
867
874
// continue.
868
875
if (auto it = visiting.find (heapType); it != visiting.end ()) {
0 commit comments