diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml index 843452e14..452e375d6 100644 --- a/interpreter/binary/decode.ml +++ b/interpreter/binary/decode.ml @@ -161,8 +161,7 @@ let heap_type s = | Some i when i land 0xc0 = 0x40 -> (match vs7 s with | -0x10 -> FuncHeapType - | -0x11 -> ExternHeapType - | -0x12 -> AnyHeapType + | -0x11 -> AnyHeapType | -0x13 -> EqHeapType | -0x16 -> I31HeapType | -0x17 -> let n = vu32 s in RttHeapType (var_type s, Some n) @@ -180,8 +179,7 @@ let ref_type s = let pos = pos s in match vs7 s with | -0x10 -> (Nullable, FuncHeapType) - | -0x11 -> (Nullable, ExternHeapType) - | -0x12 -> (Nullable, AnyHeapType) + | -0x11 -> (Nullable, AnyHeapType) | -0x13 -> (Nullable, EqHeapType) | -0x14 -> (Nullable, heap_type s) | -0x15 -> (NonNullable, heap_type s) diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index afc6d4f96..7baebdd7a 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -106,21 +106,24 @@ struct | F64Type -> vs7 (-0x04) let heap_type = function - | AnyHeapType -> vs7 (-0x12) + | AnyHeapType -> vs7 (-0x11) | EqHeapType -> vs7 (-0x13) | I31HeapType -> vs7 (-0x16) | DataHeapType -> vs7 (-0x19) | ArrayHeapType -> vs7 (-0x1a) | FuncHeapType -> vs7 (-0x10) - | ExternHeapType -> vs7 (-0x11) | DefHeapType x -> var_type vs33 x | RttHeapType (x, None) -> vs7 (-0x18); var_type vu32 x | RttHeapType (x, Some n) -> vs7 (-0x17); vs32 n; var_type vu32 x | BotHeapType -> assert false let ref_type = function + | (Nullable, AnyHeapType) -> vs7 (-0x11) + | (Nullable, EqHeapType) -> vs7 (-0x13) + | (NonNullable, I31HeapType) -> vs7 (-0x16) + | (NonNullable, DataHeapType) -> vs7 (-0x19) + | (NonNullable, ArrayHeapType) -> vs7 (-0x1a) | (Nullable, FuncHeapType) -> vs7 (-0x10) - | (Nullable, ExternHeapType) -> vs7 (-0x11) | (Nullable, t) -> vs7 (-0x14); heap_type t | (NonNullable, t) -> vs7 (-0x15); heap_type t diff --git a/interpreter/script/js.ml b/interpreter/script/js.ml index 0d356f74a..8239e6ddf 100644 --- a/interpreter/script/js.ml +++ b/interpreter/script/js.ml @@ -246,10 +246,9 @@ let lookup (mods : modules) x_opt name at = let subject_idx = 0l let externref_idx = 1l -let is_externref_idx = 2l -let is_eqref_idx = 3l -let eq_ref_idx = 4l -let subject_type_idx = 5l +let is_eqref_idx = 2l +let eq_ref_idx = 3l +let subject_type_idx = 4l let eq_of = function | I32Type -> I32 I32Op.Eq @@ -345,7 +344,6 @@ let assert_return ress ts at = | DataHeapType -> RefTest DataOp | ArrayHeapType -> RefTest ArrayOp | FuncHeapType -> RefTest FuncOp - | ExternHeapType -> Call (is_externref_idx @@ at) | DefHeapType _ -> Const (I32 1l @@ at) (* TODO *) | RttHeapType _ -> Const (I32 1l @@ at) (* TODO *) | BotHeapType -> assert false @@ -365,7 +363,6 @@ let assert_return ress ts at = let i32_type = NumType I32Type let anyref_type = RefType (Nullable, AnyHeapType) let eqref_type = RefType (Nullable, EqHeapType) -let externref_type = RefType (Nullable, ExternHeapType) let func_def_type ins out at = FuncDefType (FuncType (ins, out)) @@ at let wrap item_name wrap_action wrap_assertion at = @@ -373,7 +370,7 @@ let wrap item_name wrap_action wrap_assertion at = let locals, assertion = wrap_assertion at in let types = func_def_type [] [] at :: - func_def_type [i32_type] [externref_type] at :: + func_def_type [i32_type] [anyref_type] at :: func_def_type [anyref_type] [i32_type] at :: func_def_type [eqref_type; eqref_type] [i32_type] at :: itypes @@ -382,8 +379,6 @@ let wrap item_name wrap_action wrap_assertion at = [ {module_name = Utf8.decode "module"; item_name; idesc} @@ at; {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "externref"; idesc = FuncImport (1l @@ at) @@ at} @@ at; - {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "is_externref"; - idesc = FuncImport (2l @@ at) @@ at} @@ at; {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "is_eqref"; idesc = FuncImport (2l @@ at) @@ at} @@ at; {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "eq_ref"; diff --git a/interpreter/script/run.ml b/interpreter/script/run.ml index d66ceb5b8..ce0ddc6fe 100644 --- a/interpreter/script/run.ml +++ b/interpreter/script/run.ml @@ -231,7 +231,7 @@ let type_of_result r = | LitResult v -> Value.type_of_value v.it | NanResult n -> Types.NumType (Value.type_of_num n.it) | RefResult t -> Types.(RefType (NonNullable, t)) - | NullResult -> Types.(RefType (Nullable, ExternHeapType)) + | NullResult -> Types.(RefType (Nullable, AnyHeapType)) let string_of_result r = match r with @@ -357,8 +357,7 @@ let assert_result at got expect = | Types.I31HeapType, Ref (I31.I31Ref _) | Types.DataHeapType, Ref (Data.DataRef _) | Types.ArrayHeapType, Ref (Data.DataRef (Data.Array _)) - | Types.FuncHeapType, Ref (Instance.FuncRef _) - | Types.ExternHeapType, Ref (ExternRef _) -> false + | Types.FuncHeapType, Ref (Instance.FuncRef _) -> false | _ -> true ) | NullResult -> diff --git a/interpreter/script/script.ml b/interpreter/script/script.ml index 82c73be91..3a26476b6 100644 --- a/interpreter/script/script.ml +++ b/interpreter/script/script.ml @@ -57,7 +57,7 @@ exception Syntax of Source.region * string let () = let type_of_ref' = !Value.type_of_ref' in Value.type_of_ref' := function - | ExternRef _ -> Types.ExternHeapType + | ExternRef _ -> Types.AnyHeapType | r -> type_of_ref' r let () = diff --git a/interpreter/syntax/free.ml b/interpreter/syntax/free.ml index 12c8c59ff..cfdbc8076 100644 --- a/interpreter/syntax/free.ml +++ b/interpreter/syntax/free.ml @@ -70,7 +70,7 @@ let num_type = function let heap_type = function | AnyHeapType | EqHeapType | I31HeapType | DataHeapType | ArrayHeapType - | FuncHeapType | ExternHeapType | BotHeapType -> empty + | FuncHeapType | BotHeapType -> empty | DefHeapType x | RttHeapType (x, _) -> var_type x let ref_type = function diff --git a/interpreter/syntax/types.ml b/interpreter/syntax/types.ml index 81f6669d1..6464bcee0 100644 --- a/interpreter/syntax/types.ml +++ b/interpreter/syntax/types.ml @@ -21,7 +21,6 @@ and heap_type = | DataHeapType | ArrayHeapType | FuncHeapType - | ExternHeapType | DefHeapType of var | RttHeapType of var * int32 option | BotHeapType @@ -167,7 +166,6 @@ let sem_heap_type c = function | DataHeapType -> DataHeapType | ArrayHeapType -> ArrayHeapType | FuncHeapType -> FuncHeapType - | ExternHeapType -> ExternHeapType | DefHeapType x -> DefHeapType (sem_var_type c x) | RttHeapType (x, no) -> RttHeapType (sem_var_type c x, no) | BotHeapType -> BotHeapType @@ -288,7 +286,6 @@ and string_of_heap_type = function | DataHeapType -> "data" | ArrayHeapType -> "array" | FuncHeapType -> "func" - | ExternHeapType -> "extern" | DefHeapType x -> string_of_var x | RttHeapType (x, None) -> "(rtt " ^ string_of_var x ^ ")" | RttHeapType (x, Some n) -> diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly index c153d68f9..745f94fba 100644 --- a/interpreter/text/parser.mly +++ b/interpreter/text/parser.mly @@ -302,7 +302,7 @@ heap_type : | DATA { fun c -> DataHeapType } | ARRAY { fun c -> ArrayHeapType } | FUNC { fun c -> FuncHeapType } - | EXTERN { fun c -> ExternHeapType } + | EXTERN { fun c -> AnyHeapType } | var { fun c -> DefHeapType (SynVar ($1 c type_).it) } | LPAR RTT var RPAR /* Sugar */ { fun c -> RttHeapType (SynVar ($3 c type_).it, None) } @@ -318,7 +318,7 @@ ref_type : | DATAREF { fun c -> (NonNullable, DataHeapType) } /* Sugar */ | ARRAYREF { fun c -> (NonNullable, ArrayHeapType) } /* Sugar */ | FUNCREF { fun c -> (Nullable, FuncHeapType) } /* Sugar */ - | EXTERNREF { fun c -> (Nullable, ExternHeapType) } /* Sugar */ + | EXTERNREF { fun c -> (Nullable, AnyHeapType) } /* Sugar */ | LPAR RTT var RPAR /* Sugar */ { fun c -> (NonNullable, RttHeapType (SynVar ($3 c type_).it, None)) } | LPAR RTT NAT var RPAR /* Sugar */ @@ -1284,7 +1284,6 @@ result : | LPAR REF_DATA RPAR { RefResult DataHeapType @@ at () } | LPAR REF_ARRAY RPAR { RefResult ArrayHeapType @@ at () } | LPAR REF_FUNC RPAR { RefResult FuncHeapType @@ at () } - | LPAR REF_EXTERN RPAR { RefResult ExternHeapType @@ at () } | LPAR REF_NULL RPAR { NullResult @@ at () } result_list : diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index 4919e35a3..db6187751 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -91,7 +91,7 @@ let check_num_type (c : context) (t : num_type) at = let check_heap_type (c : context) (t : heap_type) at = match t with | AnyHeapType | EqHeapType | I31HeapType | DataHeapType | ArrayHeapType - | FuncHeapType | ExternHeapType -> () + | FuncHeapType -> () | DefHeapType (SynVar x) -> ignore (type_ c (x @@ at)) | RttHeapType (SynVar x, _) -> ignore (type_ c (x @@ at)) | DefHeapType (SemVar _) | RttHeapType (SemVar _, _) | BotHeapType -> diff --git a/proposals/gc/MVP.md b/proposals/gc/MVP.md index eb1517879..840bff1d4 100644 --- a/proposals/gc/MVP.md +++ b/proposals/gc/MVP.md @@ -31,10 +31,6 @@ All three proposals are prerequisites. [Heap types](https://github.com/WebAssembly/function-references/blob/master/proposals/function-references/Overview.md#types) classify reference types and are extended: -* `any` is a new heap type - - `heaptype ::= ... | any` - - the common supertype of all referenceable types - * `eq` is a new heap type - `heaptype ::= ... | eq` - the common supertype of all referenceable types on which comparison (`ref.eq`) is allowed @@ -56,6 +52,10 @@ All three proposals are prerequisites. - `rtt n? t ok` iff `t ok` - the constant `n`, if present, encodes the static knowledge that this type has `n` dynamic supertypes (see [Runtime types](#runtime-types)) +* `extern` is renamed back to `any` + - the common supertype of all referenceable types + - the name `extern` is kept as an alias in the text format for backwards compatibility + * Note: heap types `func` and `extern` already exist via [reference types proposal](https://github.com/WebAssembly/reference-types), and `(ref null? $t)` via [typed references](https://github.com/WebAssembly/function-references) We distinguish these *abstract* heap types from *concrete* heap types `(type $t)`. @@ -67,9 +67,6 @@ Moreover, they form a small [subtype hierarchy](#subtyping). New abbreviations are introduced for reference types in binary and text format, corresponding to `funcref` and `externref`: -* `anyref` is a new reference type - - `anyref == (ref null any)` - * `eqref` is a new reference type - `eqref == (ref null eq)` @@ -85,6 +82,10 @@ New abbreviations are introduced for reference types in binary and text format, * `rtt ? ` is a new reference type - `(rtt ? $t) == (ref (rtt ? $t))` +* `externref` is renamed to `anyref` + - `anyref == (ref null any)` + - the name `externref` is kept as an alias in the text format for backwards compatibility + #### Type Definitions @@ -166,14 +167,10 @@ i31 data All *concrete* heap types (of the form `(type $t)`) are situated below either `data` or `func`. RTTs are below `eq`. -In addition, the abstract heap type `extern` is also a subtype of `any`. -Its interpretation is defined by the host environment. -It may contain additional host-defined types that are neither of the above three leaf type categories. -It may also overlap with some or all of these categories, as would be observable by applying a classification instruction like `ref.is_func` to a value of type `externref`. -The possible outcomes of such an operation hence depend on the host environment. -(For example, in a JavaScript embedding, `externref` could be inhabited by all JS values -- which is a natural choice, because JavaScript is untyped; but some of its values are JS-side representations of Wasm values per the JS API, and those can also be observed as `data` or `func` references. Another possible interpretation could be that `data` is disjoint from `extern`, which would be determined by the coercions allowed by the JS API at the JS/Wasm boundary. While such an interpretation is probably not attractive for JavaScript, it would be natural in other embeddings such as the C/C++ API, where different references are represented with different host types.) +In addition, a host environment may introduce additional inhabitants of type `any` that are are in neither of the above three leaf type categories. +The interpretation of such values is defined by the host environment. -Note: In the future, this hierarchy could be refined to distinguish compound data types that are not subtypes of `eq`. +Note: In the future, this hierarchy could be refined, e.g., to distinguish compound data types that are not subtypes of `eq`. ##### Defined Types @@ -397,8 +394,6 @@ Tentatively, support a type of guaranteed unboxed scalars. Note: The [reference types](https://github.com/WebAssembly/reference-types) and [typed function references](https://github.com/WebAssembly/function-references)already introduce similar `ref.is_null`, `br_on_null`, and `br_on_non_null` instructions. -Note: There are no instructions to check for `externref`, since that can consist of a diverse set of different object representations that would be costly to check for exhaustively. - Note: The `br_on_*` instructions allow an operand of unrelated reference type, even though this cannot possibly succeed. That's because subtyping allows to forget that information, so by the subtype substitutibility property, it would be accepted in any case. The given typing rules merely allow this type to also propagate to the result, which avoids the need to compute a least upper bound between the operand type and the target type in the typing algorithm. @@ -480,8 +475,7 @@ This extends the [encodings](https://github.com/WebAssembly/function-references/ | Opcode | Type | Parameters | Note | | ------ | --------------- | ---------- | ---- | | -0x10 | `funcref` | | shorthand, from reftype proposal | -| -0x11 | `externref` | | shorthand, from reftype proposal | -| -0x12 | `anyref` | | shorthand | +| -0x11 | `anyref` | | shorthand, from reftype proposal | | -0x13 | `eqref` | | shorthand | | -0x14 | `(ref null ht)` | `ht : heaptype (s33)` | from funcref proposal | | -0x15 | `(ref ht)` | `ht : heaptype (s33)` | from funcref proposal | @@ -499,8 +493,7 @@ The opcode for heap types is encoded as an `s33`. | ------ | --------------- | ---------- | ---- | | i >= 0 | `(type i)` | | from funcref proposal | | -0x10 | `func` | | from funcref proposal | -| -0x11 | `extern` | | from funcref proposal | -| -0x12 | `any` | | | +| -0x11 | `any` | | from funcref proposal | | -0x13 | `eq` | | | | -0x16 | `i31` | | | | -0x17 | `(rtt n i)` | `n : u32`, `i : typeidx` | | diff --git a/test/core/linking.wast b/test/core/linking.wast index 85de43d8f..6a8ba1d0c 100644 --- a/test/core/linking.wast +++ b/test/core/linking.wast @@ -177,23 +177,6 @@ "incompatible import type" ) -(assert_unlinkable - (module (global (import "Mref_ex" "g-const-funcnull") externref)) - "incompatible import type" -) -(assert_unlinkable - (module (global (import "Mref_ex" "g-const-func") externref)) - "incompatible import type" -) -(assert_unlinkable - (module (global (import "Mref_ex" "g-const-refnull") externref)) - "incompatible import type" -) -(assert_unlinkable - (module (global (import "Mref_ex" "g-const-ref") externref)) - "incompatible import type" -) - (assert_unlinkable (module (global (import "Mref_ex" "g-var-func") (mut (ref null func))))