Skip to content

[Wasm GC] Do not consider reference type equality in fuzzer due to roundtripping creating new recursive types - #3679

Closed
kripken wants to merge 4 commits into
mainfrom
fuzzref2
Closed

kripken wants to merge 4 commits into
mainfrom
fuzzref2

Conversation

@kripken

@kripken kripken commented Mar 12, 2021

Copy link
Copy Markdown
Member

The testcase here passes with --fuzz-exec but fails when adding --roundtrip,
as then the type appears different. Is that expected @tlively ?

@tlively

tlively commented Mar 12, 2021

Copy link
Copy Markdown
Member

If I understand the issue correctly, then yes, it is expected. --roundtrip will freshly parse the types, so any self-referential types will be rebuilt into new copies of themselves. Until we get equirecursive type canonicalization working, the new self-referential types will not have the same identity as the old types.

@kripken

kripken commented Mar 12, 2021

Copy link
Copy Markdown
Member Author

Oh right, I forgot that part.. yes, then because of recursive types I think we do need this, marking as non-draft.

@kripken
kripken marked this pull request as ready for review March 12, 2021 02:09
@kripken kripken changed the title Roundtripping creates new types? [Wasm GC] Do not consider reference type equality in fuzzer due to roundtripping creates new recursive types Mar 12, 2021
@kripken kripken changed the title [Wasm GC] Do not consider reference type equality in fuzzer due to roundtripping creates new recursive types [Wasm GC] Do not consider reference type equality in fuzzer due to roundtripping creating new recursive types Mar 12, 2021
Comment thread src/tools/execution-results.h Outdated
// will end up with a type that does not compare equally.
return true;
}
if (a.type != b.type) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alternative would be to not special-case ref types, but to change the condition to a.type != b.type && (a.type < b.type || b.type < a.type), which will detect structurally equivalent types correctly.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But would that work with recursive types, for which we create a new one when roundtripping which is the issue here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. operator< compares structure, not identity. (The bug it has where it can compare two types as mutually less than each other should not affect this use case.)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, the problem is just of comparing equality via identity... changed as you suggested.

@kripken

kripken commented Mar 12, 2021

Copy link
Copy Markdown
Member Author

Ah, as CI shows that does not work actually. The two types are not identical to each other after roundtripping. So the problem is still there.

Is it not as I thought earlier, that roundtripping creating new versions of recursive types is a problem for subtype checks between them later? If that's not it I guess I'll need to debug the comparison code unless you have an idea.

@tlively

tlively commented Mar 12, 2021

Copy link
Copy Markdown
Member

The new types should be structurally identical to the old types and therefore the new and old types should be subtypes of each other (and Type::isSubType should reflect that). If they are not structurally identical after round tripping, that sounds like a bug.

@kripken

kripken commented Mar 12, 2021

Copy link
Copy Markdown
Member Author

What happens appears to be this:

  • The SubTyper compares the Types, which then
  • Compares the HeapTypes, which then
  • Compares the Signatures.

All that makes sense. Then Signature checking for subTyping does this:

  // TODO: Implement proper signature subtyping, covariant in results and
  // contravariant in params, once V8 implements it.
  // return isSubType(b.params, a.params) && isSubType(a.results, b.results);
  return a == b;

Do you remember why we commented that out? Looks like you added it in #3610

@kripken

kripken commented Mar 12, 2021

Copy link
Copy Markdown
Member Author

(Even if v8 doesn't have it yet, I think we should maybe uncomment it - hard for me to see the danger the commenting implies.)

@tlively

tlively commented Mar 12, 2021

Copy link
Copy Markdown
Member

Aha, that will do it! Using operator< instead of subtyping here should avoid that problem. Until V8 implements signature subtyping, if we emit binaries that depend on it, they will fail to validate on V8.

@tlively

tlively commented Mar 12, 2021

Copy link
Copy Markdown
Member

Actually, I think the subtyper could be changed to use !(a < b || b < a), since it's not supposed to depend on identity at all until we implement proper canonicalization.

@kripken

kripken commented Mar 12, 2021

Copy link
Copy Markdown
Member Author

Why would < be correct, though? Isn't it just an arbitrary order we use internally? (It's documented as Order types by some notion of simplicity)

It seems simpler to just not compare reference types at all here as in the first version of this PR? Or, what is the benefit of using <?

@tlively

tlively commented Mar 13, 2021

Copy link
Copy Markdown
Member

Yes, it's an arbitrary order, but it is a total order on structural types, so it can be used to detect structural equality. This will be moot once I update == to use structural equality (which I plan to do by the end of Monday).

@kripken kripken closed this Apr 5, 2021
@kripken
kripken deleted the fuzzref2 branch April 5, 2021 21:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants