Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/ir/subtype-exprs.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
// sources, call_indirect target types may be supertypes of their source
// table types. In this case, the cast will always succeed, but only if we
// keep the types related.
// TODO: No value flows here, so we could use |noteNonFlowSubtype|, but
// this is a trivial situation that is not worth optimizing.
self()->noteSubtype(tableType, curr->heapType);
} else if (HeapType::isSubType(curr->heapType, tableType)) {
self()->noteCast(tableType, curr->heapType);
Expand Down Expand Up @@ -256,6 +258,8 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
void visitTupleExtract(TupleExtract* curr) {}
void visitRefI31(RefI31* curr) {}
void visitI31Get(I31Get* curr) {
// This could be |noteNonFlowSubtype| but as there are no subtypes of i31
// it does not matter.
self()->noteSubtype(curr->i31, Type(HeapType::i31, Nullable));
}
void visitCallRef(CallRef* curr) {
Expand All @@ -271,6 +275,9 @@ struct SubtypingDiscoverer : public OverriddenVisitor<SubType> {
// generalize, should they generalize the target more or the parameters
// more? etc.), so we do the simple thing here for now of requiring the
// target type not generalize.
//
// Note that this could be |noteNonFlowSubtype| but since we are comparing
// a type to itself here, that does not matter.
self()->noteSubtype(curr->target, curr->target->type);

if (curr->target->type.isSignature()) {
Expand Down
11 changes: 11 additions & 0 deletions src/passes/Unsubtyping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,17 @@ struct Unsubtyping
// basic type then we can simply ignore this: we only remove subtyping
// between user types, so subtyping wrt basic types is unchanged, and so
// this constraint will never be a problem.
//
// This is sort of a hack because in general to be precise we should not
// just consider basic types here - in general, we should note for each
// constraint whether it is a flow-based one or not, and only take the
// flow-based ones into account when looking at the impact of casts.
// However, in practice this is enough as the only non-trivial case of
// |noteNonFlowSubtype| is for RefEq, which uses a basic type (eqref). Other
// cases of non-flow subtyping end up trivial, e.g., the target of a
// CallRef is compared to itself (and we ignore constraints of A :> A).
// However, if we change how |noteNonFlowSubtype| is used in
// SubtypingDiscoverer then we may need to generalize this.
if (super.isRef() && super.getHeapType().isBasic()) {
return;
}
Expand Down