Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GC: wasmparser: Subtypes #1059

Merged
merged 30 commits into from
Jul 7, 2023
Merged

Conversation

imikushin
Copy link
Contributor

Introducing the SubType struct:

pub struct SubType {
    pub is_final: bool,
    pub supertype_idxs: Vec<u32>,
    pub structural_type: StructuralType,
}

Here, StructuralType is an enum (previously named Type).

supertype_idxs is a vector of indexes of supertypes, limited to at most one supertype as per GC MVP.

A valid subtype matches its supertypes. Supertypes cannot be final.

Introducing the `SubType` struct:
```rust
pub struct SubType {
    pub is_final: bool,
    pub supertype_idxs: Vec<u32>,
    pub structural_type: StructuralType,
}
```

Here, `StructuralType` is an enum (previously named `Type`).

`supertype_idxs` is a vector of indexes of supertypes, limited to
at most one supertype as per GC MVP.

A valid subtype matches its supertypes. Supertypes cannot be final.
@imikushin
Copy link
Contributor Author

x86_64-linux and x86_64-windows CI jobs were canceled for some reason.

Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

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

Thanks!

This is looking good, but I have a few nitpicks and also a request for more complete testing.

Once those things are addressed we can merge this.

crates/wasm-encoder/src/core/types.rs Outdated Show resolved Hide resolved
crates/wasmparser/src/readers/core/types.rs Outdated Show resolved Hide resolved
crates/wasmparser/src/readers/core/types.rs Outdated Show resolved Hide resolved
crates/wasmparser/src/validator/component.rs Outdated Show resolved Hide resolved
crates/wasmparser/src/validator/core.rs Outdated Show resolved Hide resolved
crates/wasmparser/src/validator/types.rs Outdated Show resolved Hide resolved
tests/local/gc/gc-subtypes.wat Outdated Show resolved Hide resolved
imikushin and others added 2 commits June 14, 2023 14:03
Co-authored-by: Nick Fitzgerald <fitzgen@gmail.com>
Co-authored-by: Nick Fitzgerald <fitzgen@gmail.com>
imikushin added 11 commits June 20, 2023 17:20
Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

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

LGTM with a couple minor nitpicks. I'll be on vacation for a week starting tomorrow, so maybe @alexcrichton can merge this once you've addressed the nitpicks.

Thanks!

crates/wasm-encoder/src/core/types.rs Outdated Show resolved Hide resolved
crates/wasm-encoder/src/core/types.rs Outdated Show resolved Hide resolved
crates/wit-component/src/gc.rs Outdated Show resolved Hide resolved
tests/local/gc/gc-subtypes.wat Outdated Show resolved Hide resolved
@imikushin
Copy link
Contributor Author

@alexcrichton I believe I've addressed all @fitzgen's feedback (thank you!).

Currently, field namespace is global (per module). But if a field of the same name is at the same position, that should be okay.
crates/wast/src/names.rs Outdated Show resolved Hide resolved
crates/wasmparser/src/validator/core.rs Show resolved Hide resolved
pub(crate) trait Matches {
fn matches<'a, F>(&self, other: &Self, type_at: &F) -> Result<bool>
where
F: Fn(u32) -> Result<&'a SubType>;
Copy link
Member

Choose a reason for hiding this comment

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

One thing I might recommend is to remove the Result here since indices at this point should always be valid because the definitions of types are validated to all be correct. Additionally it might be better to pass a concrete type here rather than a generic Fn(u32) -> &SubType but instead have something like cx: &Validator or similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

One thing I might recommend is to remove the Result here since indices at this point should always be valid because the definitions of types are validated to all be correct.

Actually, the primary use case for matches() is to validate if the type definitions are correct.

Copy link
Member

Choose a reason for hiding this comment

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

I don't think that's the case? Whenever a type definition is reached as part of validation there are no type-matching queries performed at that time and instead the structure of the defined type is validated. This means that the indices are all valid for the type section after it's read, so in the future when the matching predicate comes into play during the code section for example there are no invalid indices.

I believe this is Module::add_type which is where indices are validated and afterwards indices don't need validation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe this is Module::add_type which is where indices are validated and afterwards indices don't need validation.

Yeah, that's exactly where matches() gets called:

<wasmparser::readers::core::types::SubType as wasmparser::readers::core::types::Matches>::matches types.rs:763
wasmparser::validator::core::Module::check_subtype core.rs:525
wasmparser::validator::core::Module::add_type core.rs:507

Copy link
Member

Choose a reason for hiding this comment

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

Ah ok I see that now, but I still think that this Result isn't necessary. For example if check_structural_type is moved above the subtype check, then everything is guaranteed to be valid while performing a subtype check?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! Updated.

crates/wasmparser/src/readers/core/types.rs Outdated Show resolved Hide resolved
StructuralType::Func(_) => Ok(true),
_ => Ok(false),
},
(a, b) => Ok(a == b),
Copy link
Member

