@@ -685,10 +685,8 @@ struct Inhabitator {
685685 //
686686 // An invariant field of a heaptype must have the same type in subtypes of
687687 // 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 };
692690
693691 // The input types.
694692 const std::vector<HeapType>& types;
@@ -712,7 +710,7 @@ struct Inhabitator {
712710
713711Inhabitator::Variance Inhabitator::getVariance (FieldPos field) {
714712 auto [type, idx] = field;
715- assert (!type.isBasic ());
713+ assert (!type.isBasic () && !type. isSignature () );
716714 if (type.isStruct ()) {
717715 if (type.getStruct ().fields [idx].mutable_ == Mutable) {
718716 return Invariant;
@@ -727,13 +725,6 @@ Inhabitator::Variance Inhabitator::getVariance(FieldPos field) {
727725 return Covariant;
728726 }
729727 }
730- if (type.isSignature ()) {
731- if (idx < type.getSignature ().params .size ()) {
732- return Contravariant;
733- } else {
734- return Covariant;
735- }
736- }
737728 WASM_UNREACHABLE (" unexpected kind" );
738729}
739730
@@ -768,8 +759,6 @@ void Inhabitator::markNullable(FieldPos field) {
768759 curr = *super;
769760 }
770761 }
771- [[fallthrough]];
772- case Contravariant:
773762 // Mark the field nullable in all subtypes. If the subtype field is
774763 // already nullable, that's ok and this will have no effect. TODO: Remove
775764 // this extra `index` variable once we have C++20. It's a workaround for
@@ -784,6 +773,11 @@ void Inhabitator::markNullable(FieldPos field) {
784773
785774void Inhabitator::markBottomRefsNullable () {
786775 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+ }
787781 auto children = type.getTypeChildren ();
788782 for (size_t i = 0 ; i < children.size (); ++i) {
789783 auto child = children[i];
@@ -801,6 +795,11 @@ void Inhabitator::markExternRefsNullable() {
801795 // TODO: Remove this once the fuzzer imports externref globals or gets some
802796 // other way to instantiate externrefs.
803797 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+ }
804803 auto children = type.getTypeChildren ();
805804 for (size_t i = 0 ; i < children.size (); ++i) {
806805 auto child = children[i];
@@ -863,6 +862,14 @@ void Inhabitator::breakNonNullableCycles() {
863862 ++idx;
864863 continue ;
865864 }
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+ }
866873 // If this ref forms a cycle, break the cycle by marking it nullable and
867874 // continue.
868875 if (auto it = visiting.find (heapType); it != visiting.end ()) {
0 commit comments