Choose a reason for hiding this comment

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

I've mentioned this before, but personally I'm not a fan of catch-all clauses like this. This is very easy to forget to update if a new variant is added because of #[derive(PartialEq)] which can lead to further bugs in behavior. Where possible I'd recommend exhaustively matching remaining cases, for example something like:

(a @ (HeapType::T1 | HeapType::T2), b) => Ok(a == b),

which explicitly documents the list of "catch-all" types being caught here and it's obvious there's no payload so equality can only be identity-based. That way if new types are added in the future this'll generate a compiler error with a non-exhaustive check.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

because of #[derive(PartialEq)]

Not sure I understand what bad things can happen because of it. Everything else seems clear.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, updated the code according to your comment.

crates/wasmparser/src/readers/core/types.rs Outdated Show resolved Hide resolved
crates/wasmparser/src/readers/core/types.rs Outdated Show resolved Hide resolved
crates/wasmparser/src/readers/core/types.rs Outdated Show resolved Hide resolved
crates/wasmparser/src/readers/core/types.rs Outdated Show resolved Hide resolved
@@ -93,7 +93,7 @@ impl<'a> ModuleInfo<'a> {

// Save function types
for ty in reader {
let typeinfo = TypeInfo::try_from(ty?).unwrap();
let typeinfo = TypeInfo::try_from(ty?.structural_type).unwrap();
Copy link
Member

Choose a reason for hiding this comment

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

I think it would be best to update wasm-mutate a bit differently in this commit. Currently wasm-mutate doesn't have support for GC, and that's ok, but if given a binary with gc with these changes it runs a risk of "accepting" the binary and making it invalid. For example this is ignoring all fields other than structural_type.

I think it would be better to keep wasm-mutate as-is where it explicitly rejects gc-using binaries. For wasm-mutate that would look like handling the full SubType structure but returning errors if any fields are set that look like gc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@imikushin
Copy link
Contributor Author

@alexcrichton I believe I've addressed all your comments (so far).

Use `a == b` vs `*a == *b`: dereference is unnecessary since `PartialEq::eq(&self, other: &Rhs) -> bool` accepts references.
@alexcrichton alexcrichton merged commit e633e6f into bytecodealliance:main Jul 7, 2023
@alexcrichton
Copy link
Member

Thanks!

alexcrichton added a commit to alexcrichton/wasm-tools that referenced this pull request Jul 9, 2023
This fixes an accidental regression from bytecodealliance#1059 where an invalid wasm
file was causing a panic in wasmprinter, and wasmprinter shouldn't be
panicking on invalid wasm files.
alexcrichton added a commit that referenced this pull request Jul 10, 2023
This fixes an accidental regression from #1059 where an invalid wasm
file was causing a panic in wasmprinter, and wasmprinter shouldn't be
panicking on invalid wasm files.
alexcrichton added a commit to alexcrichton/wasm-tools that referenced this pull request Jul 11, 2023
Releases recent changes such as:

* More support for the gc proposal. bytecodealliance#1045 bytecodealliance#1059
* Support for resources throughout most tooling. bytecodealliance#1053 bytecodealliance#1068 bytecodealliance#1070 bytecodealliance#1082
  bytecodealliance#1079 bytecodealliance#1083 bytecodealliance#1084 bytecodealliance#1105 bytecodealliance#1113 bytecodealliance#1116
* Support for `include` in WIT files. bytecodealliance#1054 bytecodealliance#1085 bytecodealliance#1088
* WIT worlds may now be rejected if the same interface can be "reached"
  as both an import and an export simultaneously. bytecodealliance#1081 bytecodealliance#1107
* Support for registry metadata in `wasm-tools metadata`. bytecodealliance#1060
* A new subcommand `wasm-tools component targets`. bytecodealliance#1089
* An `--out-dir` argument is supported on `wasm-tools component wit` to
  print the entire `Resolve` instead of just one package. bytecodealliance#1108
* Miscellaneous bug fixes and improvements. bytecodealliance#1061 bytecodealliance#1065 bytecodealliance#1074 bytecodealliance#1073 bytecodealliance#1078 bytecodealliance#1077
  bytecodealliance#1072 bytecodealliance#1086 bytecodealliance#1091 bytecodealliance#1094 bytecodealliance#1114 bytecodealliance#1106
alexcrichton added a commit to alexcrichton/wasm-tools that referenced this pull request Jul 11, 2023
Releases recent changes such as:

* More support for the gc proposal.
  [bytecodealliance#1045](bytecodealliance#1045)
  [bytecodealliance#1059](bytecodealliance#1059)
* Support for resources throughout most tooling.
  [bytecodealliance#1053](bytecodealliance#1053)
  [bytecodealliance#1068](bytecodealliance#1068)
  [bytecodealliance#1070](bytecodealliance#1070)
  [bytecodealliance#1082](bytecodealliance#1082)
  [bytecodealliance#1079](bytecodealliance#1079)
  [bytecodealliance#1083](bytecodealliance#1083)
  [bytecodealliance#1084](bytecodealliance#1084)
  [bytecodealliance#1105](bytecodealliance#1105)
  [bytecodealliance#1113](bytecodealliance#1113)
  [bytecodealliance#1116](bytecodealliance#1116)
* Support for `include` in WIT files.
  [bytecodealliance#1054](bytecodealliance#1054)
  [bytecodealliance#1085](bytecodealliance#1085)
  [bytecodealliance#1088](bytecodealliance#1088)
* WIT worlds may now be rejected if the same interface can be "reached"
  as both an import and an export simultaneously.
  [bytecodealliance#1081](bytecodealliance#1081)
  [bytecodealliance#1107](bytecodealliance#1107)
* Support for registry metadata in `wasm-tools metadata`.
  [bytecodealliance#1060](bytecodealliance#1060)
* A new subcommand `wasm-tools component targets`.
  [bytecodealliance#1089](bytecodealliance#1089)
* An `--out-dir` argument is supported on `wasm-tools component wit` to
  print the entire `Resolve` instead of just one package.
  [bytecodealliance#1108](bytecodealliance#1108)
* Miscellaneous bug fixes and improvements.
  [bytecodealliance#1061](bytecodealliance#1061)
  [bytecodealliance#1065](bytecodealliance#1065)
  [bytecodealliance#1074](bytecodealliance#1074)
  [bytecodealliance#1073](bytecodealliance#1073)
  [bytecodealliance#1078](bytecodealliance#1078)
  [bytecodealliance#1077](bytecodealliance#1077)
  [bytecodealliance#1072](bytecodealliance#1072)
  [bytecodealliance#1086](bytecodealliance#1086)
  [bytecodealliance#1091](bytecodealliance#1091)
  [bytecodealliance#1094](bytecodealliance#1094)
  [bytecodealliance#1114](bytecodealliance#1114)
  [bytecodealliance#1106](bytecodealliance#1106)
alexcrichton added a commit that referenced this pull request Jul 11, 2023
Releases recent changes such as:

* More support for the gc proposal.
  [#1045](#1045)
  [#1059](#1059)
* Support for resources throughout most tooling.
  [#1053](#1053)
  [#1068](#1068)
  [#1070](#1070)
  [#1082](#1082)
  [#1079](#1079)
  [#1083](#1083)
  [#1084](#1084)
  [#1105](#1105)
  [#1113](#1113)
  [#1116](#1116)
* Support for `include` in WIT files.
  [#1054](#1054)
  [#1085](#1085)
  [#1088](#1088)
* WIT worlds may now be rejected if the same interface can be "reached"
  as both an import and an export simultaneously.
  [#1081](#1081)
  [#1107](#1107)
* Support for registry metadata in `wasm-tools metadata`.
  [#1060](#1060)
* A new subcommand `wasm-tools component targets`.
  [#1089](#1089)
* An `--out-dir` argument is supported on `wasm-tools component wit` to
  print the entire `Resolve` instead of just one package.
  [#1108](#1108)
* Miscellaneous bug fixes and improvements.
  [#1061](#1061)
  [#1065](#1065)
  [#1074](#1074)
  [#1073](#1073)
  [#1078](#1078)
  [#1077](#1077)
  [#1072](#1072)
  [#1086](#1086)
  [#1091](#1091)
  [#1094](#1094)
  [#1114](#1114)
  [#1106](#1106)
@imikushin imikushin deleted the subtypes branch July 12, 2023 01:07
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.

3 participants