From 5e231e9cce62fc27f576a0d75bb079a9a2a826ae Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Tue, 18 Feb 2020 13:34:03 +0100 Subject: [PATCH 1/6] Remove nullref --- document/core/appendix/algorithm.rst | 7 +-- document/core/appendix/index-instructions.rst | 2 +- document/core/appendix/index-types.rst | 3 +- document/core/binary/instructions.rst | 2 +- document/core/binary/types.rst | 3 +- document/core/exec/instructions.rst | 14 ++--- document/core/exec/modules.rst | 18 +++--- document/core/exec/runtime.rst | 4 +- document/core/syntax/instructions.rst | 2 +- document/core/syntax/types.rst | 8 +-- document/core/text/instructions.rst | 2 +- document/core/text/types.rst | 7 ++- document/core/util/macros.def | 2 +- document/core/valid/instructions.rst | 8 +-- document/core/valid/types.rst | 7 --- document/js-api/index.bs | 8 --- interpreter/README.md | 11 ++-- interpreter/binary/decode.ml | 3 +- interpreter/binary/encode.ml | 3 +- interpreter/exec/eval.ml | 15 +++-- interpreter/host/spectest.ml | 5 +- interpreter/script/js.ml | 6 +- interpreter/script/run.ml | 3 +- interpreter/syntax/ast.ml | 2 +- interpreter/syntax/free.ml | 2 +- interpreter/syntax/operators.ml | 2 +- interpreter/syntax/types.ml | 4 +- interpreter/syntax/values.ml | 8 +-- interpreter/text/arrange.ml | 8 ++- interpreter/text/lexer.mll | 2 +- interpreter/text/parser.mly | 11 ++-- interpreter/valid/valid.ml | 6 +- proposals/reference-types/Overview.md | 13 ++-- test/core/binary.wast | 4 +- test/core/br_table.wast | 22 +------ test/core/bulk.wast | 2 +- test/core/elem.wast | 22 +++---- test/core/global.wast | 6 +- test/core/linking.wast | 60 ++----------------- test/core/ref_is_null.wast | 37 ++++-------- test/core/ref_null.wast | 15 ++--- test/core/select.wast | 22 +------ test/core/table_fill.wast | 42 ++++++------- test/core/table_get.wast | 4 +- test/core/table_grow.wast | 22 +++---- test/core/table_set.wast | 26 ++++---- test/core/table_size.wast | 8 +-- 47 files changed, 192 insertions(+), 301 deletions(-) diff --git a/document/core/appendix/algorithm.rst b/document/core/appendix/algorithm.rst index 19ec29a0..9f39b995 100644 --- a/document/core/appendix/algorithm.rst +++ b/document/core/appendix/algorithm.rst @@ -26,17 +26,16 @@ A simple subtyping check can be defined on these types. .. code-block:: pseudo - type val_type = I32 | I64 | F32 | F64 | Anyref | Funcref | Nullref | Bot + type val_type = I32 | I64 | F32 | F64 | Anyref | Funcref | Bot func is_num(t : val_type) : bool = return t = I32 || t = I64 || t = F32 || t = F64 || t = Bot func is_ref(t : val_type) : bool = - return t = Anyref || t = Funcref || t = Nullref || t = Bot + return t = Anyref || t = Funcref || t = Bot func matches(t1 : val_type, t2 : val_type) : bool = - return t1 = t2 || t1 = Bot || - (t1 = Nullref && is_ref(t2)) || (is_ref(t1) && t2 = Anyref) + return t1 = t2 || t1 = Bot || (is_ref(t1) && t2 = Anyref) The algorithm uses two separate stacks: the *value stack* and the *control stack*. The former tracks the :ref:`types ` of operand values on the :ref:`stack `, diff --git a/document/core/appendix/index-instructions.rst b/document/core/appendix/index-instructions.rst index f54363c7..9de22e97 100644 --- a/document/core/appendix/index-instructions.rst +++ b/document/core/appendix/index-instructions.rst @@ -215,7 +215,7 @@ Instruction Binary Opcode Type (reserved) :math:`\hex{CD}` (reserved) :math:`\hex{CE}` (reserved) :math:`\hex{CF}` -:math:`\REFNULL` :math:`\hex{D0}` :math:`[] \to [\NULLREF]` :ref:`validation ` :ref:`execution ` +:math:`\REFNULL~t` :math:`\hex{D0}` :math:`[] \to [t]` :ref:`validation ` :ref:`execution ` :math:`\REFISNULL` :math:`\hex{D1}` :math:`[\ANYREF] \to [\I32]` :ref:`validation ` :ref:`execution ` :math:`\REFFUNC~x` :math:`\hex{D2}` :math:`[] \to [\FUNCREF]` :ref:`validation ` :ref:`execution ` :math:`\MEMORYINIT` :math:`\hex{FC08}` :math:`[\I32~\I32~\I32] \to []` :ref:`validation ` :ref:`execution ` diff --git a/document/core/appendix/index-types.rst b/document/core/appendix/index-types.rst index 37f33c7b..3f13e553 100644 --- a/document/core/appendix/index-types.rst +++ b/document/core/appendix/index-types.rst @@ -15,8 +15,7 @@ Category Constructor (reserved) :math:`\hex{7B}` .. :math:`\hex{71}` :ref:`Reference type ` |FUNCREF| :math:`\hex{70}` (-16 as |Bs7|) :ref:`Reference type ` |ANYREF| :math:`\hex{6F}` (-17 as |Bs7|) -:ref:`Reference type ` |NULLREF| :math:`\hex{6E}` (-18 as |Bs7|) -(reserved) :math:`\hex{6D}` .. :math:`\hex{61}` +(reserved) :math:`\hex{6E}` .. :math:`\hex{61}` :ref:`Function type ` :math:`[\valtype^\ast] \to [\valtype^\ast]` :math:`\hex{60}` (-32 as |Bs7|) (reserved) :math:`\hex{5F}` .. :math:`\hex{41}` :ref:`Result type ` :math:`[\epsilon]` :math:`\hex{40}` (-64 as |Bs7|) diff --git a/document/core/binary/instructions.rst b/document/core/binary/instructions.rst index cb34bba1..609d743c 100644 --- a/document/core/binary/instructions.rst +++ b/document/core/binary/instructions.rst @@ -76,7 +76,7 @@ Reference Instructions .. math:: \begin{array}{llclll} \production{instruction} & \Binstr &::=& \dots \\ &&|& - \hex{D0} &\Rightarrow& \REFNULL \\ &&|& + \hex{D0}~~t{:}\Breftype &\Rightarrow& \REFNULL~t \\ &&|& \hex{D1} &\Rightarrow& \REFISNULL \\ &&|& \hex{D2}~~x{:}\Bfuncidx &\Rightarrow& \REFFUNC~x \\ \end{array} diff --git a/document/core/binary/types.rst b/document/core/binary/types.rst index e7a7f8ed..4261b60d 100644 --- a/document/core/binary/types.rst +++ b/document/core/binary/types.rst @@ -42,8 +42,7 @@ Reference Types \begin{array}{llclll@{\qquad\qquad}l} \production{reference type} & \Breftype &::=& \hex{70} &\Rightarrow& \FUNCREF \\ &&|& - \hex{6F} &\Rightarrow& \ANYREF \\ &&|& - \hex{6E} &\Rightarrow& \NULLREF \\ + \hex{6F} &\Rightarrow& \ANYREF \\ \end{array} diff --git a/document/core/exec/instructions.rst b/document/core/exec/instructions.rst index ef8dd5e6..4e6930ed 100644 --- a/document/core/exec/instructions.rst +++ b/document/core/exec/instructions.rst @@ -192,10 +192,10 @@ Reference Instructions .. _exec-ref.null: -:math:`\REFNULL` -................ +:math:`\REFNULL~t` +.................. -1. Push the value :math:`\REFNULL` to the stack. +1. Push the value :math:`\REFNULL~t` to the stack. .. note:: No formal reduction rule is required for this instruction, since the |REFNULL| instruction is already a :ref:`value `. @@ -210,7 +210,7 @@ Reference Instructions 2. Pop the value :math:`\val` from the stack. -3. If :math:`\val` is |REFNULL|, then: +3. If :math:`\val` is :math:`\REFNULL~t`, then: a. Push the value :math:`\I32.\CONST~1` to the stack. @@ -221,9 +221,9 @@ Reference Instructions .. math:: \begin{array}{lcl@{\qquad}l} \val~\REFISNULL &\stepto& \I32.\CONST~1 - & (\iff \val = \REFNULL) \\ + & (\iff \val = \REFNULL~t) \\ \val~\REFISNULL &\stepto& \I32.\CONST~0 - & (\iff \val \neq \REFNULL) \\ + & (\otherwise) \\ \end{array} @@ -1768,7 +1768,7 @@ Control Instructions 11. Let :math:`r` be the :ref:`reference ` :math:`\X{tab}.\TIELEM[i]`. -12. If :math:`r` is |REFNULL|, then: +12. If :math:`r` is :math:`\REFNULL~t`, then: a. Trap. diff --git a/document/core/exec/modules.rst b/document/core/exec/modules.rst index eb46eb68..1e578785 100644 --- a/document/core/exec/modules.rst +++ b/document/core/exec/modules.rst @@ -110,15 +110,15 @@ The following auxiliary typing rules specify this typing relation relative to a .. _valid-ref: -:ref:`Null References ` :math:`\REFNULL` -.................................................... +:ref:`Null References ` :math:`\REFNULL~t` +...................................................... -* The value is valid with :ref:`reference type ` :math:`\NULLREF`. +* The value is valid with :ref:`reference type ` :math:`t`. .. math:: \frac{ }{ - S \vdashval \REFNULL : \NULLREF + S \vdashval \REFNULL~t : t } @@ -447,7 +447,10 @@ and list of :ref:`reference ` vectors for the module's :ref:`element 3. For each :ref:`table ` :math:`\table_i` in :math:`\module.\MTABLES`, do: - a. Let :math:`\tableaddr_i` be the :ref:`table address ` resulting from :ref:`allocating ` :math:`\table_i.\TTYPE`. + a. Let :math:`\limits_i~t_i` be the :ref:`table type ` :math:`\table_i.\TTYPE`. + + b. Let :math:`\tableaddr_i` be the :ref:`table address ` resulting from :ref:`allocating ` :math:`\table_i.\TTYPE` + with initialization value :math:`\REFNULL~t_i`. 4. For each :ref:`memory ` :math:`\mem_i` in :math:`\module.\MMEMS`, do: @@ -526,8 +529,9 @@ where: \MIEXPORTS~\exportinst^\ast ~\} \end{array} \\[1ex] S_1, \funcaddr^\ast &=& \allocfunc^\ast(S, \module.\MFUNCS, \moduleinst) \\ - S_2, \tableaddr^\ast &=& \alloctable^\ast(S_1, (\table.\TTYPE)^\ast, \REFNULL) - \qquad\qquad\qquad~ (\where \table^\ast = \module.\MTABLES) \\ + S_2, \tableaddr^\ast &=& \alloctable^\ast(S_1, (\table.\TTYPE)^\ast, \REFNULL~t) + \qquad\qquad\qquad~ (\where \table^\ast = \module.\MTABLES \\ && + \qquad\qquad\qquad~~ \wedge (\table.\TTYPE)^\ast = (\limits~t)^\ast) \\ S_3, \memaddr^\ast &=& \allocmem^\ast(S_2, (\mem.\MTYPE)^\ast) \qquad\qquad\qquad~ (\where \mem^\ast = \module.\MMEMS) \\ S_4, \globaladdr^\ast &=& \allocglobal^\ast(S_3, (\global.\GTYPE)^\ast, \val^\ast) diff --git a/document/core/exec/runtime.rst b/document/core/exec/runtime.rst index 757cf3f6..a0f13d77 100644 --- a/document/core/exec/runtime.rst +++ b/document/core/exec/runtime.rst @@ -35,7 +35,7 @@ or *host references* pointing to an uninterpreted form of :ref:`host address ` an .. math:: \begin{array}{lcl@{\qquad}l} \default_t &=& t{.}\CONST~0 & (\iff t = \numtype) \\ - \default_t &=& \REFNULL & (\iff t = \reftype) \\ + \default_t &=& \REFNULL~t & (\iff t = \reftype) \\ \end{array} diff --git a/document/core/syntax/instructions.rst b/document/core/syntax/instructions.rst index 87a11b17..a76d4f52 100644 --- a/document/core/syntax/instructions.rst +++ b/document/core/syntax/instructions.rst @@ -183,7 +183,7 @@ Instructions in this group are concerned with accessing :ref:`references ` of all other reference types. The type |FUNCREF| denotes the infinite union of all references to :ref:`functions `, regardless of their :ref:`function types `. -The type |NULLREF| only contains a single value: the :ref:`null ` reference. -It is a :ref:`subtype ` of all other reference types. - -.. note:: - Future versions of WebAssembly may include reference types that do not include null and hence are not supertypes of |NULLREF|. - Reference types are *opaque*, meaning that neither their size nor their bit pattern can be observed. Values of reference type can be stored in :ref:`tables `. diff --git a/document/core/text/instructions.rst b/document/core/text/instructions.rst index dad0d02e..7d97fcce 100644 --- a/document/core/text/instructions.rst +++ b/document/core/text/instructions.rst @@ -143,7 +143,7 @@ Reference Instructions .. math:: \begin{array}{llclll} \production{instruction} & \Tplaininstr_I &::=& \dots \\ &&|& - \text{ref.null} &\Rightarrow& \REFNULL \\ &&|& + \text{ref.null}~~t{:}\Trefedtype &\Rightarrow& \REFNULL~t \\ &&|& \text{ref.is\_null} &\Rightarrow& \REFISNULL \\ &&|& \text{ref.func}~~x{:}\Tfuncidx &\Rightarrow& \REFFUNC~x \\ &&|& \end{array} diff --git a/document/core/text/types.rst b/document/core/text/types.rst index 569e7f21..85f3ca4e 100644 --- a/document/core/text/types.rst +++ b/document/core/text/types.rst @@ -25,6 +25,7 @@ Number Types .. index:: reference type pair: text format; reference type .. _text-reftype: +.. _text-refedtype: Reference Types ~~~~~~~~~~~~~~~ @@ -33,8 +34,10 @@ Reference Types \begin{array}{llcll@{\qquad\qquad}l} \production{reference type} & \Treftype &::=& \text{anyref} &\Rightarrow& \ANYREF \\ &&|& - \text{funcref} &\Rightarrow& \FUNCREF \\ &&|& - \text{nullref} &\Rightarrow& \NULLREF \\ + \text{funcref} &\Rightarrow& \FUNCREF \\ + \production{referenced type} & \Trefedtype &::=& + \text{any} &\Rightarrow& \ANYREF \\ &&|& + \text{func} &\Rightarrow& \FUNCREF \\ \end{array} diff --git a/document/core/util/macros.def b/document/core/util/macros.def index 4151d7a5..8142139b 100644 --- a/document/core/util/macros.def +++ b/document/core/util/macros.def @@ -181,7 +181,6 @@ .. |ANYREF| mathdef:: \xref{syntax/types}{syntax-reftype}{\K{anyref}} .. |FUNCREF| mathdef:: \xref{syntax/types}{syntax-reftype}{\K{funcref}} -.. |NULLREF| mathdef:: \xref{syntax/types}{syntax-reftype}{\K{nullref}} .. |MVAR| mathdef:: \xref{syntax/types}{syntax-mut}{\K{var}} .. |MCONST| mathdef:: \xref{syntax/types}{syntax-mut}{\K{const}} @@ -659,6 +658,7 @@ .. |Tnumtype| mathdef:: \xref{text/types}{text-numtype}{\T{numtype}} .. |Treftype| mathdef:: \xref{text/types}{text-reftype}{\T{reftype}} +.. |Trefedtype| mathdef:: \xref{text/types}{text-refedtype}{\T{refedtype}} .. |Tvaltype| mathdef:: \xref{text/types}{text-valtype}{\T{valtype}} .. |Tresulttype| mathdef:: \xref{text/types}{text-resulttype}{\T{resulttype}} .. |Tblocktype| mathdef:: \xref{text/types}{text-blocktype}{\T{blocktype}} diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst index c125c8bc..94efc2d7 100644 --- a/document/core/valid/instructions.rst +++ b/document/core/valid/instructions.rst @@ -166,15 +166,15 @@ Reference Instructions .. _valid-ref.null: -:math:`\REFNULL` -................ +:math:`\REFNULL~t` +.................. -* The instruction is valid with type :math:`[] \to [\NULLREF]`. +* The instruction is valid with type :math:`[] \to [t]`. .. math:: \frac{ }{ - C \vdashinstr \REFNULL : [] \to [\NULLREF] + C \vdashinstr \REFNULL~t : [] \to [t] } diff --git a/document/core/valid/types.rst b/document/core/valid/types.rst index f18a500f..e3212660 100644 --- a/document/core/valid/types.rst +++ b/document/core/valid/types.rst @@ -235,8 +235,6 @@ A :ref:`reference type ` :math:`\reftype_1` matches a :ref:`refe * Either both :math:`\reftype_1` and :math:`\reftype_2` are the same. -* Or :math:`\reftype_1` is |NULLREF|. - * Or :math:`\reftype_2` is |ANYREF|. .. math:: @@ -247,11 +245,6 @@ A :ref:`reference type ` :math:`\reftype_1` matches a :ref:`refe } \qquad \frac{ - }{ - \vdashreftypematch \NULLREF \matchesvaltype \reftype - } - \qquad - \frac{ }{ \vdashreftypematch \reftype \matchesvaltype \ANYREF } diff --git a/document/js-api/index.bs b/document/js-api/index.bs index 14bd1b59..20734823 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -152,7 +152,6 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df url: syntax/types.html#syntax-reftype text: anyref text: funcref - text: nullref text: function element; url: exec/runtime.html#syntax-funcelem text: import component; url: syntax/modules.html#imports text: external value; url: exec/runtime.html#syntax-externval @@ -707,7 +706,6 @@ Immediately after a WebAssembly [=memory.grow=] instruction executes, perform th
 enum TableKind {
-  "nullref",
   "anyref",
   "anyfunc",
   // Note: More values may be added in future iterations,
@@ -836,7 +834,6 @@ enum ValueType {
   "i64",
   "f32",
   "f64",
-  "nullref",
   "anyref",
   "anyfunc",
 };
@@ -892,7 +889,6 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
     1. If |s| equals "f64", return [=π–ΏπŸ¨πŸ¦=].
     1. If |s| equals "anyref", return [=anyref=].
     1. If |s| equals "funcref", return [=funcref=].
-    1. If |s| equals "nullref", return [=nullref=].
     1. Assert: This step is not reached.
 
 
@@ -902,9 +898,7 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
     1. If |valuetype| equals [=π—‚πŸ¨πŸ¦=], return [=π—‚πŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] 0.
     1. If |valuetype| equals [=𝖿πŸ₯𝟀=], return [=𝖿πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] 0.
     1. If |valuetype| equals [=π–ΏπŸ¨πŸ¦=], return [=π–ΏπŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] 0.
-    1. If |valuetype| equals [=nullref=], return [=ref.null=].
     1. If |valuetype| equals [=anyref=], return [=ToWebAssemblyValue=](undefined, |valuetype|).
-    1. If |valuetype| equals [=nullref=], return [=ref.null=].
     1. Assert: This step is not reached.
 
 
@@ -1097,8 +1091,6 @@ The algorithm ToWebAssemblyValue(|v|, |type|) coerces a JavaScript va
     1. Do nothing.
 1. If |type| is [=funcref=],
     1. If |v| is not an [=Exported function=] or null, throw a {{TypeError}}.
-1. If |type| is [=nullref=],
-    1. If |v| is not null, throw a {{TypeError}}.
 1. Return the result of [=allocating a host address=] for |v|.
 
 
diff --git a/interpreter/README.md b/interpreter/README.md
index 2c320f16..8427536c 100644
--- a/interpreter/README.md
+++ b/interpreter/README.md
@@ -178,13 +178,14 @@ var:  | 
 unop:  ctz | clz | popcnt | ...
 binop: add | sub | mul | ...
 relop: eq | ne | lt | ...
-sign:  s|u
+sign:  s | u
 offset: offset=
 align: align=(1|2|4|8|...)
 cvtop: trunc | extend | wrap | ...
 
 num_type: i32 | i64 | f32 | f64
-ref_type: anyref | funcref | nullref
+ref_kind: any | func
+ref_type: anyref | funcref
 val_type: num_type | ref_type
 block_type : ( result * )*
 func_type:   ( type  )? * *
@@ -240,8 +241,8 @@ op:
   memory.copy
   memory.init 
   data.drop 
-  ref.null
-  ref.isnull
+  ref.null 
+  ref.is_null
   ref.func 
   .const 
   .
@@ -349,7 +350,7 @@ action:
 
 const:
   ( .const  )                 ;; number value
-  ( ref.null )                               ;; null reference
+  ( ref.null  )                    ;; null reference
   ( ref.host  )                         ;; host reference
 
 assertion:
diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml
index af687e86..d900cfdb 100644
--- a/interpreter/binary/decode.ml
+++ b/interpreter/binary/decode.ml
@@ -145,7 +145,6 @@ let ref_type s =
   match vs7 s with
   | -0x10 -> FuncRefType
   | -0x11 -> AnyRefType
-  | -0x12 -> NullRefType
   | _ -> error s (pos s - 1) "malformed reference type"
 
 let value_type s =
@@ -444,7 +443,7 @@ let rec instr s =
   | 0xc0 | 0xc1 | 0xc2 | 0xc3 | 0xc4 | 0xc5 | 0xc6 | 0xc7
   | 0xc8 | 0xc9 | 0xca | 0xcb | 0xcc | 0xcd | 0xce | 0xcf as b -> illegal s pos b
 
-  | 0xd0 -> ref_null
+  | 0xd0 -> ref_null (ref_type s)
   | 0xd1 -> ref_is_null
   | 0xd2 -> ref_func (at var s)
 
diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml
index 6910cf42..054f0e72 100644
--- a/interpreter/binary/encode.ml
+++ b/interpreter/binary/encode.ml
@@ -99,7 +99,6 @@ let encode m =
     let ref_type = function
       | FuncRefType -> vs7 (-0x10)
       | AnyRefType -> vs7 (-0x11)
-      | NullRefType -> vs7 (-0x12)
 
     let value_type = function
       | NumType t -> num_type t
@@ -233,7 +232,7 @@ let encode m =
       | MemoryInit x -> op 0xfc; op 0x08; var x; u8 0x00
       | DataDrop x -> op 0xfc; op 0x09; var x
 
-      | RefNull -> op 0xd0
+      | RefNull t -> op 0xd0; ref_type t
       | RefIsNull -> op 0xd1
       | RefFunc x -> op 0xd2; var x
 
diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml
index 58802850..3c809c42 100644
--- a/interpreter/exec/eval.ml
+++ b/interpreter/exec/eval.ml
@@ -97,7 +97,7 @@ let any_ref inst x i at =
 let func_ref inst x i at =
   match any_ref inst x i at with
   | FuncRef f -> f
-  | NullRef -> Trap.error at ("uninitialized element " ^ Int32.to_string i)
+  | NullRef _ -> Trap.error at ("uninitialized element " ^ Int32.to_string i)
   | _ -> Crash.error at ("type mismatch for element " ^ Int32.to_string i)
 
 let take n (vs : 'a stack) at =
@@ -407,14 +407,16 @@ let rec step (c : config) : config =
         seg := "";
         vs, []
 
-      | RefNull, vs' ->
-        Ref NullRef :: vs', []
+      | RefNull t, vs' ->
+        Ref (NullRef t) :: vs', []
 
       | RefIsNull, Ref r :: vs' ->
-        if r = NullRef then
+        (match r with
+        | NullRef _ ->
           Num (I32 1l) :: vs', []
-        else
+        | _ ->
           Num (I32 0l) :: vs', []
+        )
 
       | RefFunc x, vs' ->
         let f = func frame.inst x in
@@ -554,7 +556,8 @@ let create_func (inst : module_inst) (f : func) : func_inst =
 
 let create_table (inst : module_inst) (tab : table) : table_inst =
   let {ttype} = tab.it in
-  Table.alloc ttype NullRef
+  let TableType (_lim, t) = ttype in
+  Table.alloc ttype (NullRef t)
 
 let create_memory (inst : module_inst) (mem : memory) : memory_inst =
   let {mtype} = mem.it in
diff --git a/interpreter/host/spectest.ml b/interpreter/host/spectest.ml
index a8d32aa5..a2cbf096 100644
--- a/interpreter/host/spectest.ml
+++ b/interpreter/host/spectest.ml
@@ -14,12 +14,13 @@ let global (GlobalType (t, _) as gt) =
     | NumType I64Type -> Num (I64 666L)
     | NumType F32Type -> Num (F32 (F32.of_float 666.6))
     | NumType F64Type -> Num (F64 (F64.of_float 666.6))
-    | RefType _ -> Ref NullRef
+    | RefType t -> Ref (NullRef t)
     | BotType -> assert false
   in Global.alloc gt v
 
 let table =
-  Table.alloc (TableType ({min = 10l; max = Some 20l}, FuncRefType)) NullRef
+  Table.alloc (TableType ({min = 10l; max = Some 20l}, FuncRefType))
+    (NullRef FuncRefType)
 let memory = Memory.alloc (MemoryType {min = 1l; max = Some 2l})
 let func f t = Func.alloc_host t (f t)
 
diff --git a/interpreter/script/js.ml b/interpreter/script/js.ml
index f0eeb114..312072f5 100644
--- a/interpreter/script/js.ml
+++ b/interpreter/script/js.ml
@@ -244,7 +244,7 @@ let abs_mask_of = function
 let value v =
   match v.it with
   | Values.Num num -> [Const (num @@ v.at) @@ v.at]
-  | Values.Ref Values.NullRef -> [RefNull @@ v.at]
+  | Values.Ref (Values.NullRef t) -> [RefNull t @@ v.at]
   | Values.Ref (HostRef n) ->
     [Const (Values.I32 n @@ v.at) @@ v.at; Call (hostref_idx @@ v.at) @@ v.at]
   | Values.Ref _ -> assert false
@@ -270,7 +270,7 @@ let assert_return ress ts at =
         Compare (eq_of t') @@ at;
         Test (Values.I32 I32Op.Eqz) @@ at;
         BrIf (0l @@ at) @@ at ]
-    | LitResult {it = Values.Ref Values.NullRef; _} ->
+    | LitResult {it = Values.Ref (Values.NullRef _); _} ->
       [ RefIsNull @@ at;
         Test (Values.I32 I32Op.Eqz) @@ at;
         BrIf (0l @@ at) @@ at ]
@@ -407,7 +407,7 @@ let of_value v =
   | Num (I64 i) -> "int64(\"" ^ I64.to_string_s i ^ "\")"
   | Num (F32 z) -> of_float (F32.to_float z)
   | Num (F64 z) -> of_float (F64.to_float z)
-  | Ref NullRef -> "null"
+  | Ref (NullRef _) -> "null"
   | Ref (HostRef n) -> "hostref(" ^ Int32.to_string n ^ ")"
   | _ -> assert false
 
diff --git a/interpreter/script/run.ml b/interpreter/script/run.ml
index 11764e43..58144476 100644
--- a/interpreter/script/run.ml
+++ b/interpreter/script/run.ml
@@ -377,7 +377,8 @@ let assert_result at got expect =
         )
       | RefResult ->
         (match v with
-        | Ref ref -> ref = NullRef
+        | Ref (NullRef _) -> true
+        | Ref _ -> false
         | _ -> true
         )
       | FuncResult ->
diff --git a/interpreter/syntax/ast.ml b/interpreter/syntax/ast.ml
index d3e1c6c0..949a5f91 100644
--- a/interpreter/syntax/ast.ml
+++ b/interpreter/syntax/ast.ml
@@ -102,7 +102,7 @@ and instr' =
   | MemoryCopy                        (* copy memory ranges *)
   | MemoryInit of var                 (* initialize memory range from segment *)
   | DataDrop of var                   (* drop passive data segment *)
-  | RefNull                           (* null reference *)
+  | RefNull of ref_type               (* null reference *)
   | RefIsNull                         (* null test *)
   | RefFunc of var                    (* function reference *)
   | Const of num                      (* constant *)
diff --git a/interpreter/syntax/free.ml b/interpreter/syntax/free.ml
index af322f67..33bfefc0 100644
--- a/interpreter/syntax/free.ml
+++ b/interpreter/syntax/free.ml
@@ -62,7 +62,7 @@ let list free xs = List.fold_left union empty (List.map free xs)
 let rec instr (e : instr) =
   match e.it with
   | Unreachable | Nop | Drop | Select _ -> empty
-  | RefNull | RefIsNull -> empty
+  | RefNull _ | RefIsNull -> empty
   | RefFunc x -> funcs (var x)
   | Const _ | Test _ | Compare _ | Unary _ | Binary _ | Convert _ -> empty
   | Block (_, es) | Loop (_, es) -> block es
diff --git a/interpreter/syntax/operators.ml b/interpreter/syntax/operators.ml
index e804a413..73b2f410 100644
--- a/interpreter/syntax/operators.ml
+++ b/interpreter/syntax/operators.ml
@@ -9,7 +9,7 @@ let i32_const n = Const (I32 n.it @@ n.at)
 let i64_const n = Const (I64 n.it @@ n.at)
 let f32_const n = Const (F32 n.it @@ n.at)
 let f64_const n = Const (F64 n.it @@ n.at)
-let ref_null = RefNull
+let ref_null t = RefNull t
 let ref_func x = RefFunc x
 let ref_is_null = RefIsNull
 
diff --git a/interpreter/syntax/types.ml b/interpreter/syntax/types.ml
index fb3f13b1..60c595b8 100644
--- a/interpreter/syntax/types.ml
+++ b/interpreter/syntax/types.ml
@@ -1,7 +1,7 @@
 (* Types *)
 
 type num_type = I32Type | I64Type | F32Type | F64Type
-type ref_type = NullRefType | AnyRefType | FuncRefType
+type ref_type = AnyRefType | FuncRefType
 type value_type = NumType of num_type | RefType of ref_type | BotType
 type stack_type = value_type list
 type func_type = FuncType of stack_type * stack_type
@@ -33,7 +33,6 @@ let match_num_type t1 t2 =
 let match_ref_type t1 t2 =
   match t1, t2 with
   | _, AnyRefType -> true
-  | NullRefType, _ -> true
   | _, _ -> t1 = t2
 
 let match_value_type t1 t2 =
@@ -101,7 +100,6 @@ let string_of_num_type = function
   | F64Type -> "f64"
 
 let string_of_ref_type = function
-  | NullRefType -> "nullref"
   | AnyRefType -> "anyref"
   | FuncRefType -> "funcref"
 
diff --git a/interpreter/syntax/values.ml b/interpreter/syntax/values.ml
index 6907ae75..1024eb05 100644
--- a/interpreter/syntax/values.ml
+++ b/interpreter/syntax/values.ml
@@ -9,7 +9,7 @@ type ('i32, 'i64, 'f32, 'f64) op =
 type num = (I32.t, I64.t, F32.t, F64.t) op
 
 type ref_ = ..
-type ref_ += NullRef
+type ref_ += NullRef of ref_type
 
 type value = Num of num | Ref of ref_
 
@@ -22,7 +22,7 @@ let type_of_num = function
   | F32 _ -> F32Type
   | F64 _ -> F64Type
 
-let type_of_ref' = ref (function NullRef -> NullRefType | _ -> AnyRefType)
+let type_of_ref' = ref (function NullRef t -> t | _ -> AnyRefType)
 let type_of_ref r = !type_of_ref' r
 
 let type_of_value = function
@@ -50,7 +50,7 @@ let default_num = function
   | F64Type -> F64 F64.zero
 
 let default_ref = function
-  | _ -> NullRef
+  | t -> NullRef t
 
 let default_value = function
   | NumType t' -> Num (default_num t')
@@ -68,7 +68,7 @@ let string_of_num = function
   | F32 z -> F32.to_string z
   | F64 z -> F64.to_string z
 
-let string_of_ref' = ref (function NullRef -> "null" | _ -> "ref")
+let string_of_ref' = ref (function NullRef t -> "null" | _ -> "ref")
 let string_of_ref r = !string_of_ref' r
 
 let string_of_value = function
diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml
index 6fc76e93..3df41b49 100644
--- a/interpreter/text/arrange.ml
+++ b/interpreter/text/arrange.ml
@@ -55,6 +55,10 @@ let break_string s =
 
 (* Types *)
 
+let ref_kind = function
+  | AnyRefType -> "any"
+  | FuncRefType -> "func"
+
 let num_type t = string_of_num_type t
 let ref_type t = string_of_ref_type t
 let value_type t = string_of_value_type t
@@ -262,7 +266,7 @@ let rec instr e =
     | MemoryCopy -> "memory.copy", []
     | MemoryInit x -> "memory.init " ^ var x, []
     | DataDrop x -> "data.drop " ^ var x, []
-    | RefNull -> "ref.null", []
+    | RefNull t -> "ref.null", [Atom (ref_kind t)]
     | RefIsNull -> "ref.is_null", []
     | RefFunc x -> "ref.func " ^ var x, []
     | Const n -> constop n ^ " " ^ num n, []
@@ -431,7 +435,7 @@ let value v =
   | Num (Values.I64 i) -> Node ("i64.const " ^ I64.to_string_s i, [])
   | Num (Values.F32 z) -> Node ("f32.const " ^ F32.to_string z, [])
   | Num (Values.F64 z) -> Node ("f64.const " ^ F64.to_string z, [])
-  | Ref NullRef -> Node ("ref.null", [])
+  | Ref (NullRef t) -> Node ("ref.null", [Atom (ref_kind t)])
   | Ref (HostRef n) -> Node ("ref.host " ^ Int32.to_string n, [])
   | _ -> assert false
 
diff --git a/interpreter/text/lexer.mll b/interpreter/text/lexer.mll
index 3a1c3f11..6667f611 100644
--- a/interpreter/text/lexer.mll
+++ b/interpreter/text/lexer.mll
@@ -160,9 +160,9 @@ rule token = parse
   | '"'character*'\\'_
     { error_nest (Lexing.lexeme_end_p lexbuf) lexbuf "illegal escape" }
 
+  | "any" { ANY }
   | "anyref" { ANYREF }
   | "funcref" { FUNCREF }
-  | "nullref" { NULLREF }
   | (nxx as t) { NUM_TYPE (num_type t) }
   | "mut" { MUT }
 
diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly
index 07be9cbc..10b07024 100644
--- a/interpreter/text/parser.mly
+++ b/interpreter/text/parser.mly
@@ -164,7 +164,7 @@ let inline_type_explicit (c : context) x ft at =
 
 %token LPAR RPAR
 %token NAT INT FLOAT STRING VAR
-%token ANYREF NULLREF FUNCREF NUM_TYPE MUT
+%token ANY ANYREF FUNCREF NUM_TYPE MUT
 %token UNREACHABLE NOP DROP SELECT
 %token BLOCK END IF THEN ELSE LOOP BR BR_IF BR_TABLE
 %token CALL CALL_INDIRECT RETURN
@@ -226,10 +226,13 @@ string_list :
 
 /* Types */
 
+ref_kind :
+  | ANY { AnyRefType }
+  | FUNC { FuncRefType }
+
 ref_type :
   | ANYREF { AnyRefType }
   | FUNCREF { FuncRefType }
-  | NULLREF { NullRefType }
 
 value_type :
   | NUM_TYPE { NumType $1 }
@@ -372,7 +375,7 @@ plain_instr :
   | MEMORY_COPY { fun c -> memory_copy }
   | MEMORY_INIT var { fun c -> memory_init ($2 c data) }
   | DATA_DROP var { fun c -> data_drop ($2 c data) }
-  | REF_NULL { fun c -> ref_null }
+  | REF_NULL ref_kind { fun c -> ref_null $2 }
   | REF_IS_NULL { fun c -> ref_is_null }
   | REF_FUNC var { fun c -> ref_func ($2 c func) }
   | CONST num { fun c -> fst (num $1 $2) }
@@ -986,7 +989,7 @@ meta :
 
 const :
   | LPAR CONST num RPAR { Values.Num (snd (num $2 $3)) @@ at () }
-  | LPAR REF_NULL RPAR { Values.Ref Values.NullRef @@ at () }
+  | LPAR REF_NULL ref_kind RPAR { Values.Ref (Values.NullRef $3) @@ at () }
   | LPAR REF_HOST NAT RPAR { Values.Ref (HostRef (nat32 $3 (ati 3))) @@ at () }
 
 const_list :
diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml
index 30de76a6..69122001 100644
--- a/interpreter/valid/valid.ml
+++ b/interpreter/valid/valid.ml
@@ -342,8 +342,8 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type =
     ignore (data c x);
     [] --> []
 
-  | RefNull ->
-    [] --> [RefType NullRefType]
+  | RefNull t ->
+    [] --> [RefType t]
 
   | RefIsNull ->
     [RefType AnyRefType] --> [NumType I32Type]
@@ -466,7 +466,7 @@ let check_func (c : context) (f : func) =
 
 let is_const (c : context) (e : instr) =
   match e.it with
-  | RefNull
+  | RefNull _
   | RefFunc _
   | Const _ -> true
   | GlobalGet x -> let GlobalType (_, mut) = global c x in mut = Immutable
diff --git a/proposals/reference-types/Overview.md b/proposals/reference-types/Overview.md
index 8e35ab71..fea602cf 100644
--- a/proposals/reference-types/Overview.md
+++ b/proposals/reference-types/Overview.md
@@ -25,8 +25,7 @@ by repurposing tables as a general memory for opaque data types
 Get the most important parts soon!
 
 Summary:
-
-* Add new types `anyref` and `nullref` that can be used as both a value types and a table element types.
+* Add new type `anyref` that can be used as both a value types and a table element type.
 
 * Also allow `funcref` as a value type.
 
@@ -47,8 +46,8 @@ Notes:
 
 Typing extensions:
 
-* Introduce `anyref`, `funcref`, and `nullref` as a new class of *reference types*.
-  - `reftype ::= anyref | funcref | nullref`
+* Introduce `anyref` and `funcref` as a new class of *reference types*.
+  - `reftype ::= anyref | funcref`
 
 * Value types (of locals, globals, function parameters and results) can now be either numeric types or reference types.
   - `numtype ::= i32 | i64 | f32 | f64`
@@ -61,14 +60,13 @@ Typing extensions:
 * Introduce a simple subtype relation between reference types.
   - reflexive transitive closure of the following rules
   - `t <: anyref` for all reftypes `t`
-  - `nullref <: anyref` and `nullref <: funcref`
-  - Note: No rule `nullref <: t` for all reftypes `t` -- while that is derivable from the above given the current set of types it might not hold for future reference types which don't allow null.
 
 
 New/extended instructions:
 
 * The new instruction `ref.null` evaluates to the null reference constant.
-  - `ref.null : [] -> [nullref]`
+  - `ref.null rt : [] -> [rtref]`
+    - iff `rt = any` or `rt = func` 
   - allowed in constant expressions
 
 * The new instruction `ref.is_null` checks for null.
@@ -159,7 +157,6 @@ Additions:
   - `reftype ::= ... | eqref`
 * It is a subtype of `anyref`
   - `eqref < anyref`
-  - `nullref < eqref`
 * Add `ref.eq` instruction.
   - `ref.eq : [eqref eqref] -> [i32]`
 
diff --git a/test/core/binary.wast b/test/core/binary.wast
index 91cdd359..4b00271d 100644
--- a/test/core/binary.wast
+++ b/test/core/binary.wast
@@ -1116,10 +1116,10 @@
 
   "\05\03\01\00\00"          ;; Memory section
 
-  "\09\06\01"                ;; Element section with one segment
+  "\09\07\01"                ;; Element section with one segment
   "\05\70"                   ;; Passive, funcref
   "\01"                      ;; 1 element
-  "\d0\0b"                   ;; ref.null, end
+  "\d0\70\0b"                ;; ref.null, end
 
   "\0a\04\01"                ;; Code section
 
diff --git a/test/core/br_table.wast b/test/core/br_table.wast
index 48e7a874..7589d72a 100644
--- a/test/core/br_table.wast
+++ b/test/core/br_table.wast
@@ -1280,24 +1280,6 @@
     )
   )
 
-  (func (export "meet-nullref") (param i32) (result funcref)
-    (block $l1 (result funcref)
-      (block $l2 (result nullref)
-        (br_table $l1 $l2 $l1 (ref.null) (local.get 0))
-      )
-    )
-  )
-
-  (func (export "meet-multi-ref") (param i32) (result anyref)
-    (block $l1 (result anyref)
-      (block $l2 (result funcref)
-        (block $l3 (result nullref)
-          (br_table $l3 $l2 $l1 (ref.null) (local.get 0))
-        )
-      )
-    )
-  )
-
   (func (export "meet-bottom")
     (block (result f64)
       (block (result f32)
@@ -1641,10 +1623,10 @@
     (block $l1 (result anyref)
       (drop
         (block $l2 (result i32)
-          (br_table $l2 $l1 $l2 (ref.null) (local.get 0))
+          (br_table $l2 $l1 $l2 (ref.null any) (local.get 0))
         )
       )
-      (ref.null)
+      (ref.null any)
     )
   ))
   "type mismatch"
diff --git a/test/core/bulk.wast b/test/core/bulk.wast
index fe71939d..1927461f 100644
--- a/test/core/bulk.wast
+++ b/test/core/bulk.wast
@@ -5,7 +5,7 @@
 
 (module
   (table 3 funcref)
-  (elem funcref (ref.func 0) (ref.null) (ref.func 1))
+  (elem funcref (ref.func 0) (ref.null func) (ref.func 1))
   (func)
   (func))
 
diff --git a/test/core/elem.wast b/test/core/elem.wast
index 6661c9a8..d0537aa2 100644
--- a/test/core/elem.wast
+++ b/test/core/elem.wast
@@ -8,18 +8,18 @@
 
   ;; Passive
   (elem funcref)
-  (elem funcref (ref.func $f) (item ref.func $f) (item (ref.null)) (ref.func $g))
+  (elem funcref (ref.func $f) (item ref.func $f) (item (ref.null func)) (ref.func $g))
   (elem func)
   (elem func $f $f $g $g)
 
   (elem $p1 funcref)
-  (elem $p2 funcref (ref.func $f) (ref.func $f) (ref.null) (ref.func $g))
+  (elem $p2 funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g))
   (elem $p3 func)
   (elem $p4 func $f $f $g $g)
 
   ;; Active
   (elem (table $t) (i32.const 0) funcref)
-  (elem (table $t) (i32.const 0) funcref (ref.func $f) (ref.null))
+  (elem (table $t) (i32.const 0) funcref (ref.func $f) (ref.null func))
   (elem (table $t) (i32.const 0) func)
   (elem (table $t) (i32.const 0) func $f $g)
   (elem (table $t) (offset (i32.const 0)) funcref)
@@ -33,16 +33,16 @@
   (elem (table $t) (offset (i32.const 0)) func)
   (elem (table $t) (offset (i32.const 0)) func $f $f)
   (elem (offset (i32.const 0)))
-  (elem (offset (i32.const 0)) funcref (ref.func $f) (ref.null))
+  (elem (offset (i32.const 0)) funcref (ref.func $f) (ref.null func))
   (elem (offset (i32.const 0)) func $f $f)
   (elem (offset (i32.const 0)) $f $f)
   (elem (i32.const 0))
-  (elem (i32.const 0) funcref (ref.func $f) (ref.null))
+  (elem (i32.const 0) funcref (ref.func $f) (ref.null func))
   (elem (i32.const 0) func $f $f)
   (elem (i32.const 0) $f $f)
 
   (elem $a1 (table $t) (i32.const 0) funcref)
-  (elem $a2 (table $t) (i32.const 0) funcref (ref.func $f) (ref.null))
+  (elem $a2 (table $t) (i32.const 0) funcref (ref.func $f) (ref.null func))
   (elem $a3 (table $t) (i32.const 0) func)
   (elem $a4 (table $t) (i32.const 0) func $f $g)
   (elem $a9 (table $t) (offset (i32.const 0)) funcref)
@@ -56,22 +56,22 @@
   (elem $a17 (table $t) (offset (i32.const 0)) func)
   (elem $a18 (table $t) (offset (i32.const 0)) func $f $f)
   (elem $a19 (offset (i32.const 0)))
-  (elem $a20 (offset (i32.const 0)) funcref (ref.func $f) (ref.null))
+  (elem $a20 (offset (i32.const 0)) funcref (ref.func $f) (ref.null func))
   (elem $a21 (offset (i32.const 0)) func $f $f)
   (elem $a22 (offset (i32.const 0)) $f $f)
   (elem $a23 (i32.const 0))
-  (elem $a24 (i32.const 0) funcref (ref.func $f) (ref.null))
+  (elem $a24 (i32.const 0) funcref (ref.func $f) (ref.null func))
   (elem $a25 (i32.const 0) func $f $f)
   (elem $a26 (i32.const 0) $f $f)
 
   ;; Declarative
   (elem declare funcref)
-  (elem declare funcref (ref.func $f) (ref.func $f) (ref.null) (ref.func $g))
+  (elem declare funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g))
   (elem declare func)
   (elem declare func $f $f $g $g)
 
   (elem $d1 declare funcref)
-  (elem $d2 declare funcref (ref.func $f) (ref.func $f) (ref.null) (ref.func $g))
+  (elem $d2 declare funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g))
   (elem $d3 declare func)
   (elem $d4 declare func $f $f $g $g)
 )
@@ -80,7 +80,7 @@
   (func $f)
   (func $g)
 
-  (table $t funcref (elem (ref.func $f) (ref.null) (ref.func $g)))
+  (table $t funcref (elem (ref.func $f) (ref.null func) (ref.func $g)))
 )
 
 
diff --git a/test/core/global.wast b/test/core/global.wast
index 1326679e..ef0ccf72 100644
--- a/test/core/global.wast
+++ b/test/core/global.wast
@@ -11,8 +11,8 @@
   (global (;6;) (mut f64) (f64.const -14))
   (global $y (mut i64) (i64.const -15))
 
-  (global $r anyref (ref.null))
-  (global funcref (ref.null))
+  (global $r anyref (ref.null any))
+  (global funcref (ref.null func))
 
   (func (export "get-a") (result i32) (global.get $a))
   (func (export "get-b") (result i64) (global.get $b))
@@ -184,7 +184,7 @@
 
 (assert_return (invoke "get-a") (i32.const -2))
 (assert_return (invoke "get-b") (i64.const -5))
-(assert_return (invoke "get-r") (ref.null))
+(assert_return (invoke "get-r") (ref.null any))
 (assert_return (invoke "get-x") (i32.const -12))
 (assert_return (invoke "get-y") (i64.const -15))
 
diff --git a/test/core/linking.wast b/test/core/linking.wast
index 49d55723..2b51032d 100644
--- a/test/core/linking.wast
+++ b/test/core/linking.wast
@@ -94,62 +94,32 @@
 
 
 (module $Mref_ex
-  (global (export "g-const-null") nullref (ref.null))
-  (global (export "g-var-null") (mut nullref) (ref.null))
-  (global (export "g-const-func") funcref (ref.null))
-  (global (export "g-var-func") (mut funcref) (ref.null))
-  (global (export "g-const-any") anyref (ref.null))
-  (global (export "g-var-any") (mut anyref) (ref.null))
+  (global (export "g-const-func") funcref (ref.null func))
+  (global (export "g-var-func") (mut funcref) (ref.null func))
+  (global (export "g-const-any") anyref (ref.null any))
+  (global (export "g-var-any") (mut anyref) (ref.null any))
 )
 (register "Mref_ex" $Mref_ex)
 
 (module $Mref_im
-  (global (import "Mref_ex" "g-const-null") nullref)
-  (global (import "Mref_ex" "g-const-null") funcref)
-  (global (import "Mref_ex" "g-const-null") anyref)
   (global (import "Mref_ex" "g-const-func") funcref)
   (global (import "Mref_ex" "g-const-func") anyref)
   (global (import "Mref_ex" "g-const-any") anyref)
 
-  (global (import "Mref_ex" "g-var-null") (mut nullref))
   (global (import "Mref_ex" "g-var-func") (mut funcref))
   (global (import "Mref_ex" "g-var-any") (mut anyref))
 )
 
-(assert_unlinkable
-  (module (global (import "Mref_ex" "g-const-func") nullref))
-  "incompatible import type"
-)
-(assert_unlinkable
-  (module (global (import "Mref_ex" "g-const-any") nullref))
-  "incompatible import type"
-)
 (assert_unlinkable
   (module (global (import "Mref_ex" "g-const-any") funcref))
   "incompatible import type"
 )
 
 
-(assert_unlinkable
-  (module (global (import "Mref_ex" "g-var-null") (mut funcref)))
-  "incompatible import type"
-)
-(assert_unlinkable
-  (module (global (import "Mref_ex" "g-var-null") (mut anyref)))
-  "incompatible import type"
-)
-(assert_unlinkable
-  (module (global (import "Mref_ex" "g-var-func") (mut nullref)))
-  "incompatible import type"
-)
 (assert_unlinkable
   (module (global (import "Mref_ex" "g-var-func") (mut anyref)))
   "incompatible import type"
 )
-(assert_unlinkable
-  (module (global (import "Mref_ex" "g-var-any") (mut nullref)))
-  "incompatible import type"
-)
 (assert_unlinkable
   (module (global (import "Mref_ex" "g-var-any") (mut funcref)))
   "incompatible import type"
@@ -315,38 +285,20 @@
 
 
 (module $Mtable_ex
-  (table $t1 (export "t-null") 1 nullref)
-  (table $t2 (export "t-func") 1 funcref)
-  (table $t3 (export "t-any") 1 anyref)
+  (table $t1 (export "t-func") 1 funcref)
+  (table $t2 (export "t-any") 1 anyref)
 )
 (register "Mtable_ex" $Mtable_ex)
 
 (module
-  (table (import "Mtable_ex" "t-null") 1 nullref)
   (table (import "Mtable_ex" "t-func") 1 funcref)
   (table (import "Mtable_ex" "t-any") 1 anyref)
 )
 
-(assert_unlinkable
-  (module (table (import "Mtable_ex" "t-null") 1 funcref))
-  "incompatible import type"
-)
-(assert_unlinkable
-  (module (table (import "Mtable_ex" "t-null") 1 anyref))
-  "incompatible import type"
-)
-(assert_unlinkable
-  (module (table (import "Mtable_ex" "t-func") 1 nullref))
-  "incompatible import type"
-)
 (assert_unlinkable
   (module (table (import "Mtable_ex" "t-func") 1 anyref))
   "incompatible import type"
 )
-(assert_unlinkable
-  (module (table (import "Mtable_ex" "t-any") 1 nullref))
-  "incompatible import type"
-)
 (assert_unlinkable
   (module (table (import "Mtable_ex" "t-any") 1 funcref))
   "incompatible import type"
diff --git a/test/core/ref_is_null.wast b/test/core/ref_is_null.wast
index 7a42ca7d..ac283209 100644
--- a/test/core/ref_is_null.wast
+++ b/test/core/ref_is_null.wast
@@ -1,62 +1,49 @@
 (module
-  (func $f1 (export "nullref") (param $x nullref) (result i32)
+  (func $f1 (export "anyref") (param $x anyref) (result i32)
     (ref.is_null (local.get $x))
   )
-  (func $f2 (export "anyref") (param $x anyref) (result i32)
-    (ref.is_null (local.get $x))
-  )
-  (func $f3 (export "funcref") (param $x funcref) (result i32)
+  (func $f2 (export "funcref") (param $x funcref) (result i32)
     (ref.is_null (local.get $x))
   )
 
-  (table $t1 2 nullref)
-  (table $t2 2 anyref)
-  (table $t3 2 funcref)
-  (elem (table $t3) (i32.const 1) func $dummy)
+  (table $t1 2 anyref)
+  (table $t2 2 funcref)
+  (elem (table $t2) (i32.const 1) func $dummy)
   (func $dummy)
 
   (func (export "init") (param $r anyref)
-    (table.set $t2 (i32.const 1) (local.get $r))
+    (table.set $t1 (i32.const 1) (local.get $r))
   )
   (func (export "deinit")
-    (table.set $t1 (i32.const 1) (ref.null))
-    (table.set $t2 (i32.const 1) (ref.null))
-    (table.set $t3 (i32.const 1) (ref.null))
+    (table.set $t1 (i32.const 1) (ref.null any))
+    (table.set $t2 (i32.const 1) (ref.null func))
   )
 
-  (func (export "nullref-elem") (param $x i32) (result i32)
-    (call $f1 (table.get $t1 (local.get $x)))
-  )
   (func (export "anyref-elem") (param $x i32) (result i32)
-    (call $f2 (table.get $t2 (local.get $x)))
+    (call $f1 (table.get $t1 (local.get $x)))
   )
   (func (export "funcref-elem") (param $x i32) (result i32)
-    (call $f3 (table.get $t3 (local.get $x)))
+    (call $f2 (table.get $t2 (local.get $x)))
   )
 )
 
-(assert_return (invoke "nullref" (ref.null)) (i32.const 1))
-(assert_return (invoke "anyref" (ref.null)) (i32.const 1))
-(assert_return (invoke "funcref" (ref.null)) (i32.const 1))
+(assert_return (invoke "anyref" (ref.null any)) (i32.const 1))
+(assert_return (invoke "funcref" (ref.null func)) (i32.const 1))
 
 (assert_return (invoke "anyref" (ref.host 1)) (i32.const 0))
 
 (invoke "init" (ref.host 0))
 
-(assert_return (invoke "nullref-elem" (i32.const 0)) (i32.const 1))
 (assert_return (invoke "anyref-elem" (i32.const 0)) (i32.const 1))
 (assert_return (invoke "funcref-elem" (i32.const 0)) (i32.const 1))
 
-(assert_return (invoke "nullref-elem" (i32.const 1)) (i32.const 1))
 (assert_return (invoke "anyref-elem" (i32.const 1)) (i32.const 0))
 (assert_return (invoke "funcref-elem" (i32.const 1)) (i32.const 0))
 
 (invoke "deinit")
 
-(assert_return (invoke "nullref-elem" (i32.const 0)) (i32.const 1))
 (assert_return (invoke "anyref-elem" (i32.const 0)) (i32.const 1))
 (assert_return (invoke "funcref-elem" (i32.const 0)) (i32.const 1))
 
-(assert_return (invoke "nullref-elem" (i32.const 0)) (i32.const 1))
 (assert_return (invoke "anyref-elem" (i32.const 1)) (i32.const 1))
 (assert_return (invoke "funcref-elem" (i32.const 1)) (i32.const 1))
diff --git a/test/core/ref_null.wast b/test/core/ref_null.wast
index 96cac314..0155d3dc 100644
--- a/test/core/ref_null.wast
+++ b/test/core/ref_null.wast
@@ -1,13 +1,10 @@
 (module
-  (func (export "anyref") (result anyref) (ref.null))
-  (func (export "funcref") (result funcref) (ref.null))
-  (func (export "nullref") (result nullref) (ref.null))
+  (func (export "anyref") (result anyref) (ref.null any))
+  (func (export "funcref") (result funcref) (ref.null func))
 
-  (global anyref (ref.null))
-  (global funcref (ref.null))
-  (global nullref (ref.null))
+  (global anyref (ref.null any))
+  (global funcref (ref.null func))
 )
 
-(assert_return (invoke "anyref") (ref.null))
-(assert_return (invoke "funcref") (ref.null))
-(assert_return (invoke "nullref") (ref.null))
+(assert_return (invoke "anyref") (ref.null any))
+(assert_return (invoke "funcref") (ref.null func))
diff --git a/test/core/select.wast b/test/core/select.wast
index 267dd573..41958aed 100644
--- a/test/core/select.wast
+++ b/test/core/select.wast
@@ -29,9 +29,6 @@
   (func (export "select-f64-t") (param f64 f64 i32) (result f64)
     (select (result f64) (local.get 0) (local.get 1) (local.get 2))
   )
-  (func (export "select-nullref") (param nullref nullref i32) (result nullref)
-    (select (result nullref) (local.get 0) (local.get 1) (local.get 2))
-  )
   (func (export "select-funcref") (param funcref funcref i32) (result funcref)
     (select (result funcref) (local.get 0) (local.get 1) (local.get 2))
   )
@@ -39,13 +36,10 @@
     (select (result anyref) (local.get 0) (local.get 1) (local.get 2))
   )
 
-  (func (export "join-nullref") (param i32) (result anyref)
-    (select (result nullref) (ref.null) (ref.null) (local.get 0))
-  )
   (func (export "join-funcref") (param i32) (result anyref)
     (select (result funcref)
       (table.get $tab (i32.const 0))
-      (ref.null)
+      (ref.null func)
       (local.get 0)
     )
   )
@@ -250,8 +244,7 @@
 (assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const 1)) (i64.const 2))
 (assert_return (invoke "select-f32-t" (f32.const 1) (f32.const 2) (i32.const 1)) (f32.const 1))
 (assert_return (invoke "select-f64-t" (f64.const 1) (f64.const 2) (i32.const 1)) (f64.const 1))
-(assert_return (invoke "select-nullref" (ref.null) (ref.null) (i32.const 1)) (ref.null))
-(assert_return (invoke "select-funcref" (ref.null) (ref.null) (i32.const 1)) (ref.null))
+(assert_return (invoke "select-funcref" (ref.null func) (ref.null func) (i32.const 1)) (ref.null func))
 (assert_return (invoke "select-anyref" (ref.host 1) (ref.host 2) (i32.const 1)) (ref.host 1))
 
 (assert_return (invoke "select-i32-t" (i32.const 1) (i32.const 2) (i32.const 0)) (i32.const 2))
@@ -279,11 +272,8 @@
 (assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan) (i32.const 0)) (f64.const nan))
 (assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan:0x20304) (i32.const 0)) (f64.const nan:0x20304))
 
-(assert_return (invoke "join-nullref" (i32.const 1)) (ref.null))
-(assert_return (invoke "join-nullref" (i32.const 0)) (ref.null))
-
 (assert_return (invoke "join-funcref" (i32.const 1)) (ref.func))
-(assert_return (invoke "join-funcref" (i32.const 0)) (ref.null))
+(assert_return (invoke "join-funcref" (i32.const 0)) (ref.null func))
 
 (assert_return (invoke "join-anyref" (i32.const 1) (ref.host 1)) (ref.func))
 (assert_return (invoke "join-anyref" (i32.const 0) (ref.host 1)) (ref.host 1))
@@ -389,12 +379,6 @@
 )
 
 
-(assert_invalid
-  (module (func $type-nullref-implicit
-    (drop (select (ref.null) (ref.null) (i32.const 1)))
-  ))
-  "type mismatch"
-)
 (assert_invalid
   (module (func $type-anyref-implicit (param $r anyref)
     (drop (select (local.get $r) (local.get $r) (i32.const 1)))
diff --git a/test/core/table_fill.wast b/test/core/table_fill.wast
index 7aff2024..2d77bb4e 100644
--- a/test/core/table_fill.wast
+++ b/test/core/table_fill.wast
@@ -10,24 +10,24 @@
   )
 )
 
-(assert_return (invoke "get" (i32.const 1)) (ref.null))
-(assert_return (invoke "get" (i32.const 2)) (ref.null))
-(assert_return (invoke "get" (i32.const 3)) (ref.null))
-(assert_return (invoke "get" (i32.const 4)) (ref.null))
-(assert_return (invoke "get" (i32.const 5)) (ref.null))
+(assert_return (invoke "get" (i32.const 1)) (ref.null any))
+(assert_return (invoke "get" (i32.const 2)) (ref.null any))
+(assert_return (invoke "get" (i32.const 3)) (ref.null any))
+(assert_return (invoke "get" (i32.const 4)) (ref.null any))
+(assert_return (invoke "get" (i32.const 5)) (ref.null any))
 
 (assert_return (invoke "fill" (i32.const 2) (ref.host 1) (i32.const 3)))
-(assert_return (invoke "get" (i32.const 1)) (ref.null))
+(assert_return (invoke "get" (i32.const 1)) (ref.null any))
 (assert_return (invoke "get" (i32.const 2)) (ref.host 1))
 (assert_return (invoke "get" (i32.const 3)) (ref.host 1))
 (assert_return (invoke "get" (i32.const 4)) (ref.host 1))
-(assert_return (invoke "get" (i32.const 5)) (ref.null))
+(assert_return (invoke "get" (i32.const 5)) (ref.null any))
 
 (assert_return (invoke "fill" (i32.const 4) (ref.host 2) (i32.const 2)))
 (assert_return (invoke "get" (i32.const 3)) (ref.host 1))
 (assert_return (invoke "get" (i32.const 4)) (ref.host 2))
 (assert_return (invoke "get" (i32.const 5)) (ref.host 2))
-(assert_return (invoke "get" (i32.const 6)) (ref.null))
+(assert_return (invoke "get" (i32.const 6)) (ref.null any))
 
 (assert_return (invoke "fill" (i32.const 4) (ref.host 3) (i32.const 0)))
 (assert_return (invoke "get" (i32.const 3)) (ref.host 1))
@@ -35,32 +35,32 @@
 (assert_return (invoke "get" (i32.const 5)) (ref.host 2))
 
 (assert_return (invoke "fill" (i32.const 8) (ref.host 4) (i32.const 2)))
-(assert_return (invoke "get" (i32.const 7)) (ref.null))
+(assert_return (invoke "get" (i32.const 7)) (ref.null any))
 (assert_return (invoke "get" (i32.const 8)) (ref.host 4))
 (assert_return (invoke "get" (i32.const 9)) (ref.host 4))
 
-(assert_return (invoke "fill" (i32.const 9) (ref.null) (i32.const 1)))
+(assert_return (invoke "fill" (i32.const 9) (ref.null any) (i32.const 1)))
 (assert_return (invoke "get" (i32.const 8)) (ref.host 4))
-(assert_return (invoke "get" (i32.const 9)) (ref.null))
+(assert_return (invoke "get" (i32.const 9)) (ref.null any))
 
 (assert_return (invoke "fill" (i32.const 10) (ref.host 5) (i32.const 0)))
-(assert_return (invoke "get" (i32.const 9)) (ref.null))
+(assert_return (invoke "get" (i32.const 9)) (ref.null any))
 
 (assert_trap
   (invoke "fill" (i32.const 8) (ref.host 6) (i32.const 3))
   "out of bounds"
 )
-(assert_return (invoke "get" (i32.const 7)) (ref.null))
+(assert_return (invoke "get" (i32.const 7)) (ref.null any))
 (assert_return (invoke "get" (i32.const 8)) (ref.host 4))
-(assert_return (invoke "get" (i32.const 9)) (ref.null))
+(assert_return (invoke "get" (i32.const 9)) (ref.null any))
 
 (assert_trap
-  (invoke "fill" (i32.const 11) (ref.null) (i32.const 0))
+  (invoke "fill" (i32.const 11) (ref.null any) (i32.const 0))
   "out of bounds"
 )
 
 (assert_trap
-  (invoke "fill" (i32.const 11) (ref.null) (i32.const 10))
+  (invoke "fill" (i32.const 11) (ref.null any) (i32.const 10))
   "out of bounds"
 )
 
@@ -80,7 +80,7 @@
   (module
     (table $t 10 anyref)
     (func $type-index-empty-vs-i32
-      (table.fill $t (ref.null) (i32.const 1))
+      (table.fill $t (ref.null any) (i32.const 1))
     )
   )
   "type mismatch"
@@ -98,7 +98,7 @@
   (module
     (table $t 10 anyref)
     (func $type-length-empty-vs-i32
-      (table.fill $t (i32.const 1) (ref.null))
+      (table.fill $t (i32.const 1) (ref.null any))
     )
   )
   "type mismatch"
@@ -107,7 +107,7 @@
   (module
     (table $t 0 anyref)
     (func $type-index-f32-vs-i32
-      (table.fill $t (f32.const 1) (ref.null) (i32.const 1))
+      (table.fill $t (f32.const 1) (ref.null any) (i32.const 1))
     )
   )
   "type mismatch"
@@ -125,7 +125,7 @@
   (module
     (table $t 0 anyref)
     (func $type-length-f32-vs-i32
-      (table.fill $t (i32.const 1) (ref.null) (f32.const 1))
+      (table.fill $t (i32.const 1) (ref.null any) (f32.const 1))
     )
   )
   "type mismatch"
@@ -146,7 +146,7 @@
   (module
     (table $t 1 anyref)
     (func $type-result-empty-vs-num (result i32)
-      (table.fill $t (i32.const 0) (ref.null) (i32.const 1))
+      (table.fill $t (i32.const 0) (ref.null any) (i32.const 1))
     )
   )
   "type mismatch"
diff --git a/test/core/table_get.wast b/test/core/table_get.wast
index c95fce72..93aca18a 100644
--- a/test/core/table_get.wast
+++ b/test/core/table_get.wast
@@ -23,10 +23,10 @@
 
 (invoke "init" (ref.host 1))
 
-(assert_return (invoke "get-anyref" (i32.const 0)) (ref.null))
+(assert_return (invoke "get-anyref" (i32.const 0)) (ref.null any))
 (assert_return (invoke "get-anyref" (i32.const 1)) (ref.host 1))
 
-(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null))
+(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func))
 (assert_return (invoke "is_null-funcref" (i32.const 1)) (i32.const 0))
 (assert_return (invoke "is_null-funcref" (i32.const 2)) (i32.const 0))
 
diff --git a/test/core/table_grow.wast b/test/core/table_grow.wast
index 91fc096f..9bfa108a 100644
--- a/test/core/table_grow.wast
+++ b/test/core/table_grow.wast
@@ -14,9 +14,9 @@
 (assert_trap (invoke "set" (i32.const 0) (ref.host 2)) "out of bounds table access")
 (assert_trap (invoke "get" (i32.const 0)) "out of bounds table access")
 
-(assert_return (invoke "grow" (i32.const 1) (ref.null)) (i32.const 0))
+(assert_return (invoke "grow" (i32.const 1) (ref.null any)) (i32.const 0))
 (assert_return (invoke "size") (i32.const 1))
-(assert_return (invoke "get" (i32.const 0)) (ref.null))
+(assert_return (invoke "get" (i32.const 0)) (ref.null any))
 (assert_return (invoke "set" (i32.const 0) (ref.host 2)))
 (assert_return (invoke "get" (i32.const 0)) (ref.host 2))
 (assert_trap (invoke "set" (i32.const 1) (ref.host 2)) "out of bounds table access")
@@ -50,7 +50,7 @@
 (module
   (table $t 0 anyref)
   (func (export "grow") (param i32) (result i32)
-    (table.grow $t (ref.null) (local.get 0))
+    (table.grow $t (ref.null any) (local.get 0))
   )
 )
 
@@ -64,7 +64,7 @@
 (module
   (table $t 0 10 anyref)
   (func (export "grow") (param i32) (result i32)
-    (table.grow $t (ref.null) (local.get 0))
+    (table.grow $t (ref.null any) (local.get 0))
   )
 )
 
@@ -81,7 +81,7 @@
 (module
   (table $t 10 anyref)
   (func (export "grow") (param i32) (result i32)
-    (table.grow $t (ref.null) (local.get 0))
+    (table.grow $t (ref.null any) (local.get 0))
   )
   (elem declare func 1)
   (func (export "check-table-null") (param i32 i32) (result anyref)
@@ -100,9 +100,9 @@
   )
 )
 
-(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 9)) (ref.null))
+(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 9)) (ref.null any))
 (assert_return (invoke "grow" (i32.const 10)) (i32.const 10))
-(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 19)) (ref.null))
+(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 19)) (ref.null any))
 
 
 ;; Type errors
@@ -120,7 +120,7 @@
   (module
     (table $t 0 anyref)
     (func $type-size-empty-vs-i32 (result i32)
-      (table.grow $t (ref.null))
+      (table.grow $t (ref.null any))
     )
   )
   "type mismatch"
@@ -138,7 +138,7 @@
   (module
     (table $t 0 anyref)
     (func $type-size-f32-vs-i32 (result i32)
-      (table.grow $t (ref.null) (f32.const 1))
+      (table.grow $t (ref.null any) (f32.const 1))
     )
   )
   "type mismatch"
@@ -157,7 +157,7 @@
   (module
     (table $t 1 anyref)
     (func $type-result-i32-vs-empty
-      (table.grow $t (ref.null) (i32.const 0))
+      (table.grow $t (ref.null any) (i32.const 0))
     )
   )
   "type mismatch"
@@ -166,7 +166,7 @@
   (module
     (table $t 1 anyref)
     (func $type-result-i32-vs-f32 (result f32)
-      (table.grow $t (ref.null) (i32.const 0))
+      (table.grow $t (ref.null any) (i32.const 0))
     )
   )
   "type mismatch"
diff --git a/test/core/table_set.wast b/test/core/table_set.wast
index 848830e2..f5976c1e 100644
--- a/test/core/table_set.wast
+++ b/test/core/table_set.wast
@@ -26,22 +26,22 @@
   )
 )
 
-(assert_return (invoke "get-anyref" (i32.const 0)) (ref.null))
+(assert_return (invoke "get-anyref" (i32.const 0)) (ref.null any))
 (assert_return (invoke "set-anyref" (i32.const 0) (ref.host 1)))
 (assert_return (invoke "get-anyref" (i32.const 0)) (ref.host 1))
-(assert_return (invoke "set-anyref" (i32.const 0) (ref.null)))
-(assert_return (invoke "get-anyref" (i32.const 0)) (ref.null))
+(assert_return (invoke "set-anyref" (i32.const 0) (ref.null any)))
+(assert_return (invoke "get-anyref" (i32.const 0)) (ref.null any))
 
-(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null))
+(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func))
 (assert_return (invoke "set-funcref-from" (i32.const 0) (i32.const 1)))
 (assert_return (invoke "is_null-funcref" (i32.const 0)) (i32.const 0))
-(assert_return (invoke "set-funcref" (i32.const 0) (ref.null)))
-(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null))
+(assert_return (invoke "set-funcref" (i32.const 0) (ref.null func)))
+(assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func))
 
-(assert_trap (invoke "set-anyref" (i32.const 2) (ref.null)) "out of bounds")
-(assert_trap (invoke "set-funcref" (i32.const 3) (ref.null)) "out of bounds")
-(assert_trap (invoke "set-anyref" (i32.const -1) (ref.null)) "out of bounds")
-(assert_trap (invoke "set-funcref" (i32.const -1) (ref.null)) "out of bounds")
+(assert_trap (invoke "set-anyref" (i32.const 2) (ref.null any)) "out of bounds")
+(assert_trap (invoke "set-funcref" (i32.const 3) (ref.null func)) "out of bounds")
+(assert_trap (invoke "set-anyref" (i32.const -1) (ref.null any)) "out of bounds")
+(assert_trap (invoke "set-funcref" (i32.const -1) (ref.null func)) "out of bounds")
 
 (assert_trap (invoke "set-anyref" (i32.const 2) (ref.host 0)) "out of bounds")
 (assert_trap (invoke "set-funcref-from" (i32.const 3) (i32.const 1)) "out of bounds")
@@ -64,7 +64,7 @@
   (module
     (table $t 10 anyref)
     (func $type-index-empty-vs-i32
-      (table.set $t (ref.null))
+      (table.set $t (ref.null any))
     )
   )
   "type mismatch"
@@ -82,7 +82,7 @@
   (module
     (table $t 10 anyref)
     (func $type-size-f32-vs-i32
-      (table.set $t (f32.const 1) (ref.null))
+      (table.set $t (f32.const 1) (ref.null any))
     )
   )
   "type mismatch"
@@ -112,7 +112,7 @@
   (module
     (table $t 10 anyref)
     (func $type-result-empty-vs-num (result i32)
-      (table.set $t (i32.const 0) (ref.null))
+      (table.set $t (i32.const 0) (ref.null any))
     )
   )
   "type mismatch"
diff --git a/test/core/table_size.wast b/test/core/table_size.wast
index 5817104a..8c7cd1eb 100644
--- a/test/core/table_size.wast
+++ b/test/core/table_size.wast
@@ -10,16 +10,16 @@
   (func (export "size-t3") (result i32) (table.size $t3))
 
   (func (export "grow-t0") (param $sz i32)
-    (drop (table.grow $t0 (ref.null) (local.get $sz)))
+    (drop (table.grow $t0 (ref.null any) (local.get $sz)))
   )
   (func (export "grow-t1") (param $sz i32)
-    (drop (table.grow $t1 (ref.null) (local.get $sz)))
+    (drop (table.grow $t1 (ref.null any) (local.get $sz)))
   )
   (func (export "grow-t2") (param $sz i32)
-    (drop (table.grow $t2 (ref.null) (local.get $sz)))
+    (drop (table.grow $t2 (ref.null any) (local.get $sz)))
   )
   (func (export "grow-t3") (param $sz i32)
-    (drop (table.grow $t3 (ref.null) (local.get $sz)))
+    (drop (table.grow $t3 (ref.null any) (local.get $sz)))
   )
 )
 

From 009626d02a5c9c294d76382a40426966a44434de Mon Sep 17 00:00:00 2001
From: Andreas Rossberg 
Date: Tue, 18 Feb 2020 13:54:00 +0100
Subject: [PATCH 2/6] Remove funcref subtyping

---
 document/core/appendix/algorithm.rst          |  2 +-
 document/core/appendix/index-instructions.rst |  2 +-
 document/core/syntax/types.rst                |  6 +--
 document/core/valid/instructions.rst          |  6 ++-
 document/core/valid/types.rst                 | 12 ++----
 interpreter/script/js.ml                      | 38 ++++++++++-------
 interpreter/script/run.ml                     | 19 +++------
 interpreter/script/script.ml                  |  3 +-
 interpreter/syntax/types.ml                   |  8 ++--
 interpreter/syntax/values.ml                  |  2 +-
 interpreter/text/arrange.ml                   | 12 ++----
 interpreter/text/parser.mly                   |  4 +-
 interpreter/valid/valid.ml                    |  6 ++-
 proposals/reference-types/Overview.md         |  3 +-
 test/core/br_table.wast                       | 42 -------------------
 test/core/linking.wast                        |  5 ++-
 test/core/ref_func.wast                       |  4 +-
 test/core/select.wast                         | 21 ----------
 test/core/table-sub.wast                      | 10 -----
 test/core/table_grow.wast                     | 14 +++----
 20 files changed, 74 insertions(+), 145 deletions(-)

diff --git a/document/core/appendix/algorithm.rst b/document/core/appendix/algorithm.rst
index 9f39b995..a7e2087c 100644
--- a/document/core/appendix/algorithm.rst
+++ b/document/core/appendix/algorithm.rst
@@ -35,7 +35,7 @@ A simple subtyping check can be defined on these types.
      return t = Anyref || t = Funcref || t = Bot
 
    func matches(t1 : val_type, t2 : val_type) : bool =
-     return t1 = t2 || t1 = Bot || (is_ref(t1) && t2 = Anyref)
+     return t1 = t2 || t1 = Bot
 
 The algorithm uses two separate stacks: the *value stack* and the *control stack*.
 The former tracks the :ref:`types ` of operand values on the :ref:`stack `,
diff --git a/document/core/appendix/index-instructions.rst b/document/core/appendix/index-instructions.rst
index 9de22e97..8f5157fe 100644
--- a/document/core/appendix/index-instructions.rst
+++ b/document/core/appendix/index-instructions.rst
@@ -216,7 +216,7 @@ Instruction                             Binary Opcode       Type
 (reserved)                              :math:`\hex{CE}`                                                  
 (reserved)                              :math:`\hex{CF}`                                                  
 :math:`\REFNULL~t`                      :math:`\hex{D0}`    :math:`[] \to [t]`                          :ref:`validation `        :ref:`execution `
-:math:`\REFISNULL`                      :math:`\hex{D1}`    :math:`[\ANYREF] \to [\I32]`                :ref:`validation `     :ref:`execution `
+:math:`\REFISNULL`                      :math:`\hex{D1}`    :math:`[t] \to [\I32]`                      :ref:`validation `     :ref:`execution `
 :math:`\REFFUNC~x`                      :math:`\hex{D2}`    :math:`[] \to [\FUNCREF]`                   :ref:`validation `        :ref:`execution `
 :math:`\MEMORYINIT`                     :math:`\hex{FC08}`  :math:`[\I32~\I32~\I32] \to []`             :ref:`validation `     :ref:`execution `
 :math:`\DATADROP`                       :math:`\hex{FC09}`  :math:`[] \to []`                           :ref:`validation `       :ref:`execution `
diff --git a/document/core/syntax/types.rst b/document/core/syntax/types.rst
index 18de258d..60322dc1 100644
--- a/document/core/syntax/types.rst
+++ b/document/core/syntax/types.rst
@@ -54,13 +54,13 @@ Reference Types
 .. math::
    \begin{array}{llll}
    \production{reference type} & \reftype &::=&
-     \ANYREF ~|~ \FUNCREF \\
+     \FUNCREF ~|~ \ANYREF \\
    \end{array}
 
-The type |ANYREF| denotes the infinite union of all references, and thereby a :ref:`supertype ` of all other reference types.
-
 The type |FUNCREF| denotes the infinite union of all references to :ref:`functions `, regardless of their :ref:`function types `.
 
+The type |ANYREF| denotes the infinite union of all references to objects owned by the :ref:`embedder ` and that can be passed into WebAssembly under this type.
+
 Reference types are *opaque*, meaning that neither their size nor their bit pattern can be observed.
 Values of reference type can be stored in :ref:`tables `.
 
diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst
index 94efc2d7..abd9982c 100644
--- a/document/core/valid/instructions.rst
+++ b/document/core/valid/instructions.rst
@@ -177,18 +177,20 @@ Reference Instructions
      C \vdashinstr \REFNULL~t : [] \to [t]
    }
 
+.. note::
+   In future versions of WebAssembly, there may be reference types for which no null reference is allowed.
 
 .. _valid-ref.is_null:
 
 :math:`\REFISNULL`
 ..................
 
-* The instruction is valid with type :math:`[\ANYREF] \to [\I32]`.
+* The instruction is valid with type :math:`[\reftype] \to [\I32]` for any :ref:`reference type ` :math:`\reftype`.
 
 .. math::
    \frac{
    }{
-     C \vdashinstr \REFISNULL : [\ANYREF] \to [\I32]
+     C \vdashinstr \REFISNULL : [\reftype] \to [\I32]
    }
 
 .. _valid-ref.func:
diff --git a/document/core/valid/types.rst b/document/core/valid/types.rst
index e3212660..9ce9f17e 100644
--- a/document/core/valid/types.rst
+++ b/document/core/valid/types.rst
@@ -233,9 +233,7 @@ Reference Types
 
 A :ref:`reference type ` :math:`\reftype_1` matches a :ref:`reference type ` :math:`\reftype_2` if and only if:
 
-* Either both :math:`\reftype_1` and :math:`\reftype_2` are the same.
-
-* Or :math:`\reftype_2` is |ANYREF|.
+* Both :math:`\reftype_1` and :math:`\reftype_2` are the same.
 
 .. math::
    ~\\[-1ex]
@@ -243,11 +241,9 @@ A :ref:`reference type ` :math:`\reftype_1` matches a :ref:`refe
    }{
      \vdashreftypematch \reftype \matchesvaltype \reftype
    }
-   \qquad
-   \frac{
-   }{
-     \vdashreftypematch \reftype \matchesvaltype \ANYREF
-   }
+
+.. note::
+   In future versions of WebAssembly, additional subtyping relations may be added.
 
 
 .. index:: value type, number type, reference type
diff --git a/interpreter/script/js.ml b/interpreter/script/js.ml
index 312072f5..7d4219f3 100644
--- a/interpreter/script/js.ml
+++ b/interpreter/script/js.ml
@@ -22,7 +22,10 @@ function is_hostref(x) {
 function is_funcref(x) {
   return typeof x === "function" ? 1 : 0;
 }
-function eq_ref(x, y) {
+function eq_hostref(x, y) {
+  return x === y ? 1 : 0;
+}
+function eq_funcref(x, y) {
   return x === y ? 1 : 0;
 }
 
@@ -212,10 +215,11 @@ let lookup (mods : modules) x_opt name at =
 
 let subject_idx = 0l
 let hostref_idx = 1l
-let _is_hostref_idx = 2l
+let is_hostref_idx = 2l
 let is_funcref_idx = 3l
-let eq_ref_idx = 4l
-let subject_type_idx = 5l
+let eq_hostref_idx = 4l
+let _eq_funcref_idx = 5l
+let subject_type_idx = 6l
 
 let eq_of = function
   | I32Type -> Values.I32 I32Op.Eq
@@ -277,7 +281,7 @@ let assert_return ress ts at =
     | LitResult {it = Values.Ref (HostRef n); _} ->
       [ Const (Values.I32 n @@ at) @@ at;
         Call (hostref_idx @@ at) @@ at;
-        Call (eq_ref_idx @@ at)  @@ at;
+        Call (eq_hostref_idx @@ at)  @@ at;
         Test (Values.I32 I32Op.Eqz) @@ at;
         BrIf (0l @@ at) @@ at ]
     | LitResult {it = Values.Ref _; _} ->
@@ -302,11 +306,13 @@ let assert_return ress ts at =
         Compare (eq_of t') @@ at;
         Test (Values.I32 I32Op.Eqz) @@ at;
         BrIf (0l @@ at) @@ at ]
-    | RefResult ->
-      [ RefIsNull @@ at;
-        BrIf (0l @@ at) @@ at ]
-    | FuncResult ->
-      [ Call (is_funcref_idx @@ at) @@ at;
+    | RefResult t ->
+      let is_ref_idx =
+        match t with
+        | AnyRefType -> is_hostref_idx
+        | FuncRefType -> is_funcref_idx
+      in
+      [ Call (is_ref_idx @@ at) @@ at;
         Test (Values.I32 I32Op.Eqz) @@ at;
         BrIf (0l @@ at) @@ at ]
   in [], List.flatten (List.rev_map test ress)
@@ -318,8 +324,9 @@ let wrap item_name wrap_action wrap_assertion at =
     (FuncType ([], []) @@ at) ::
     (FuncType ([NumType I32Type], [RefType AnyRefType]) @@ at) ::
     (FuncType ([RefType AnyRefType], [NumType I32Type]) @@ at) ::
-    (FuncType ([RefType AnyRefType], [NumType I32Type]) @@ at) ::
+    (FuncType ([RefType FuncRefType], [NumType I32Type]) @@ at) ::
     (FuncType ([RefType AnyRefType; RefType AnyRefType], [NumType I32Type]) @@ at) ::
+    (FuncType ([RefType FuncRefType; RefType FuncRefType], [NumType I32Type]) @@ at) ::
     itypes
   in
   let imports =
@@ -330,8 +337,10 @@ let wrap item_name wrap_action wrap_assertion at =
        idesc = FuncImport (2l @@ at) @@ at} @@ at;
       {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "is_funcref";
        idesc = FuncImport (3l @@ at) @@ at} @@ at;
-      {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "eq_ref";
-       idesc = FuncImport (4l @@ at) @@ at} @@ at ]
+      {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "eq_hostref";
+       idesc = FuncImport (4l @@ at) @@ at} @@ at;
+      {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "eq_funcref";
+       idesc = FuncImport (5l @@ at) @@ at} @@ at ]
   in
   let item =
     List.fold_left
@@ -423,8 +432,7 @@ let of_result res =
     | Values.I32 _ | Values.I64 _ -> assert false
     | Values.F32 n | Values.F64 n -> of_nan n
     )
-  | RefResult -> "\"ref.any\""
-  | FuncResult -> "\"ref.func\""
+  | RefResult t -> "\"ref." ^ string_of_refed_type t ^ "\""
 
 let rec of_definition def =
   match def.it with
diff --git a/interpreter/script/run.ml b/interpreter/script/run.ml
index 58144476..afa658b6 100644
--- a/interpreter/script/run.ml
+++ b/interpreter/script/run.ml
@@ -254,8 +254,7 @@ let type_of_result r =
   match r with
   | LitResult v -> Values.type_of_value v.it
   | NanResult n -> Types.NumType (Values.type_of_num n.it)
-  | RefResult -> Types.RefType Types.AnyRefType
-  | FuncResult -> Types.RefType Types.FuncRefType
+  | RefResult t -> Types.RefType t
 
 let string_of_result r =
   match r with
@@ -265,8 +264,7 @@ let string_of_result r =
     | Values.I32 _ | Values.I64 _ -> assert false
     | Values.F32 n | Values.F64 n -> string_of_nan n
     )
-  | RefResult -> "ref"
-  | FuncResult -> "func"
+  | RefResult t -> Types.string_of_refed_type t
 
 let string_of_results = function
   | [r] -> string_of_result r
@@ -375,15 +373,10 @@ let assert_result at got expect =
           Int64.logand (F64.to_bits z) pos_nan <> pos_nan
         | _, _ -> false
         )
-      | RefResult ->
-        (match v with
-        | Ref (NullRef _) -> true
-        | Ref _ -> false
-        | _ -> true
-        )
-      | FuncResult ->
-        (match v with
-        | Ref (Instance.FuncRef _) -> false
+      | RefResult t ->
+        (match t, v with
+        | Types.AnyRefType, Ref (HostRef _)
+        | Types.FuncRefType, Ref (Instance.FuncRef _) -> false
         | _ -> true
         )
     ) got expect
diff --git a/interpreter/script/script.ml b/interpreter/script/script.ml
index 0c664c01..07812aed 100644
--- a/interpreter/script/script.ml
+++ b/interpreter/script/script.ml
@@ -22,8 +22,7 @@ type result = result' Source.phrase
 and result' =
   | LitResult of Values.value Source.phrase
   | NanResult of nanop
-  | RefResult
-  | FuncResult
+  | RefResult of Types.ref_type
 
 type assertion = assertion' Source.phrase
 and assertion' =
diff --git a/interpreter/syntax/types.ml b/interpreter/syntax/types.ml
index 60c595b8..6dbe6e1d 100644
--- a/interpreter/syntax/types.ml
+++ b/interpreter/syntax/types.ml
@@ -31,9 +31,7 @@ let match_num_type t1 t2 =
   t1 = t2
 
 let match_ref_type t1 t2 =
-  match t1, t2 with
-  | _, AnyRefType -> true
-  | _, _ -> t1 = t2
+  t1 = t2
 
 let match_value_type t1 t2 =
   match t1, t2 with
@@ -103,6 +101,10 @@ let string_of_ref_type = function
   | AnyRefType -> "anyref"
   | FuncRefType -> "funcref"
 
+let string_of_refed_type = function
+  | AnyRefType -> "any"
+  | FuncRefType -> "func"
+
 let string_of_value_type = function
   | NumType t -> string_of_num_type t
   | RefType t -> string_of_ref_type t
diff --git a/interpreter/syntax/values.ml b/interpreter/syntax/values.ml
index 1024eb05..03bbb88e 100644
--- a/interpreter/syntax/values.ml
+++ b/interpreter/syntax/values.ml
@@ -22,7 +22,7 @@ let type_of_num = function
   | F32 _ -> F32Type
   | F64 _ -> F64Type
 
-let type_of_ref' = ref (function NullRef t -> t | _ -> AnyRefType)
+let type_of_ref' = ref (function NullRef t -> t | _ -> assert false)
 let type_of_ref r = !type_of_ref' r
 
 let type_of_value = function
diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml
index 3df41b49..656793c7 100644
--- a/interpreter/text/arrange.ml
+++ b/interpreter/text/arrange.ml
@@ -55,12 +55,9 @@ let break_string s =
 
 (* Types *)
 
-let ref_kind = function
-  | AnyRefType -> "any"
-  | FuncRefType -> "func"
-
 let num_type t = string_of_num_type t
 let ref_type t = string_of_ref_type t
+let refed_type t = string_of_refed_type t
 let value_type t = string_of_value_type t
 
 let decls kind ts = tab kind (atom value_type) ts
@@ -266,7 +263,7 @@ let rec instr e =
     | MemoryCopy -> "memory.copy", []
     | MemoryInit x -> "memory.init " ^ var x, []
     | DataDrop x -> "data.drop " ^ var x, []
-    | RefNull t -> "ref.null", [Atom (ref_kind t)]
+    | RefNull t -> "ref.null", [Atom (refed_type t)]
     | RefIsNull -> "ref.is_null", []
     | RefFunc x -> "ref.func " ^ var x, []
     | Const n -> constop n ^ " " ^ num n, []
@@ -435,7 +432,7 @@ let value v =
   | Num (Values.I64 i) -> Node ("i64.const " ^ I64.to_string_s i, [])
   | Num (Values.F32 z) -> Node ("f32.const " ^ F32.to_string z, [])
   | Num (Values.F64 z) -> Node ("f64.const " ^ F64.to_string z, [])
-  | Ref (NullRef t) -> Node ("ref.null", [Atom (ref_kind t)])
+  | Ref (NullRef t) -> Node ("ref.null", [Atom (refed_type t)])
   | Ref (HostRef n) -> Node ("ref.host " ^ Int32.to_string n, [])
   | _ -> assert false
 
@@ -487,8 +484,7 @@ let result res =
     | Values.F32 n -> Node ("f32.const " ^ nan n, [])
     | Values.F64 n -> Node ("f64.const " ^ nan n, [])
     )
-  | RefResult -> Node ("ref", [])
-  | FuncResult -> Node ("ref.func", [])
+  | RefResult t -> Node ("ref." ^ refed_type t, [])
 
 let assertion mode ass =
   match ass.it with
diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly
index 10b07024..2781fbe9 100644
--- a/interpreter/text/parser.mly
+++ b/interpreter/text/parser.mly
@@ -999,8 +999,8 @@ const_list :
 result :
   | const { LitResult $1 @@ at () }
   | LPAR CONST NAN RPAR { NanResult (nanop $2 ($3 @@ ati 3)) @@ at () }
-  | LPAR REF_ANY RPAR { RefResult @@ at () }
-  | LPAR REF_FUNC RPAR { FuncResult @@ at () }
+  | LPAR REF_ANY RPAR { RefResult AnyRefType @@ at () }
+  | LPAR REF_FUNC RPAR { RefResult FuncRefType @@ at () }
 
 result_list :
   | /* empty */ { [] }
diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml
index 69122001..11fd69f0 100644
--- a/interpreter/valid/valid.ml
+++ b/interpreter/valid/valid.ml
@@ -346,7 +346,11 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type =
     [] --> [RefType t]
 
   | RefIsNull ->
-    [RefType AnyRefType] --> [NumType I32Type]
+    let t = peek 0 s in
+    require (is_ref_type t) e.at
+      ("type mismatch: instruction requires reference type" ^
+       " but stack has " ^ string_of_value_type t);
+    [t] --> [NumType I32Type]
 
   | RefFunc x ->
     let _ft = func c x in
diff --git a/proposals/reference-types/Overview.md b/proposals/reference-types/Overview.md
index fea602cf..c5395984 100644
--- a/proposals/reference-types/Overview.md
+++ b/proposals/reference-types/Overview.md
@@ -58,8 +58,7 @@ Typing extensions:
   - `elemtype ::= `
 
 * Introduce a simple subtype relation between reference types.
-  - reflexive transitive closure of the following rules
-  - `t <: anyref` for all reftypes `t`
+  - reflexive transitive closure of rules to come
 
 
 New/extended instructions:
diff --git a/test/core/br_table.wast b/test/core/br_table.wast
index 7589d72a..566fab30 100644
--- a/test/core/br_table.wast
+++ b/test/core/br_table.wast
@@ -1251,35 +1251,6 @@
     )
   )
 
-  (func (export "meet-funcref-1") (param i32) (result anyref)
-    (block $l1 (result anyref)
-      (block $l2 (result funcref)
-        (br_table $l1 $l1 $l2 (table.get 0 (i32.const 0)) (local.get 0))
-      )
-    )
-  )
-  (func (export "meet-funcref-2") (param i32) (result anyref)
-    (block $l1 (result anyref)
-      (block $l2 (result funcref)
-        (br_table $l2 $l2 $l1 (table.get 0 (i32.const 0)) (local.get 0))
-      )
-    )
-  )
-  (func (export "meet-funcref-3") (param i32) (result anyref)
-    (block $l1 (result anyref)
-      (block $l2 (result funcref)
-        (br_table $l2 $l1 $l2 (table.get 0 (i32.const 0)) (local.get 0))
-      )
-    )
-  )
-  (func (export "meet-funcref-4") (param i32) (result anyref)
-    (block $l1 (result anyref)
-      (block $l2 (result funcref)
-        (br_table $l1 $l2 $l1 (table.get 0 (i32.const 0)) (local.get 0))
-      )
-    )
-  )
-
   (func (export "meet-bottom")
     (block (result f64)
       (block (result f32)
@@ -1478,19 +1449,6 @@
 (assert_return (invoke "meet-anyref" (i32.const 1) (ref.host 1)) (ref.host 1))
 (assert_return (invoke "meet-anyref" (i32.const 2) (ref.host 1)) (ref.host 1))
 
-(assert_return (invoke "meet-funcref-1" (i32.const 0)) (ref.func))
-(assert_return (invoke "meet-funcref-1" (i32.const 1)) (ref.func))
-(assert_return (invoke "meet-funcref-1" (i32.const 2)) (ref.func))
-(assert_return (invoke "meet-funcref-2" (i32.const 0)) (ref.func))
-(assert_return (invoke "meet-funcref-2" (i32.const 1)) (ref.func))
-(assert_return (invoke "meet-funcref-2" (i32.const 2)) (ref.func))
-(assert_return (invoke "meet-funcref-3" (i32.const 0)) (ref.func))
-(assert_return (invoke "meet-funcref-3" (i32.const 1)) (ref.func))
-(assert_return (invoke "meet-funcref-3" (i32.const 2)) (ref.func))
-(assert_return (invoke "meet-funcref-4" (i32.const 0)) (ref.func))
-(assert_return (invoke "meet-funcref-4" (i32.const 1)) (ref.func))
-(assert_return (invoke "meet-funcref-4" (i32.const 2)) (ref.func))
-
 (assert_invalid
   (module (func $type-arg-void-vs-num (result i32)
     (block (br_table 0 (i32.const 1)) (i32.const 1))
diff --git a/test/core/linking.wast b/test/core/linking.wast
index 2b51032d..38366425 100644
--- a/test/core/linking.wast
+++ b/test/core/linking.wast
@@ -103,7 +103,6 @@
 
 (module $Mref_im
   (global (import "Mref_ex" "g-const-func") funcref)
-  (global (import "Mref_ex" "g-const-func") anyref)
   (global (import "Mref_ex" "g-const-any") anyref)
 
   (global (import "Mref_ex" "g-var-func") (mut funcref))
@@ -114,6 +113,10 @@
   (module (global (import "Mref_ex" "g-const-any") funcref))
   "incompatible import type"
 )
+(assert_unlinkable
+  (module (global (import "Mref_ex" "g-const-func") anyref))
+  "incompatible import type"
+)
 
 
 (assert_unlinkable
diff --git a/test/core/ref_func.wast b/test/core/ref_func.wast
index e9033a3b..2e811a93 100644
--- a/test/core/ref_func.wast
+++ b/test/core/ref_func.wast
@@ -9,8 +9,8 @@
     (i32.add (local.get $x) (i32.const 1))
   )
 
-  (global anyref (ref.func $f))
-  (global anyref (ref.func $g))
+  (global anyref (ref.null any))
+  (global anyref (ref.null any))
   (global funcref (ref.func $f))
   (global funcref (ref.func $g))
   (global $v (mut funcref) (ref.func $f))
diff --git a/test/core/select.wast b/test/core/select.wast
index 41958aed..c11f1261 100644
--- a/test/core/select.wast
+++ b/test/core/select.wast
@@ -36,21 +36,6 @@
     (select (result anyref) (local.get 0) (local.get 1) (local.get 2))
   )
 
-  (func (export "join-funcref") (param i32) (result anyref)
-    (select (result funcref)
-      (table.get $tab (i32.const 0))
-      (ref.null func)
-      (local.get 0)
-    )
-  )
-  (func (export "join-anyref") (param i32) (param anyref) (result anyref)
-    (select (result anyref)
-      (table.get $tab (i32.const 0))
-      (local.get 1)
-      (local.get 0)
-    )
-  )
-
   ;; Check that both sides of the select are evaluated
   (func (export "select-trap-left") (param $cond i32) (result i32)
     (select (unreachable) (i32.const 0) (local.get $cond))
@@ -272,12 +257,6 @@
 (assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan) (i32.const 0)) (f64.const nan))
 (assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan:0x20304) (i32.const 0)) (f64.const nan:0x20304))
 
-(assert_return (invoke "join-funcref" (i32.const 1)) (ref.func))
-(assert_return (invoke "join-funcref" (i32.const 0)) (ref.null func))
-
-(assert_return (invoke "join-anyref" (i32.const 1) (ref.host 1)) (ref.func))
-(assert_return (invoke "join-anyref" (i32.const 0) (ref.host 1)) (ref.host 1))
-
 (assert_trap (invoke "select-trap-left" (i32.const 1)) "unreachable")
 (assert_trap (invoke "select-trap-left" (i32.const 0)) "unreachable")
 (assert_trap (invoke "select-trap-right" (i32.const 1)) "unreachable")
diff --git a/test/core/table-sub.wast b/test/core/table-sub.wast
index 66f18310..780b38f7 100644
--- a/test/core/table-sub.wast
+++ b/test/core/table-sub.wast
@@ -1,13 +1,3 @@
-(module
-  (table $t1 10 anyref)
-  (table $t2 10 funcref)
-  (elem $el funcref)
-  (func $f
-    (table.init $t1 $el (i32.const 0) (i32.const 1) (i32.const 2))
-    (table.copy $t1 $t2 (i32.const 0) (i32.const 1) (i32.const 2))
-  )
-)
-
 (assert_invalid
   (module
     (table $t1 10 funcref)
diff --git a/test/core/table_grow.wast b/test/core/table_grow.wast
index 9bfa108a..7ba1be9e 100644
--- a/test/core/table_grow.wast
+++ b/test/core/table_grow.wast
@@ -37,7 +37,7 @@
 
 ;; Reject growing to size outside i32 value range
 (module
-  (table $t 0x10 anyref)
+  (table $t 0x10 funcref)
   (elem declare func $f)
   (func $f (export "grow") (result i32)
     (table.grow $t (ref.func $f) (i32.const 0xffff_fff0))
@@ -79,13 +79,13 @@
 
 
 (module
-  (table $t 10 anyref)
+  (table $t 10 funcref)
   (func (export "grow") (param i32) (result i32)
-    (table.grow $t (ref.null any) (local.get 0))
+    (table.grow $t (ref.null func) (local.get 0))
   )
   (elem declare func 1)
-  (func (export "check-table-null") (param i32 i32) (result anyref)
-    (local anyref)
+  (func (export "check-table-null") (param i32 i32) (result funcref)
+    (local funcref)
     (local.set 2 (ref.func 1))
     (block
       (loop
@@ -100,9 +100,9 @@
   )
 )
 
-(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 9)) (ref.null any))
+(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 9)) (ref.null func))
 (assert_return (invoke "grow" (i32.const 10)) (i32.const 10))
-(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 19)) (ref.null any))
+(assert_return (invoke "check-table-null" (i32.const 0) (i32.const 19)) (ref.null func))
 
 
 ;; Type errors

From c594220b1e8ede3db4ffcfad14900e7deaa683c1 Mon Sep 17 00:00:00 2001
From: Andreas Rossberg 
Date: Thu, 2 Apr 2020 15:14:51 +0200
Subject: [PATCH 3/6] Completely remove subtyping

---
 document/core/appendix/algorithm.rst   |  46 +++++------
 document/core/appendix/index-rules.rst |   4 -
 document/core/appendix/properties.rst  |  24 ++----
 document/core/exec/runtime.rst         |   4 +-
 document/core/syntax/types.rst         |   8 +-
 document/core/util/macros.def          |   7 --
 document/core/valid/instructions.rst   |  46 ++++-------
 document/core/valid/modules.rst        |  10 +--
 document/core/valid/types.rst          | 106 +------------------------
 interpreter/binary/encode.ml           |   1 -
 interpreter/exec/eval.ml               |   2 +-
 interpreter/host/spectest.ml           |   1 -
 interpreter/runtime/global.ml          |   4 +-
 interpreter/runtime/table.ml           |   2 +-
 interpreter/script/js.ml               |   1 -
 interpreter/script/run.ml              |   2 +-
 interpreter/syntax/types.ml            |  57 +++++--------
 interpreter/syntax/values.ml           |   1 -
 interpreter/valid/valid.ml             |  58 +++++++-------
 proposals/reference-types/Overview.md  |  18 ++++-
 test/core/br_table.wast                |  13 +--
 21 files changed, 125 insertions(+), 290 deletions(-)

diff --git a/document/core/appendix/algorithm.rst b/document/core/appendix/algorithm.rst
index a7e2087c..df2e5a87 100644
--- a/document/core/appendix/algorithm.rst
+++ b/document/core/appendix/algorithm.rst
@@ -22,20 +22,16 @@ Data Structures
 ~~~~~~~~~~~~~~~
 
 Types are representable as an enumeration.
-A simple subtyping check can be defined on these types.
 
 .. code-block:: pseudo
 
-   type val_type = I32 | I64 | F32 | F64 | Anyref | Funcref | Bot
+   type val_type = I32 | I64 | F32 | F64 | Anyref | Funcref
 
    func is_num(t : val_type) : bool =
-     return t = I32 || t = I64 || t = F32 || t = F64 || t = Bot
+     return t = I32 || t = I64 || t = F32 || t = F64
 
    func is_ref(t : val_type) : bool =
-     return t = Anyref || t = Funcref || t = Bot
-
-   func matches(t1 : val_type, t2 : val_type) : bool =
-     return t1 = t2 || t1 = Bot
+     return t = Anyref || t = Funcref
 
 The algorithm uses two separate stacks: the *value stack* and the *control stack*.
 The former tracks the :ref:`types ` of operand values on the :ref:`stack `,
@@ -43,7 +39,7 @@ the latter surrounding :ref:`structured control instructions `.
+For each value, the value stack records its :ref:`value type `, or :code:`Unknown` when the type is not known.
+
 
 For each entered block, the control stack records a *control frame* with the type of the associated :ref:`label ` (used to type-check branches), the result type of the block (used to check its result), the height of the operand stack at the start of the block (used to check that operands do not underflow the current block), and a flag recording whether the remainder of the block is unreachable (used to handle :ref:`stack-polymorphic ` typing after branches).
 
@@ -72,17 +69,19 @@ However, these variables are not manipulated directly by the main checking funct
 
 .. code-block:: pseudo
 
-   func push_val(type : val_type) =
+   func push_val(type : val_type | Unknown) =
      vals.push(type)
 
-   func pop_val() : val_type =
-     if (vals.size() = ctrls[0].height && ctrls[0].unreachable) return Bot
+   func pop_val() : val_type | Unknown =
+     if (vals.size() = ctrls[0].height && ctrls[0].unreachable) return Unknown
      error_if(vals.size() = ctrls[0].height)
      return vals.pop()
 
-   func pop_val(expect : val_type) : val_type =
+   func pop_val(expect : val_type | Unknown) : val_type | Unknown =
      let actual = pop_val()
-     error_if(not matches(actual, expect))
+     if (actual = Unknown) return expect
+     if (expect = Unknown) return actual
+     error_if(actual =/= expect)
      return actual
 
    func push_vals(types : list(val_type)) = foreach (t in types) push_val(t)
@@ -96,10 +95,10 @@ Pushing an operand value simply pushes the respective type to the value stack.
 Popping an operand value checks that the value stack does not underflow the current block and then removes one type.
 But first, a special case is handled where the block contains no known values, but has been marked as unreachable.
 That can occur after an unconditional branch, when the stack is typed :ref:`polymorphically `.
-In that case, the :code:`Bot` type is returned, because that is a *principal* choice trivially satisfying all use constraints.
+In that case, an unknown type is returned.
 
 A second function for popping an operand value takes an expected type, which the actual operand type is checked against.
-The types may differ by subtyping, including the case where the actual type is :code:`Bot`, and thereby matches unconditionally.
+The types may differ in case one of them is Unknown.
 The function returns the actual type popped from the stack.
 
 Finally, there are accumulative functions for pushing or popping multiple operand types.
@@ -142,7 +141,7 @@ In that case, all existing operand types are purged from the value stack, in ord
 .. note::
    Even with the unreachable flag set, consecutive operands are still pushed to and popped from the operand stack.
    That is necessary to detect invalid :ref:`examples ` like :math:`(\UNREACHABLE~(\I32.\CONST)~\I64.\ADD)`.
-   However, a polymorphic stack cannot underflow, but instead generates :code:`Bot` types as needed.
+   However, a polymorphic stack cannot underflow, but instead generates :code:`Unknown` types as needed.
 
 
 .. index:: opcode
@@ -174,8 +173,8 @@ Other instructions are checked in a similar manner.
          let t1 = pop_val()
          let t2 = pop_val()
          error_if(not (is_num(t1) && is_num(t2)))
-         error_if(t1 =/= t2 && t1 =/= Bot && t2 =/= Bot)
-         push_val(if (t1 = Bot) t2 else t1)
+         error_if(t1 =/= t2 && t1 =/= Unknown && t2 =/= Unknown)
+         push_val(if (t1 = Unknown) t2 else t1)
 
        case (select t)
          pop_val(I32)
@@ -216,14 +215,11 @@ Other instructions are checked in a similar manner.
  Β Β    Β Β Β push_vals(ctrls[n].label_types)
 
     Β Β Β case (br_table n* m)
-         pop_val(I32)
  Β Β    Β Β Β error_if(ctrls.size() < m)
-         let arity = ctrls[m].label_types.size()
  Β Β Β Β Β    foreach (n in n*)
- Β Β Β Β Β Β Β    error_if(ctrls.size() < n)
- Β Β Β Β Β Β Β    error_if(ctrls[n].label_types.size() =/= arity)
-           push_vals(pop_vals(ctrls[n].label_types))
-         pop_vals(ctrls[m].label_types)
+ Β Β Β Β Β Β Β    error_if(ctrls.size() < n || ctrls[n].label_types =/= ctrls[m].label_types)
+         pop_val(I32)
+ Β Β Β Β Β    pop_vals(ctrls[m].label_types)
  Β    Β Β Β Β unreachable()
 
 .. note::
diff --git a/document/core/appendix/index-rules.rst b/document/core/appendix/index-rules.rst
index 525fe139..1beabe35 100644
--- a/document/core/appendix/index-rules.rst
+++ b/document/core/appendix/index-rules.rst
@@ -82,10 +82,6 @@ Matching
 ===============================================  ===============================================================================
 Construct                                        Judgement
 ===============================================  ===============================================================================
-:ref:`Number type `               :math:`\vdashnumtypematch \numtype_1 \matchesvaltype \numtype_2`
-:ref:`Reference type `            :math:`\vdashreftypematch \reftype_1 \matchesvaltype \reftype_2`
-:ref:`Value type `                :math:`\vdashvaltypematch \valtype_1 \matchesvaltype \valtype_2`
-:ref:`Result type `            :math:`\vdashresulttypematch [t_1^?] \matchesresulttype [t_2^?]`
 :ref:`External type `          :math:`\vdashexterntypematch \externtype_1 \matchesexterntype \externtype_2`
 :ref:`Limits `                     :math:`\vdashlimitsmatch \limits_1 \matcheslimits \limits_2`
 ===============================================  ===============================================================================
diff --git a/document/core/appendix/properties.rst b/document/core/appendix/properties.rst
index 76e47b74..35abaddd 100644
--- a/document/core/appendix/properties.rst
+++ b/document/core/appendix/properties.rst
@@ -215,9 +215,7 @@ Module instances are classified by *module contexts*, which are regular :ref:`co
 
 * For each :ref:`reference ` :math:`\reff_i` in the table's elements :math:`\reff^n`:
 
-  * The :ref:`reference ` :math:`\reff_i` must be :ref:`valid ` with some :ref:`reference type ` :math:`t'_i`.
-
-  * The :ref:`reference type ` :math:`t'_i` must :ref:`match ` the :ref:`reference type ` :math:`t`.
+  * The :ref:`reference ` :math:`\reff_i` must be :ref:`valid ` with :ref:`reference type ` :math:`t`.
 
 * Then the table instance is valid with :ref:`table type ` :math:`\limits~t`.
 
@@ -227,9 +225,7 @@ Module instances are classified by *module contexts*, which are regular :ref:`co
      \qquad
      n = \limits.\LMIN
      \qquad
-     (S \vdash \reff : t')^n
-     \qquad
-     (\vdashreftypematch t' \matchesvaltype t)^n
+     (S \vdash \reff : t)^n
    }{
      S \vdashtableinst \{ \TITYPE~(\limits~t), \TIELEM~\reff^n \} : \limits~t
    }
@@ -265,9 +261,7 @@ Module instances are classified by *module contexts*, which are regular :ref:`co
 
 * The :ref:`global type ` :math:`\mut~t` must be :ref:`valid `.
 
-* The :ref:`value ` :math:`\val` must be :ref:`valid ` with some :ref:`value type ` :math:`t'`.
-
-* The :ref:`value type ` :math:`t'` must :ref:`match ` the :ref:`value type ` :math:`t`.
+* The :ref:`value ` :math:`\val` must be :ref:`valid ` with :ref:`value type ` :math:`t`.
 
 * Then the global instance is valid with :ref:`global type ` :math:`\mut~t`.
 
@@ -275,9 +269,7 @@ Module instances are classified by *module contexts*, which are regular :ref:`co
    \frac{
      \vdashglobaltype \mut~t \ok
      \qquad
-     S \vdashval \val : t'
-     \qquad
-     \vdashvaltypematch t' \matchesvaltype t
+     S \vdashval \val : t
    }{
      S \vdashglobalinst \{ \GITYPE~(\mut~t), \GIVALUE~\val \} : \mut~t
    }
@@ -291,17 +283,13 @@ Module instances are classified by *module contexts*, which are regular :ref:`co
 
 * For each :ref:`reference ` :math:`\reff_i` in the elements :math:`\reff^n`:
 
-  * The :ref:`reference ` :math:`\reff_i` must be :ref:`valid ` with some :ref:`reference type ` :math:`t'_i`.
-
-  * The :ref:`reference type ` :math:`t'_i` must :ref:`match ` the :ref:`reference type ` :math:`t`.
+  * The :ref:`reference ` :math:`\reff_i` must be :ref:`valid ` with :ref:`reference type ` :math:`t`.
 
 * Then the table instance is valid.
 
 .. math::
    \frac{
-     (S \vdash \reff : t')^\ast
-     \qquad
-     (\vdashreftypematch t' \matchesvaltype t)^\ast
+     (S \vdash \reff : t)^\ast
    }{
      S \vdasheleminst \{ \EITYPE~t, \EIELEM~\reff^\ast \} \ok
    }
diff --git a/document/core/exec/runtime.rst b/document/core/exec/runtime.rst
index a0f13d77..fd8dbed7 100644
--- a/document/core/exec/runtime.rst
+++ b/document/core/exec/runtime.rst
@@ -274,7 +274,7 @@ It records its :ref:`type ` and holds a vector of :ref:`refere
 
 Table elements can be mutated through :ref:`table instructions `, the execution of an active :ref:`element segment `, or by external means provided by the :ref:`embedder `.
 
-It is an invariant of the semantics that all table elements have a type :ref:`matching ` the element type of :math:`\tabletype`.
+It is an invariant of the semantics that all table elements have a type equal to the element type of :math:`\tabletype`.
 It also is an invariant that the length of the element vector never exceeds the maximum size of :math:`\tabletype`, if present.
 
 
@@ -322,7 +322,7 @@ It records its :ref:`type ` and holds an individual :ref:`val
 
 The value of mutable globals can be mutated through :ref:`variable instructions ` or by external means provided by the :ref:`embedder `.
 
-It is an invariant of the semantics that the value has a type :ref:`matching ` the :ref:`value type ` of :math:`\globaltype`.
+It is an invariant of the semantics that the value has a type equal to the :ref:`value type ` of :math:`\globaltype`.
 
 
 .. index:: ! element instance, element segment, embedder, element expression
diff --git a/document/core/syntax/types.rst b/document/core/syntax/types.rst
index 60322dc1..3c2616cb 100644
--- a/document/core/syntax/types.rst
+++ b/document/core/syntax/types.rst
@@ -74,16 +74,12 @@ Value Types
 ~~~~~~~~~~~
 
 *Value types* classify the individual values that WebAssembly code can compute with and the values that a variable accepts.
-They are either :ref:`number types `, :ref:`reference type `, or the unique *bottom type*, written :math:`\BOT`.
-
-The type :math:`\BOT` is a :ref:`subtype ` of all other types.
-By virtue of being representable in neither the :ref:`binary format ` nor the :ref:`text format `, it cannot be used in a program;
-it only occurs during :ref:`validation `.
+They are either :ref:`number types ` or :ref:`reference types `.
 
 .. math::
    \begin{array}{llll}
    \production{value type} & \valtype &::=&
-     \numtype ~|~ \reftype ~|~ \BOT \\
+     \numtype ~|~ \reftype \\
    \end{array}
 
 Conventions
diff --git a/document/core/util/macros.def b/document/core/util/macros.def
index 8142139b..5a87db3d 100644
--- a/document/core/util/macros.def
+++ b/document/core/util/macros.def
@@ -767,8 +767,6 @@
 
 .. |ok| mathdef:: \mathrel{\mbox{ok}}
 .. |const| mathdef:: \xref{valid/instructions}{valid-constant}{\mathrel{\mbox{const}}}
-.. |matchesvaltype| mathdef:: \xref{valid/types}{match-valtype}{\leq}
-.. |matchesresulttype| mathdef:: \xref{valid/types}{match-resulttype}{\leq}
 
 
 .. Contexts
@@ -795,11 +793,6 @@
 .. |vdashglobaltype| mathdef:: \xref{valid/types}{valid-globaltype}{\vdash}
 .. |vdashexterntype| mathdef:: \xref{valid/types}{valid-externtype}{\vdash}
 
-.. |vdashnumtypematch| mathdef:: \xref{valid/types}{match-numtype}{\vdash}
-.. |vdashreftypematch| mathdef:: \xref{valid/types}{match-reftype}{\vdash}
-.. |vdashvaltypematch| mathdef:: \xref{valid/types}{match-valtype}{\vdash}
-.. |vdashresulttypematch| mathdef:: \xref{valid/types}{match-resulttype}{\vdash}
-
 .. |vdashinstr| mathdef:: \xref{valid/instructions}{valid-instr}{\vdash}
 .. |vdashinstrseq| mathdef:: \xref{valid/instructions}{valid-instr-seq}{\vdash}
 .. |vdashexpr| mathdef:: \xref{valid/instructions}{valid-expr}{\vdash}
diff --git a/document/core/valid/instructions.rst b/document/core/valid/instructions.rst
index abd9982c..0833cae4 100644
--- a/document/core/valid/instructions.rst
+++ b/document/core/valid/instructions.rst
@@ -253,7 +253,7 @@ Parametric Instructions
 
 * Else:
 
-  * The instruction is valid with type :math:`[t~t~\I32] \to [t]`, for any :ref:`value type ` :math:`t` that :ref:`matches ` some :ref:`number type `.
+  * The instruction is valid with type :math:`[t~t~\I32] \to [t]`, for any :ref:`number type ` :math:`t`.
 
 .. math::
    \frac{
@@ -262,7 +262,7 @@ Parametric Instructions
    }
    \qquad
    \frac{
-     \vdashvaltypematch t \matchesvaltype \numtype
+     t = \numtype
    }{
      C \vdashinstr \SELECT : [t~t~\I32] \to [t]
    }
@@ -490,17 +490,15 @@ Table Instructions
 
 * Let :math:`\limits_2~t_2` be the :ref:`table type ` :math:`C.\CTABLES[y]`.
 
-* The :ref:`reference type ` :math:`t_2` must :ref:`match ` :math:`t_1`.
+* The :ref:`reference type ` :math:`t_1` must be the same as :math:`t_2`.
 
 * Then the instruction is valid with type :math:`[\I32~\I32~\I32] \to []`.
 
 .. math::
    \frac{
-     C.\CTABLES[x] = \limits_1~t_1
+     C.\CTABLES[x] = \limits_1~t
      \qquad
-     C.\CTABLES[x] = \limits_2~t_2
-     \qquad
-     \vdashreftypematch t_2 \matchesvaltype t_1
+     C.\CTABLES[x] = \limits_2~t
    }{
      C \vdashinstr \TABLECOPY~x~y : [\I32~\I32~\I32] \to []
    }
@@ -519,17 +517,15 @@ Table Instructions
 
 * Let :math:`t_2` be the :ref:`reference type ` :math:`C.\CELEMS[y]`.
 
-* The :ref:`reference type ` :math:`t_2` must :ref:`match ` :math:`t_1`.
+* The :ref:`reference type ` :math:`t_1` must be the same as :math:`t_2`.
 
 * Then the instruction is valid with type :math:`[\I32~\I32~\I32] \to []`.
 
 .. math::
    \frac{
-     C.\CTABLES[x] = \limits_1~t_1
-     \qquad
-     C.\CELEMS[y] = t_2
+     C.\CTABLES[x] = \limits_1~t
      \qquad
-     \vdashreftypematch t_2 \matchesvaltype t_1
+     C.\CELEMS[y] = t
    }{
      C \vdashinstr \TABLEINIT~x~y : [\I32~\I32~\I32] \to []
    }
@@ -928,20 +924,16 @@ Control Instructions
 * For all :math:`l_i` in :math:`l^\ast`,
   the label :math:`C.\CLABELS[l_i]` must be defined in the context.
 
-* There must be a :ref:`result type ` :math:`[t^?]`, such that:
-
-  * The result type :math:`[t^?]` :ref:`matches ` :math:`C.\CLABELS[l_N]`.
-
-  * For all :math:`l_i` in :math:`l^\ast`,
-    the result type :math:`[t^?]` :ref:`matches ` :math:`C.\CLABELS[l_i]`.
+* For all :math:`l_i` in :math:`l^\ast`,
+  :math:`C.\CLABELS[l_i]` must be :math:`[t^?]`.
 
 * Then the instruction is valid with type :math:`[t_1^\ast~t^?~\I32] \to [t_2^\ast]`, for any sequences of :ref:`value types ` :math:`t_1^\ast` and :math:`t_2^\ast`.
 
 .. math::
    \frac{
-     (\vdashresulttypematch [t^?] \matchesresulttype C.\CLABELS[l])^\ast
+     (C.\CLABELS[l] = [t^?])^\ast
      \qquad
-     \vdashresulttypematch [t^?] \matchesresulttype C.\CLABELS[l_N]
+     C.\CLABELS[l_N] = [t^?]
    }{
      C \vdashinstr \BRTABLE~l^\ast~l_N : [t_1^\ast~t^?~\I32] \to [t_2^\ast]
    }
@@ -1004,7 +996,7 @@ Control Instructions
 
 * Let :math:`\limits~t` be the :ref:`table type ` :math:`C.\CTABLES[x]`.
 
-* The :ref:`reference type ` :math:`t` must :ref:`match ` type |FUNCREF|.
+* The :ref:`reference type ` :math:`t` must be |FUNCREF|.
 
 * The type :math:`C.\CTYPES[y]` must be defined in the context.
 
@@ -1014,9 +1006,7 @@ Control Instructions
 
 .. math::
    \frac{
-     C.\CTABLES[x] = \limits~t
-     \qquad
-     \vdashvaltypematch t \leq \FUNCREF
+     C.\CTABLES[x] = \limits~\FUNCREF
      \qquad
      C.\CTYPES[y] = [t_1^\ast] \to [t_2^\ast]
    }{
@@ -1056,17 +1046,13 @@ Non-empty Instruction Sequence: :math:`\instr^\ast~\instr_N`
   for some sequences of :ref:`value types ` :math:`t^\ast` and :math:`t_3^\ast`.
 
 * There must be a sequence of :ref:`value types ` :math:`t_0^\ast`,
-  such that :math:`t_2^\ast = t_0^\ast~{t'}^\ast` where the type sequence :math:`{t'}^\ast` is as long as :math:`t^\ast`.
-
-* For each :ref:`value type ` :math:`t'_i` in :math:`{t'}^\ast` and corresponding type :math:`t_i` in :math:`t^\ast`, the type :math:`t'_i` must :ref:`match ` :math:`t_i`.
+  such that :math:`t_2^\ast = t_0^\ast~t^\ast`.
 
 * Then the combined instruction sequence is valid with type :math:`[t_1^\ast] \to [t_0^\ast~t_3^\ast]`.
 
 .. math::
    \frac{
-     C \vdashinstrseq \instr^\ast : [t_1^\ast] \to [t_0^\ast~{t'}^\ast]
-     \qquad
-     (\vdashvaltypematch t' \matchesvaltype t)^\ast
+     C \vdashinstrseq \instr^\ast : [t_1^\ast] \to [t_0^\ast~t^\ast]
      \qquad
      C \vdashinstr \instr_N : [t^\ast] \to [t_3^\ast]
    }{
diff --git a/document/core/valid/modules.rst b/document/core/valid/modules.rst
index 374cfddb..40b25a76 100644
--- a/document/core/valid/modules.rst
+++ b/document/core/valid/modules.rst
@@ -156,9 +156,7 @@ Element segments :math:`\elem` are classified by the :ref:`reference type `.
 
-* The element mode :math:`\elemmode` must be valid with :ref:`reference type ` :math:`t'`.
-
-* The :ref:`reference type ` :math:`t` must :ref:`match ` the reference type :math:`t'`.
+* The element mode :math:`\elemmode` must be valid with :ref:`reference type ` :math:`t`.
 
 * Then the element segment is valid with :ref:`reference type ` :math:`t`.
 
@@ -169,9 +167,7 @@ Element segments :math:`\elem` are classified by the :ref:`reference type ` are universally valid.
 However, restrictions apply to :ref:`function types ` as well as the :ref:`limits ` of :ref:`table types ` and :ref:`memory types `, which must be checked during validation.
 
-On :ref:`value types `, a simple notion of subtyping is defined.
-
 
 .. index:: limits
    pair: validation; limits
@@ -200,96 +198,6 @@ External Types
    }
 
 
-.. index:: subtyping
-
-Value Subtyping
-~~~~~~~~~~~~~~~
-
-.. index:: number type
-
-.. _match-numtype:
-
-Number Types
-............
-
-A :ref:`number type ` :math:`\numtype_1` matches a :ref:`number type ` :math:`\numtype_2` if and only if:
-
-* Both :math:`\numtype_1` and :math:`\numtype_2` are the same.
-
-.. math::
-   ~\\[-1ex]
-   \frac{
-   }{
-     \vdashnumtypematch \numtype \matchesvaltype \numtype
-   }
-
-
-.. index:: reference type
-
-.. _match-reftype:
-
-Reference Types
-...............
-
-A :ref:`reference type ` :math:`\reftype_1` matches a :ref:`reference type ` :math:`\reftype_2` if and only if:
-
-* Both :math:`\reftype_1` and :math:`\reftype_2` are the same.
-
-.. math::
-   ~\\[-1ex]
-   \frac{
-   }{
-     \vdashreftypematch \reftype \matchesvaltype \reftype
-   }
-
-.. note::
-   In future versions of WebAssembly, additional subtyping relations may be added.
-
-
-.. index:: value type, number type, reference type
-
-.. _match-valtype:
-
-Value Types
-...........
-
-A :ref:`value type ` :math:`\valtype_1` matches a :ref:`value type ` :math:`\valtype_2` if and only if:
-
-* Either both :math:`\valtype_1` and :math:`\valtype_2` are :ref:`number types ` and :math:`\valtype_1` :ref:`matches ` :math:`\valtype_2`.
-
-* Or both :math:`\valtype_1` and :math:`\valtype_2` are :ref:`reference types ` and :math:`\valtype_1` :ref:`matches ` :math:`\valtype_2`.
-
-* Or :math:`\valtype_1` is :math:`\BOT`.
-
-.. math::
-   ~\\[-1ex]
-   \frac{
-   }{
-     \vdashvaltypematch \BOT \matchesvaltype \valtype
-   }
-
-
-.. _match-resulttype:
-
-Result Types
-............
-
-Subtyping is lifted to :ref:`result types ` in a pointwise manner.
-That is, a :ref:`result type ` :math:`[t_1^?]` matches a :ref:`result type ` :math:`[t_2^?]` if and only if:
-
-* Either both :math:`t_1^?` and :math:`t_2^?` are empty.
-
-* Or :ref:`value type ` :math:`t_1` :ref:`matches ` :ref:`value type ` :math:`t_2`.
-
-.. math::
-   ~\\[-1ex]
-   \frac{
-     (\vdashvaltypematch t_1 \matchesvaltype t_2)^?
-   }{
-     \vdashresulttypematch [t_1^?] \matchesresulttype [t_2^?]
-   }
-
-
 .. index:: ! matching, external type
 .. _exec-import:
 .. _match:
@@ -403,21 +311,13 @@ An :ref:`external type ` :math:`\ETMEM~\limits_1` matches :ma
 Globals
 .......
 
-An :ref:`external type ` :math:`\ETGLOBAL~(\mut_1~t_1)` matches :math:`\ETGLOBAL~(\mut_2~t_2)` if and only if:
-
-* Either both :math:`\mut_1` and :math:`\mut_2` are |MVAR| and :math:`t_1` and :math:`t_2` are the same.
+An :ref:`external type ` :math:`\ETGLOBAL~\globaltype_1` matches :math:`\ETGLOBAL~\globaltype_2` if and only if:
 
-* Or both :math:`\mut_1` and :math:`\mut_2` are |MCONST| and :math:`t_1` :ref:`matches ` :math:`t_2`.
+* Both :math:`\globaltype_1` and :math:`\globaltype_2` are the same.
 
 .. math::
    ~\\[-1ex]
    \frac{
    }{
-     \vdashexterntypematch \ETGLOBAL~(\MVAR~t) \matchesexterntype \ETGLOBAL~(\MVAR~t)
-   }
-   \qquad
-   \frac{
-     \vdashvaltypematch t_1 \matchesvaltype t_2
-   }{
-     \vdashexterntypematch \ETGLOBAL~(\MCONST~t_1) \matchesexterntype \ETGLOBAL~(\MCONST~t_2)
+     \vdashexterntypematch \ETGLOBAL~\globaltype \matchesexterntype \ETGLOBAL~\globaltype
    }
diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml
index 054f0e72..c014e6b7 100644
--- a/interpreter/binary/encode.ml
+++ b/interpreter/binary/encode.ml
@@ -103,7 +103,6 @@ let encode m =
     let value_type = function
       | NumType t -> num_type t
       | RefType t -> ref_type t
-      | BotType -> assert false
 
     let stack_type = function
       | [] -> vs7 (-0x40)
diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml
index 3c809c42..938688d0 100644
--- a/interpreter/exec/eval.ml
+++ b/interpreter/exec/eval.ml
@@ -536,7 +536,7 @@ let invoke (func : func_inst) (vs : value list) : value list =
   let FuncType (ins, out) = Func.type_of func in
   if List.length vs <> List.length ins then
     Crash.error at "wrong number of arguments";
-  if not (List.for_all2 (fun v -> match_value_type (type_of_value v)) vs ins) then
+  if not (List.for_all2 (fun v -> (=) (type_of_value v)) vs ins) then
     Crash.error at "wrong types of arguments";
   let c = config empty_module_inst (List.rev vs) [Invoke func @@ at] in
   try List.rev (eval c) with Stack_overflow ->
diff --git a/interpreter/host/spectest.ml b/interpreter/host/spectest.ml
index a2cbf096..8d67b3b7 100644
--- a/interpreter/host/spectest.ml
+++ b/interpreter/host/spectest.ml
@@ -15,7 +15,6 @@ let global (GlobalType (t, _) as gt) =
     | NumType F32Type -> Num (F32 (F32.of_float 666.6))
     | NumType F64Type -> Num (F64 (F64.of_float 666.6))
     | RefType t -> Ref (NullRef t)
-    | BotType -> assert false
   in Global.alloc gt v
 
 let table =
diff --git a/interpreter/runtime/global.ml b/interpreter/runtime/global.ml
index 181399e0..5e172995 100644
--- a/interpreter/runtime/global.ml
+++ b/interpreter/runtime/global.ml
@@ -8,7 +8,7 @@ exception Type
 exception NotMutable
 
 let alloc (GlobalType (t, _) as ty) v =
-  if not (match_value_type (type_of_value v) t) then raise Type;
+  if type_of_value v <> t then raise Type;
   {ty; content = v}
 
 let type_of glob =
@@ -20,5 +20,5 @@ let load glob =
 let store glob v =
   let GlobalType (t, mut) = glob.ty in
   if mut <> Mutable then raise NotMutable;
-  if not (match_value_type (type_of_value v) t) then raise Type;
+  if type_of_value v <> t then raise Type;
   glob.content <- v
diff --git a/interpreter/runtime/table.ml b/interpreter/runtime/table.ml
index 8da0090e..bb10cab8 100644
--- a/interpreter/runtime/table.ml
+++ b/interpreter/runtime/table.ml
@@ -51,7 +51,7 @@ let load tab i =
 
 let store tab i r =
   let TableType (lim, t) = tab.ty in
-  if not (match_ref_type (type_of_ref r) t) then raise Type;
+  if type_of_ref r <> t then raise Type;
   try Lib.Array32.set tab.content i r with Invalid_argument _ -> raise Bounds
 
 let blit tab offset rs =
diff --git a/interpreter/script/js.ml b/interpreter/script/js.ml
index 7d4219f3..2934dd7e 100644
--- a/interpreter/script/js.ml
+++ b/interpreter/script/js.ml
@@ -366,7 +366,6 @@ let is_js_num_type = function
 let is_js_value_type = function
   | NumType t -> is_js_num_type t
   | RefType t -> true
-  | BotType -> assert false
 
 let is_js_global_type = function
   | GlobalType (t, mut) -> is_js_value_type t && mut = Immutable
diff --git a/interpreter/script/run.ml b/interpreter/script/run.ml
index afa658b6..618099ea 100644
--- a/interpreter/script/run.ml
+++ b/interpreter/script/run.ml
@@ -335,7 +335,7 @@ let run_action act : Values.value list =
       if List.length vs <> List.length ins then
         Script.error act.at "wrong number of arguments";
       List.iter2 (fun v t ->
-        if not (Types.match_value_type (Values.type_of_value v.it) t) then
+        if Values.type_of_value v.it <> t then
           Script.error v.at "wrong type of argument"
       ) vs ins;
       Eval.invoke f (List.map (fun v -> v.it) vs)
diff --git a/interpreter/syntax/types.ml b/interpreter/syntax/types.ml
index 6dbe6e1d..280a1af6 100644
--- a/interpreter/syntax/types.ml
+++ b/interpreter/syntax/types.ml
@@ -2,7 +2,7 @@
 
 type num_type = I32Type | I64Type | F32Type | F64Type
 type ref_type = AnyRefType | FuncRefType
-type value_type = NumType of num_type | RefType of ref_type | BotType
+type value_type = NumType of num_type | RefType of ref_type
 type stack_type = value_type list
 type func_type = FuncType of stack_type * stack_type
 
@@ -24,21 +24,28 @@ let size = function
   | I32Type | F32Type -> 4
   | I64Type | F64Type -> 8
 
+let is_num_type = function
+  | NumType _ -> true
+  | RefType _ -> false
 
-(* Subtyping *)
+let is_ref_type = function
+  | NumType _ -> false
+  | RefType _ -> true
 
-let match_num_type t1 t2 =
-  t1 = t2
 
-let match_ref_type t1 t2 =
-  t1 = t2
+(* Filters *)
 
-let match_value_type t1 t2 =
-  match t1, t2 with
-  | NumType t1', NumType t2' -> match_num_type t1' t2'
-  | RefType t1', RefType t2' -> match_ref_type t1' t2'
-  | BotType, _ -> true
-  | _, _ -> false
+let funcs =
+  Lib.List.map_filter (function ExternFuncType t -> Some t | _ -> None)
+let tables =
+  Lib.List.map_filter (function ExternTableType t -> Some t | _ -> None)
+let memories =
+  Lib.List.map_filter (function ExternMemoryType t -> Some t | _ -> None)
+let globals =
+  Lib.List.map_filter (function ExternGlobalType t -> Some t | _ -> None)
+
+
+(* Subtyping *)
 
 let match_limits lim1 lim2 =
   I32.ge_u lim1.min lim2.min &&
@@ -56,9 +63,8 @@ let match_table_type (TableType (lim1, et1)) (TableType (lim2, et2)) =
 let match_memory_type (MemoryType lim1) (MemoryType lim2) =
   match_limits lim1 lim2
 
-let match_global_type (GlobalType (t1, mut1)) (GlobalType (t2, mut2)) =
-  mut1 = mut2 &&
-  (t1 = t2 || mut2 = Immutable && match_value_type t1 t2)
+let match_global_type gt1 gt2 =
+  gt1 = gt2
 
 let match_extern_type et1 et2 =
   match et1, et2 with
@@ -68,26 +74,6 @@ let match_extern_type et1 et2 =
   | ExternGlobalType gt1, ExternGlobalType gt2 -> match_global_type gt1 gt2
   | _, _ -> false
 
-let is_num_type = function
-  | NumType _ | BotType -> true
-  | RefType _ -> false
-
-let is_ref_type = function
-  | NumType _ -> false
-  | RefType _ | BotType -> true
-
-
-(* Filters *)
-
-let funcs =
-  Lib.List.map_filter (function ExternFuncType t -> Some t | _ -> None)
-let tables =
-  Lib.List.map_filter (function ExternTableType t -> Some t | _ -> None)
-let memories =
-  Lib.List.map_filter (function ExternMemoryType t -> Some t | _ -> None)
-let globals =
-  Lib.List.map_filter (function ExternGlobalType t -> Some t | _ -> None)
-
 
 (* String conversion *)
 
@@ -108,7 +94,6 @@ let string_of_refed_type = function
 let string_of_value_type = function
   | NumType t -> string_of_num_type t
   | RefType t -> string_of_ref_type t
-  | BotType -> "impossible"
 
 let string_of_value_types = function
   | [t] -> string_of_value_type t
diff --git a/interpreter/syntax/values.ml b/interpreter/syntax/values.ml
index 03bbb88e..63416609 100644
--- a/interpreter/syntax/values.ml
+++ b/interpreter/syntax/values.ml
@@ -55,7 +55,6 @@ let default_ref = function
 let default_value = function
   | NumType t' -> Num (default_num t')
   | RefType t' -> Ref (default_ref t')
-  | BotType -> assert false
 
 
 (* Conversion *)
diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml
index 11fd69f0..b0e3a239 100644
--- a/interpreter/valid/valid.ml
+++ b/interpreter/valid/valid.ml
@@ -70,25 +70,32 @@ let refer_func (c : context) x = refer "function" c.refs.Free.funcs x
  *)
 
 type ellipses = NoEllipses | Ellipses
-type infer_stack_type = ellipses * value_type list
+type infer_stack_type = ellipses * value_type option list
 type op_type = {ins : infer_stack_type; outs : infer_stack_type}
 
-let stack ts = (NoEllipses, ts)
-let (-->) ts1 ts2 = {ins = NoEllipses, ts1; outs = NoEllipses, ts2}
-let (-->...) ts1 ts2 = {ins = Ellipses, ts1; outs = Ellipses, ts2}
+let known = List.map (fun t -> Some t)
+let stack ts = (NoEllipses, known ts)
+let (-~>) ts1 ts2 = {ins = NoEllipses, ts1; outs = NoEllipses, ts2}
+let (-->) ts1 ts2 = {ins = NoEllipses, known ts1; outs = NoEllipses, known ts2}
+let (-->...) ts1 ts2 = {ins = Ellipses, known ts1; outs = Ellipses, known ts2}
 
+let string_of_infer_type t =
+  Lib.Option.get (Lib.Option.map string_of_value_type t) "_"
+let string_of_infer_types ts =
+  "[" ^ String.concat " " (List.map string_of_infer_type ts) ^ "]"
+
+let eq_ty t1 t2 = (t1 = t2 || t1 = None || t2 = None)
 let check_stack ts1 ts2 at =
-  require
-    (List.length ts1 = List.length ts2 && List.for_all2 match_value_type ts1 ts2) at
-    ("type mismatch: operator requires " ^ string_of_stack_type ts2 ^
-     " but stack has " ^ string_of_stack_type ts1)
+  require (List.length ts1 = List.length ts2 && List.for_all2 eq_ty ts1 ts2) at
+    ("type mismatch: operator requires " ^ string_of_infer_types ts1 ^
+     " but stack has " ^ string_of_infer_types ts2)
 
 let pop (ell1, ts1) (ell2, ts2) at =
   let n1 = List.length ts1 in
   let n2 = List.length ts2 in
   let n = min n1 n2 in
   let n3 = if ell2 = Ellipses then (n1 - n) else 0 in
-  check_stack (Lib.List.make n3 BotType @ Lib.List.drop (n2 - n) ts2) ts1 at;
+  check_stack ts1 (Lib.List.make n3 None @ Lib.List.drop (n2 - n) ts2) at;
   (ell2, if ell1 = Ellipses then [] else Lib.List.take (n2 - n) ts2)
 
 let push (ell1, ts1) (ell2, ts2) =
@@ -97,7 +104,7 @@ let push (ell1, ts1) (ell2, ts2) =
   ts2 @ ts1
 
 let peek i (ell, ts) =
-  try List.nth (List.rev ts) i with Failure _ -> BotType
+  try List.nth (List.rev ts) i with Failure _ -> None
 
 
 (* Type Synthesis *)
@@ -191,14 +198,14 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type =
     [] --> []
 
   | Drop ->
-    [peek 0 s] --> []
+    [peek 0 s] -~> []
 
   | Select None ->
     let t = peek 1 s in
-    require (is_num_type t) e.at
+    require (match t with None -> true | Some t -> is_num_type t) e.at
       ("type mismatch: instruction requires numeric type" ^
-       " but stack has " ^ string_of_value_type t);
-    [t; t; NumType I32Type] --> [t]
+       " but stack has " ^ string_of_infer_type t);
+    [t; t; Some (NumType I32Type)] -~> [t]
 
   | Select (Some ts) ->
     check_arity (List.length ts) e.at;
@@ -228,10 +235,8 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type =
     (label c x @ [NumType I32Type]) --> label c x
 
   | BrTable (xs, x) ->
-    let n = List.length (label c x) in
-    let ts = Lib.List.table n (fun i -> peek (i + 1) s) in
-    check_stack ts (label c x) x.at;
-    List.iter (fun x' -> check_stack ts (label c x') x'.at) xs;
+    let ts = label c x in
+    List.iter (fun x' -> check_stack (known ts) (known (label c x')) x'.at) xs;
     (ts @ [NumType I32Type]) -->... []
 
   | Return ->
@@ -244,7 +249,7 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type =
   | CallIndirect (x, y) ->
     let TableType (lim, t) = table c x in
     let FuncType (ins, out) = type_ c y in
-    require (match_ref_type t FuncRefType) x.at
+    require (t = FuncRefType) x.at
       ("type mismatch: instruction requires table of functions" ^
        " but table has " ^ string_of_ref_type t);
     (ins @ [NumType I32Type]) --> out
@@ -290,7 +295,7 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type =
   | TableCopy (x, y) ->
     let TableType (_lim1, t1) = table c x in
     let TableType (_lim2, t2) = table c y in
-    require (match_ref_type t2 t1) x.at
+    require (t1 = t2) x.at
       ("type mismatch: source element type " ^ string_of_ref_type t1 ^
        " does not match destination element type " ^ string_of_ref_type t2);
     [NumType I32Type; NumType I32Type; NumType I32Type] --> []
@@ -298,7 +303,7 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type =
   | TableInit (x, y) ->
     let TableType (_lim1, t1) = table c x in
     let t2 = elem c y in
-    require (match_ref_type t2 t1) x.at
+    require (t1 = t2) x.at
       ("type mismatch: source element type " ^ string_of_ref_type t1 ^
        " does not match destination element type " ^ string_of_ref_type t2);
     [NumType I32Type; NumType I32Type; NumType I32Type] --> []
@@ -347,10 +352,10 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type =
 
   | RefIsNull ->
     let t = peek 0 s in
-    require (is_ref_type t) e.at
+    require (match t with None -> true | Some t -> is_ref_type t) e.at
       ("type mismatch: instruction requires reference type" ^
-       " but stack has " ^ string_of_value_type t);
-    [t] --> [NumType I32Type]
+       " but stack has " ^ string_of_infer_type t);
+    [t] -~> [Some (NumType I32Type)]
 
   | RefFunc x ->
     let _ft = func c x in
@@ -397,7 +402,7 @@ and check_block (c : context) (es : instr list) (ts : stack_type) at =
   let s' = pop (stack ts) s at in
   require (snd s' = []) at
     ("type mismatch: operator requires " ^ string_of_stack_type ts ^
-     " but stack has " ^ string_of_stack_type (snd s))
+     " but stack has " ^ string_of_infer_types (snd s))
 
 
 (* Types *)
@@ -421,7 +426,6 @@ let check_value_type (t : value_type) at =
   match t with
   | NumType t' -> check_num_type t' at
   | RefType t' -> check_ref_type t' at
-  | BotType -> ()
 
 let check_func_type (ft : func_type) at =
   let FuncType (ins, out) = ft in
@@ -497,7 +501,7 @@ let check_elem_mode (c : context) (t : ref_type) (mode : segment_mode) =
   | Passive -> ()
   | Active {index; offset} ->
     let TableType (_, et) = table c index in
-    require (match_ref_type t et) mode.at
+    require (t = et) mode.at
       "type mismatch in active element segment";
     check_const c offset (NumType I32Type)
   | Declarative -> ()
diff --git a/proposals/reference-types/Overview.md b/proposals/reference-types/Overview.md
index c5395984..63f6ea3d 100644
--- a/proposals/reference-types/Overview.md
+++ b/proposals/reference-types/Overview.md
@@ -57,15 +57,12 @@ Typing extensions:
 * Element types (of tables) are equated with reference types.
   - `elemtype ::= `
 
-* Introduce a simple subtype relation between reference types.
-  - reflexive transitive closure of rules to come
-
 
 New/extended instructions:
 
 * The new instruction `ref.null` evaluates to the null reference constant.
   - `ref.null rt : [] -> [rtref]`
-    - iff `rt = any` or `rt = func` 
+    - iff `rt = any` or `rt = func`
   - allowed in constant expressions
 
 * The new instruction `ref.is_null` checks for null.
@@ -142,6 +139,19 @@ API extensions:
 ## Possible Future Extensions
 
 
+### Subtyping
+
+Motivation:
+
+* Enable various extensions (see below).
+
+Additions:
+
+* Introduce a simple subtype relation between reference types.
+  - reflexive transitive closure of the following rules
+  - `t <: anyref` for all reftypes `t`
+
+
 ### Equality on references
 
 Motivation:
diff --git a/test/core/br_table.wast b/test/core/br_table.wast
index 566fab30..c5a5ffcd 100644
--- a/test/core/br_table.wast
+++ b/test/core/br_table.wast
@@ -1250,18 +1250,6 @@
       )
     )
   )
-
-  (func (export "meet-bottom")
-    (block (result f64)
-      (block (result f32)
-        (unreachable)
-        (br_table 0 1 1 (i32.const 1))
-      )
-      (drop)
-      (f64.const 0)
-    )
-    (drop)
-  )
 )
 
 (assert_return (invoke "type-i32"))
@@ -1576,6 +1564,7 @@
   "type mismatch"
 )
 
+
 (assert_invalid
   (module (func $meet-bottom (param i32) (result anyref)
     (block $l1 (result anyref)

From dd91463c9263449b00493ffac5dc6ca900d821ef Mon Sep 17 00:00:00 2001
From: Andreas Rossberg 
Date: Wed, 29 Apr 2020 10:52:01 +0200
Subject: [PATCH 4/6] Tweak ref.is_null

---
 document/core/appendix/index-instructions.rst | 2 +-
 document/core/binary/instructions.rst         | 2 +-
 document/core/exec/instructions.rst           | 8 ++++----
 document/core/syntax/instructions.rst         | 2 +-
 document/core/text/instructions.rst           | 2 +-
 document/core/valid/instructions.rst          | 8 ++++----
 interpreter/README.md                         | 2 +-
 interpreter/binary/decode.ml                  | 2 +-
 interpreter/binary/encode.ml                  | 2 +-
 interpreter/exec/eval.ml                      | 2 +-
 interpreter/script/js.ml                      | 4 ++--
 interpreter/syntax/ast.ml                     | 2 +-
 interpreter/syntax/free.ml                    | 2 +-
 interpreter/syntax/operators.ml               | 4 ++--
 interpreter/text/arrange.ml                   | 2 +-
 interpreter/text/parser.mly                   | 2 +-
 interpreter/valid/valid.ml                    | 8 ++------
 proposals/reference-types/Overview.md         | 3 ++-
 test/core/ref_func.wast                       | 6 +++---
 test/core/ref_is_null.wast                    | 4 ++--
 test/core/table_get.wast                      | 2 +-
 test/core/table_grow.wast                     | 2 +-
 test/core/table_set.wast                      | 2 +-
 23 files changed, 36 insertions(+), 39 deletions(-)

diff --git a/document/core/appendix/index-instructions.rst b/document/core/appendix/index-instructions.rst
index 8f5157fe..dbb02002 100644
--- a/document/core/appendix/index-instructions.rst
+++ b/document/core/appendix/index-instructions.rst
@@ -216,7 +216,7 @@ Instruction                             Binary Opcode       Type
 (reserved)                              :math:`\hex{CE}`                                                  
 (reserved)                              :math:`\hex{CF}`                                                  
 :math:`\REFNULL~t`                      :math:`\hex{D0}`    :math:`[] \to [t]`                          :ref:`validation `        :ref:`execution `
-:math:`\REFISNULL`                      :math:`\hex{D1}`    :math:`[t] \to [\I32]`                      :ref:`validation `     :ref:`execution `
+:math:`\REFISNULL~t`                    :math:`\hex{D1}`    :math:`[t] \to [\I32]`                      :ref:`validation `     :ref:`execution `
 :math:`\REFFUNC~x`                      :math:`\hex{D2}`    :math:`[] \to [\FUNCREF]`                   :ref:`validation `        :ref:`execution `
 :math:`\MEMORYINIT`                     :math:`\hex{FC08}`  :math:`[\I32~\I32~\I32] \to []`             :ref:`validation `     :ref:`execution `
 :math:`\DATADROP`                       :math:`\hex{FC09}`  :math:`[] \to []`                           :ref:`validation `       :ref:`execution `
diff --git a/document/core/binary/instructions.rst b/document/core/binary/instructions.rst
index 609d743c..a6fba132 100644
--- a/document/core/binary/instructions.rst
+++ b/document/core/binary/instructions.rst
@@ -77,7 +77,7 @@ Reference Instructions
    \begin{array}{llclll}
    \production{instruction} & \Binstr &::=& \dots \\ &&|&
      \hex{D0}~~t{:}\Breftype &\Rightarrow& \REFNULL~t \\ &&|&
-     \hex{D1} &\Rightarrow& \REFISNULL \\ &&|&
+     \hex{D1}~~t{:}\Breftype &\Rightarrow& \REFISNULL~t \\ &&|&
      \hex{D2}~~x{:}\Bfuncidx &\Rightarrow& \REFFUNC~x \\
    \end{array}
 
diff --git a/document/core/exec/instructions.rst b/document/core/exec/instructions.rst
index 4e6930ed..ba0ade50 100644
--- a/document/core/exec/instructions.rst
+++ b/document/core/exec/instructions.rst
@@ -203,8 +203,8 @@ Reference Instructions
 
 .. _exec-ref.is_null:
 
-:math:`\REFISNULL`
-..................
+:math:`\REFISNULL~t`
+....................
 
 1. Assert: due to :ref:`validation `, a :ref:`reference value ` is on the top of the stack.
 
@@ -220,9 +220,9 @@ Reference Instructions
 
 .. math::
    \begin{array}{lcl@{\qquad}l}
-   \val~\REFISNULL &\stepto& \I32.\CONST~1
+   \val~\REFISNULL~t &\stepto& \I32.\CONST~1
      & (\iff \val = \REFNULL~t) \\
-   \val~\REFISNULL &\stepto& \I32.\CONST~0
+   \val~\REFISNULL~t &\stepto& \I32.\CONST~0
      & (\otherwise) \\
    \end{array}
 
diff --git a/document/core/syntax/instructions.rst b/document/core/syntax/instructions.rst
index a76d4f52..fd29a890 100644
--- a/document/core/syntax/instructions.rst
+++ b/document/core/syntax/instructions.rst
@@ -184,7 +184,7 @@ Instructions in this group are concerned with accessing :ref:`references ` :math:`\reftype`.
+* The instruction is valid with type :math:`[t] \to [\I32]`.
 
 .. math::
    \frac{
    }{
-     C \vdashinstr \REFISNULL : [\reftype] \to [\I32]
+     C \vdashinstr \REFISNULL~t : [t] \to [\I32]
    }
 
 .. _valid-ref.func:
diff --git a/interpreter/README.md b/interpreter/README.md
index 8427536c..0704b2df 100644
--- a/interpreter/README.md
+++ b/interpreter/README.md
@@ -242,7 +242,7 @@ op:
   memory.init 
   data.drop 
   ref.null 
-  ref.is_null
+  ref.is_null 
   ref.func 
   .const 
   .
diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml
index d900cfdb..93929708 100644
--- a/interpreter/binary/decode.ml
+++ b/interpreter/binary/decode.ml
@@ -444,7 +444,7 @@ let rec instr s =
   | 0xc8 | 0xc9 | 0xca | 0xcb | 0xcc | 0xcd | 0xce | 0xcf as b -> illegal s pos b
 
   | 0xd0 -> ref_null (ref_type s)
-  | 0xd1 -> ref_is_null
+  | 0xd1 -> ref_is_null (ref_type s)
   | 0xd2 -> ref_func (at var s)
 
   | 0xfc as b1 ->
diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml
index c014e6b7..2c404c1a 100644
--- a/interpreter/binary/encode.ml
+++ b/interpreter/binary/encode.ml
@@ -232,7 +232,7 @@ let encode m =
       | DataDrop x -> op 0xfc; op 0x09; var x
 
       | RefNull t -> op 0xd0; ref_type t
-      | RefIsNull -> op 0xd1
+      | RefIsNull t -> op 0xd1; ref_type t
       | RefFunc x -> op 0xd2; var x
 
       | Const {it = I32 c; _} -> op 0x41; vs32 c
diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml
index 938688d0..aae2a0ce 100644
--- a/interpreter/exec/eval.ml
+++ b/interpreter/exec/eval.ml
@@ -410,7 +410,7 @@ let rec step (c : config) : config =
       | RefNull t, vs' ->
         Ref (NullRef t) :: vs', []
 
-      | RefIsNull, Ref r :: vs' ->
+      | RefIsNull _, Ref r :: vs' ->
         (match r with
         | NullRef _ ->
           Num (I32 1l) :: vs', []
diff --git a/interpreter/script/js.ml b/interpreter/script/js.ml
index 2934dd7e..55851301 100644
--- a/interpreter/script/js.ml
+++ b/interpreter/script/js.ml
@@ -274,8 +274,8 @@ let assert_return ress ts at =
         Compare (eq_of t') @@ at;
         Test (Values.I32 I32Op.Eqz) @@ at;
         BrIf (0l @@ at) @@ at ]
-    | LitResult {it = Values.Ref (Values.NullRef _); _} ->
-      [ RefIsNull @@ at;
+    | LitResult {it = Values.Ref (Values.NullRef t); _} ->
+      [ RefIsNull t @@ at;
         Test (Values.I32 I32Op.Eqz) @@ at;
         BrIf (0l @@ at) @@ at ]
     | LitResult {it = Values.Ref (HostRef n); _} ->
diff --git a/interpreter/syntax/ast.ml b/interpreter/syntax/ast.ml
index 949a5f91..c78a671a 100644
--- a/interpreter/syntax/ast.ml
+++ b/interpreter/syntax/ast.ml
@@ -103,7 +103,7 @@ and instr' =
   | MemoryInit of var                 (* initialize memory range from segment *)
   | DataDrop of var                   (* drop passive data segment *)
   | RefNull of ref_type               (* null reference *)
-  | RefIsNull                         (* null test *)
+  | RefIsNull of ref_type             (* null test *)
   | RefFunc of var                    (* function reference *)
   | Const of num                      (* constant *)
   | Test of testop                    (* numeric test *)
diff --git a/interpreter/syntax/free.ml b/interpreter/syntax/free.ml
index 33bfefc0..fb8973cf 100644
--- a/interpreter/syntax/free.ml
+++ b/interpreter/syntax/free.ml
@@ -62,7 +62,7 @@ let list free xs = List.fold_left union empty (List.map free xs)
 let rec instr (e : instr) =
   match e.it with
   | Unreachable | Nop | Drop | Select _ -> empty
-  | RefNull _ | RefIsNull -> empty
+  | RefNull _ | RefIsNull _ -> empty
   | RefFunc x -> funcs (var x)
   | Const _ | Test _ | Compare _ | Unary _ | Binary _ | Convert _ -> empty
   | Block (_, es) | Loop (_, es) -> block es
diff --git a/interpreter/syntax/operators.ml b/interpreter/syntax/operators.ml
index 73b2f410..4a5d5a48 100644
--- a/interpreter/syntax/operators.ml
+++ b/interpreter/syntax/operators.ml
@@ -9,9 +9,9 @@ let i32_const n = Const (I32 n.it @@ n.at)
 let i64_const n = Const (I64 n.it @@ n.at)
 let f32_const n = Const (F32 n.it @@ n.at)
 let f64_const n = Const (F64 n.it @@ n.at)
-let ref_null t = RefNull t
 let ref_func x = RefFunc x
-let ref_is_null = RefIsNull
+let ref_null t = RefNull t
+let ref_is_null t = RefIsNull t
 
 let unreachable = Unreachable
 let nop = Nop
diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml
index 656793c7..f496846f 100644
--- a/interpreter/text/arrange.ml
+++ b/interpreter/text/arrange.ml
@@ -264,7 +264,7 @@ let rec instr e =
     | MemoryInit x -> "memory.init " ^ var x, []
     | DataDrop x -> "data.drop " ^ var x, []
     | RefNull t -> "ref.null", [Atom (refed_type t)]
-    | RefIsNull -> "ref.is_null", []
+    | RefIsNull t -> "ref.is_null", [Atom (refed_type t)]
     | RefFunc x -> "ref.func " ^ var x, []
     | Const n -> constop n ^ " " ^ num n, []
     | Test op -> testop op, []
diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly
index 2781fbe9..93beee70 100644
--- a/interpreter/text/parser.mly
+++ b/interpreter/text/parser.mly
@@ -376,7 +376,7 @@ plain_instr :
   | MEMORY_INIT var { fun c -> memory_init ($2 c data) }
   | DATA_DROP var { fun c -> data_drop ($2 c data) }
   | REF_NULL ref_kind { fun c -> ref_null $2 }
-  | REF_IS_NULL { fun c -> ref_is_null }
+  | REF_IS_NULL ref_kind { fun c -> ref_is_null $2 }
   | REF_FUNC var { fun c -> ref_func ($2 c func) }
   | CONST num { fun c -> fst (num $1 $2) }
   | TEST { fun c -> $1 }
diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml
index b0e3a239..1eb6bcf1 100644
--- a/interpreter/valid/valid.ml
+++ b/interpreter/valid/valid.ml
@@ -350,12 +350,8 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type =
   | RefNull t ->
     [] --> [RefType t]
 
-  | RefIsNull ->
-    let t = peek 0 s in
-    require (match t with None -> true | Some t -> is_ref_type t) e.at
-      ("type mismatch: instruction requires reference type" ^
-       " but stack has " ^ string_of_infer_type t);
-    [t] -~> [Some (NumType I32Type)]
+  | RefIsNull t ->
+    [RefType t] --> [NumType I32Type]
 
   | RefFunc x ->
     let _ft = func c x in
diff --git a/proposals/reference-types/Overview.md b/proposals/reference-types/Overview.md
index 63f6ea3d..5eb13267 100644
--- a/proposals/reference-types/Overview.md
+++ b/proposals/reference-types/Overview.md
@@ -66,7 +66,8 @@ New/extended instructions:
   - allowed in constant expressions
 
 * The new instruction `ref.is_null` checks for null.
-  - `ref.is_null : [anyref] -> [i32]`
+  - `ref.is_null rt : [rtref] -> [i32]`
+    - iff `rt = any` or `rt = func`
 
 * The new instruction `ref.func` creates a reference to a given function.
   - `ref.func $x : [] -> [funcref]`
diff --git a/test/core/ref_func.wast b/test/core/ref_func.wast
index 2e811a93..6bc470b0 100644
--- a/test/core/ref_func.wast
+++ b/test/core/ref_func.wast
@@ -26,13 +26,13 @@
   (func $ff2)
 
   (func (export "is_null-f") (result i32)
-    (ref.is_null (ref.func $f))
+    (ref.is_null func (ref.func $f))
   )
   (func (export "is_null-g") (result i32)
-    (ref.is_null (ref.func $g))
+    (ref.is_null func (ref.func $g))
   )
   (func (export "is_null-v") (result i32)
-    (ref.is_null (global.get $v))
+    (ref.is_null func (global.get $v))
   )
 
   (func (export "set-f") (global.set $v (ref.func $f)))
diff --git a/test/core/ref_is_null.wast b/test/core/ref_is_null.wast
index ac283209..68c935bc 100644
--- a/test/core/ref_is_null.wast
+++ b/test/core/ref_is_null.wast
@@ -1,9 +1,9 @@
 (module
   (func $f1 (export "anyref") (param $x anyref) (result i32)
-    (ref.is_null (local.get $x))
+    (ref.is_null any (local.get $x))
   )
   (func $f2 (export "funcref") (param $x funcref) (result i32)
-    (ref.is_null (local.get $x))
+    (ref.is_null func (local.get $x))
   )
 
   (table $t1 2 anyref)
diff --git a/test/core/table_get.wast b/test/core/table_get.wast
index 93aca18a..506b7a9d 100644
--- a/test/core/table_get.wast
+++ b/test/core/table_get.wast
@@ -17,7 +17,7 @@
   )
 
   (func (export "is_null-funcref") (param $i i32) (result i32)
-    (ref.is_null (call $f3 (local.get $i)))
+    (ref.is_null func (call $f3 (local.get $i)))
   )
 )
 
diff --git a/test/core/table_grow.wast b/test/core/table_grow.wast
index 7ba1be9e..26b289d8 100644
--- a/test/core/table_grow.wast
+++ b/test/core/table_grow.wast
@@ -90,7 +90,7 @@
     (block
       (loop
         (local.set 2 (table.get $t (local.get 0)))
-        (br_if 1 (i32.eqz (ref.is_null (local.get 2))))
+        (br_if 1 (i32.eqz (ref.is_null func (local.get 2))))
         (br_if 1 (i32.ge_u (local.get 0) (local.get 1)))
         (local.set 0 (i32.add (local.get 0) (i32.const 1)))
         (br_if 0 (i32.le_u (local.get 0) (local.get 1)))
diff --git a/test/core/table_set.wast b/test/core/table_set.wast
index f5976c1e..2534bdf4 100644
--- a/test/core/table_set.wast
+++ b/test/core/table_set.wast
@@ -22,7 +22,7 @@
   )
 
   (func (export "is_null-funcref") (param $i i32) (result i32)
-    (ref.is_null (call $f3 (local.get $i)))
+    (ref.is_null func (call $f3 (local.get $i)))
   )
 )
 

From 3bafde21d8c9f94f94132c780d27a9059174fd3f Mon Sep 17 00:00:00 2001
From: Andreas Rossberg 
Date: Wed, 29 Apr 2020 11:53:01 +0200
Subject: [PATCH 5/6] Rename anyref to externref

---
 document/core/appendix/algorithm.rst   |   4 +-
 document/core/appendix/index-types.rst |   2 +-
 document/core/appendix/properties.rst  |  10 +--
 document/core/binary/types.rst         |   2 +-
 document/core/exec/modules.rst         |   8 +-
 document/core/exec/runtime.rst         |  14 +--
 document/core/syntax/types.rst         |   4 +-
 document/core/text/types.rst           |   8 +-
 document/core/util/macros.def          |   6 +-
 document/js-api/index.bs               |   8 +-
 interpreter/binary/decode.ml           |   2 +-
 interpreter/binary/encode.ml           |   2 +-
 interpreter/script/js.ml               |  54 +++++------
 interpreter/script/run.ml              |   4 +-
 interpreter/script/script.ml           |   6 +-
 interpreter/syntax/types.ml            |   6 +-
 interpreter/text/arrange.ml            |   2 +-
 interpreter/text/lexer.mll             |   7 +-
 interpreter/text/parser.mly            |  12 +--
 proposals/reference-types/Overview.md  |  14 +--
 test/core/br_table.wast                |  20 ++---
 test/core/global.wast                  |   8 +-
 test/core/linking.wast                 |  18 ++--
 test/core/ref_func.wast                |   4 +-
 test/core/ref_is_null.wast             |  40 ++++-----
 test/core/ref_null.wast                |   6 +-
 test/core/select.wast                  |  12 +--
 test/core/table-sub.wast               |   4 +-
 test/core/table_fill.wast              | 118 ++++++++++++-------------
 test/core/table_get.wast               |  36 ++++----
 test/core/table_grow.wast              |  72 +++++++--------
 test/core/table_set.wast               |  50 +++++------
 test/core/table_size.wast              |  20 ++---
 33 files changed, 291 insertions(+), 292 deletions(-)

diff --git a/document/core/appendix/algorithm.rst b/document/core/appendix/algorithm.rst
index df2e5a87..7fd3da33 100644
--- a/document/core/appendix/algorithm.rst
+++ b/document/core/appendix/algorithm.rst
@@ -25,13 +25,13 @@ Types are representable as an enumeration.
 
 .. code-block:: pseudo
 
-   type val_type = I32 | I64 | F32 | F64 | Anyref | Funcref
+   type val_type = I32 | I64 | F32 | F64 | Funcref | Externref
 
    func is_num(t : val_type) : bool =
      return t = I32 || t = I64 || t = F32 || t = F64
 
    func is_ref(t : val_type) : bool =
-     return t = Anyref || t = Funcref
+     return t = Funcref || t = Externref
 
 The algorithm uses two separate stacks: the *value stack* and the *control stack*.
 The former tracks the :ref:`types ` of operand values on the :ref:`stack `,
diff --git a/document/core/appendix/index-types.rst b/document/core/appendix/index-types.rst
index 3f13e553..413e6f0b 100644
--- a/document/core/appendix/index-types.rst
+++ b/document/core/appendix/index-types.rst
@@ -14,7 +14,7 @@ Category                                  Constructor
 :ref:`Number type `       |F64|                                        :math:`\hex{7C}` (-4 as |Bs7|)
 (reserved)                                                                             :math:`\hex{7B}` .. :math:`\hex{71}`
 :ref:`Reference type `    |FUNCREF|                                    :math:`\hex{70}` (-16 as |Bs7|)
-:ref:`Reference type `    |ANYREF|                                     :math:`\hex{6F}` (-17 as |Bs7|)
+:ref:`Reference type `    |EXTERNREF|                                  :math:`\hex{6F}` (-17 as |Bs7|)
 (reserved)                                                                             :math:`\hex{6E}` .. :math:`\hex{61}`
 :ref:`Function type `    :math:`[\valtype^\ast] \to [\valtype^\ast]`  :math:`\hex{60}` (-32 as |Bs7|)
 (reserved)                                                                             :math:`\hex{5F}` .. :math:`\hex{41}`
diff --git a/document/core/appendix/properties.rst b/document/core/appendix/properties.rst
index 35abaddd..f62e02b3 100644
--- a/document/core/appendix/properties.rst
+++ b/document/core/appendix/properties.rst
@@ -523,17 +523,17 @@ To that end, all previous typing judgements :math:`C \vdash \X{prop}` are genera
    }
 
 
-.. index:: host address
+.. index:: extern address
 
-:math:`\REFHOST~\hostaddr`
-..........................
+:math:`\REFEXTERNADDR~\externaddr`
+..................................
 
-* The instruction is valid with type :math:`[] \to [\ANYREF]`.
+* The instruction is valid with type :math:`[] \to [\EXTERNREF]`.
 
 .. math::
    \frac{
    }{
-     S; C \vdashadmininstr \REFHOST~\hostaddr : [] \to [\ANYREF]
+     S; C \vdashadmininstr \REFEXTERNADDR~\externaddr : [] \to [\EXTERNREF]
    }
 
 
diff --git a/document/core/binary/types.rst b/document/core/binary/types.rst
index 4261b60d..5154e4d8 100644
--- a/document/core/binary/types.rst
+++ b/document/core/binary/types.rst
@@ -42,7 +42,7 @@ Reference Types
    \begin{array}{llclll@{\qquad\qquad}l}
    \production{reference type} & \Breftype &::=&
      \hex{70} &\Rightarrow& \FUNCREF \\ &&|&
-     \hex{6F} &\Rightarrow& \ANYREF \\
+     \hex{6F} &\Rightarrow& \EXTERNREF \\
    \end{array}
 
 
diff --git a/document/core/exec/modules.rst b/document/core/exec/modules.rst
index 1e578785..35df503d 100644
--- a/document/core/exec/modules.rst
+++ b/document/core/exec/modules.rst
@@ -137,15 +137,15 @@ The following auxiliary typing rules specify this typing relation relative to a
    }
 
 
-:ref:`Host References ` :math:`\REFHOST~a`
-...........................................................
+:ref:`External References ` :math:`\REFEXTERNADDR~a`
+.......................................................................
 
-* The value is valid with :ref:`reference type ` :math:`\ANYREF`.
+* The value is valid with :ref:`reference type ` :math:`\EXTERNREF`.
 
 .. math::
    \frac{
    }{
-     S \vdashval \REFHOST~a : \ANYREF
+     S \vdashval \REFEXTERNADDR~a : \EXTERNREF
    }
 
 
diff --git a/document/core/exec/runtime.rst b/document/core/exec/runtime.rst
index fd8dbed7..568739e4 100644
--- a/document/core/exec/runtime.rst
+++ b/document/core/exec/runtime.rst
@@ -11,7 +11,7 @@ Runtime Structure
    pair: abstract syntax; value
 .. _syntax-num:
 .. _syntax-ref:
-.. _syntax-ref.host:
+.. _syntax-ref.extern:
 .. _syntax-val:
 
 Values
@@ -25,7 +25,7 @@ It is convenient to reuse the same notation as for the |CONST| :ref:`instruction
 
 References other than null are represented with additional :ref:`administrative instructions `.
 They either are *function references*, pointing to a specific :ref:`function address `,
-or *host references* pointing to an uninterpreted form of :ref:`host address ` that can be defined by the :ref:`embedder `.
+or *external references* pointing to an uninterpreted form of :ref:`extern address ` that can be defined by the :ref:`embedder ` to represent its own objects.
 
 .. math::
    \begin{array}{llcl}
@@ -37,7 +37,7 @@ or *host references* pointing to an uninterpreted form of :ref:`host address ` may supply an uninterpreted set of *h
      \addr \\
    \production{(data address)} & \dataaddr &::=&
      \addr \\
-   \production{(host address)} & \hostaddr &::=&
+   \production{(extern address)} & \externaddr &::=&
      \addr \\
    \end{array}
 
@@ -526,7 +526,7 @@ In order to express the reduction of :ref:`traps `, :ref:`calls `, :ref:`calls `. Similarly, |REFHOST| represents :ref:`host references `.
+The |REFFUNCADDR| instruction represents :ref:`function reference values `. Similarly, |REFEXTERNADDR| represents :ref:`external references `.
 
 The |INVOKE| instruction represents the imminent invocation of a :ref:`function instance `, identified by its :ref:`address `.
 It unifies the handling of different forms of calls.
diff --git a/document/core/syntax/types.rst b/document/core/syntax/types.rst
index 3c2616cb..25822424 100644
--- a/document/core/syntax/types.rst
+++ b/document/core/syntax/types.rst
@@ -54,12 +54,12 @@ Reference Types
 .. math::
    \begin{array}{llll}
    \production{reference type} & \reftype &::=&
-     \FUNCREF ~|~ \ANYREF \\
+     \FUNCREF ~|~ \EXTERNREF \\
    \end{array}
 
 The type |FUNCREF| denotes the infinite union of all references to :ref:`functions `, regardless of their :ref:`function types `.
 
-The type |ANYREF| denotes the infinite union of all references to objects owned by the :ref:`embedder ` and that can be passed into WebAssembly under this type.
+The type |EXTERNREF| denotes the infinite union of all references to objects owned by the :ref:`embedder ` and that can be passed into WebAssembly under this type.
 
 Reference types are *opaque*, meaning that neither their size nor their bit pattern can be observed.
 Values of reference type can be stored in :ref:`tables `.
diff --git a/document/core/text/types.rst b/document/core/text/types.rst
index 85f3ca4e..5711fb54 100644
--- a/document/core/text/types.rst
+++ b/document/core/text/types.rst
@@ -33,11 +33,11 @@ Reference Types
 .. math::
    \begin{array}{llcll@{\qquad\qquad}l}
    \production{reference type} & \Treftype &::=&
-     \text{anyref} &\Rightarrow& \ANYREF \\ &&|&
-     \text{funcref} &\Rightarrow& \FUNCREF \\
+     \text{funcref} &\Rightarrow& \FUNCREF \\ &&|&
+     \text{externref} &\Rightarrow& \EXTERNREF \\
    \production{referenced type} & \Trefedtype &::=&
-     \text{any} &\Rightarrow& \ANYREF \\ &&|&
-     \text{func} &\Rightarrow& \FUNCREF \\
+     \text{func} &\Rightarrow& \FUNCREF \\ &&|&
+     \text{extern} &\Rightarrow& \EXTERNREF \\
    \end{array}
 
 
diff --git a/document/core/util/macros.def b/document/core/util/macros.def
index 5a87db3d..a74a9f56 100644
--- a/document/core/util/macros.def
+++ b/document/core/util/macros.def
@@ -179,8 +179,8 @@
 .. |F32| mathdef:: \xref{syntax/types}{syntax-valtype}{\K{f32}}
 .. |F64| mathdef:: \xref{syntax/types}{syntax-valtype}{\K{f64}}
 
-.. |ANYREF| mathdef:: \xref{syntax/types}{syntax-reftype}{\K{anyref}}
 .. |FUNCREF| mathdef:: \xref{syntax/types}{syntax-reftype}{\K{funcref}}
+.. |EXTERNREF| mathdef:: \xref{syntax/types}{syntax-reftype}{\K{externref}}
 
 .. |MVAR| mathdef:: \xref{syntax/types}{syntax-mut}{\K{var}}
 .. |MCONST| mathdef:: \xref{syntax/types}{syntax-mut}{\K{const}}
@@ -850,7 +850,7 @@
 .. |globaladdr| mathdef:: \xref{exec/runtime}{syntax-globaladdr}{\X{globaladdr}}
 .. |elemaddr| mathdef:: \xref{exec/runtime}{syntax-elemaddr}{\X{elemaddr}}
 .. |dataaddr| mathdef:: \xref{exec/runtime}{syntax-dataaddr}{\X{dataaddr}}
-.. |hostaddr| mathdef:: \xref{exec/runtime}{syntax-hostaddr}{\X{hostaddr}}
+.. |externaddr| mathdef:: \xref{exec/runtime}{syntax-externaddr}{\X{externaddr}}
 
 .. Instances, terminals
 
@@ -947,7 +947,7 @@
 .. Administrative Instructions, terminals
 
 .. |REFFUNCADDR| mathdef:: \xref{exec/runtime}{syntax-ref}{\K{ref}}
-.. |REFHOST| mathdef:: \xref{exec/runtime}{syntax-ref.host}{\K{ref{.}host}}
+.. |REFEXTERNADDR| mathdef:: \xref{exec/runtime}{syntax-ref.extern}{\K{ref{.}extern}}
 .. |TRAP| mathdef:: \xref{exec/runtime}{syntax-trap}{\K{trap}}
 .. |INVOKE| mathdef:: \xref{exec/runtime}{syntax-invoke}{\K{invoke}}
 
diff --git a/document/js-api/index.bs b/document/js-api/index.bs
index 20734823..d7b1b2ba 100644
--- a/document/js-api/index.bs
+++ b/document/js-api/index.bs
@@ -150,7 +150,7 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df
         text: 𝖿πŸ₯𝟀
         text: π–ΏπŸ¨πŸ¦
     url: syntax/types.html#syntax-reftype
-        text: anyref
+        text: externref
         text: funcref
     text: function element; url: exec/runtime.html#syntax-funcelem
     text: import component; url: syntax/modules.html#imports
@@ -706,7 +706,7 @@ Immediately after a WebAssembly [=memory.grow=] instruction executes, perform th
 
 
 enum TableKind {
-  "anyref",
+  "externref",
   "anyfunc",
   // Note: More values may be added in future iterations,
   // e.g., typed function references, typed GC references
@@ -887,8 +887,8 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
     1. If |s| equals "i64", return [=π—‚πŸ¨πŸ¦=].
     1. If |s| equals "f32", return [=𝖿πŸ₯𝟀=].
     1. If |s| equals "f64", return [=π–ΏπŸ¨πŸ¦=].
-    1. If |s| equals "anyref", return [=anyref=].
     1. If |s| equals "funcref", return [=funcref=].
+    1. If |s| equals "externref", return [=externref=].
     1. Assert: This step is not reached.
 
 
@@ -1087,7 +1087,7 @@ The algorithm ToWebAssemblyValue(|v|, |type|) coerces a JavaScript va
     1. Let |f64| be ? [=ToNumber=](|v|).
     1. Return [=π–ΏπŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] |f64|.
 1. Assert: |type| is a reference type.
-1. If |type| is [=anyref=],
+1. If |type| is [=externref=],
     1. Do nothing.
 1. If |type| is [=funcref=],
     1. If |v| is not an [=Exported function=] or null, throw a {{TypeError}}.
diff --git a/interpreter/binary/decode.ml b/interpreter/binary/decode.ml
index 93929708..4c1b135f 100644
--- a/interpreter/binary/decode.ml
+++ b/interpreter/binary/decode.ml
@@ -144,7 +144,7 @@ let num_type s =
 let ref_type s =
   match vs7 s with
   | -0x10 -> FuncRefType
-  | -0x11 -> AnyRefType
+  | -0x11 -> ExternRefType
   | _ -> error s (pos s - 1) "malformed reference type"
 
 let value_type s =
diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml
index 2c404c1a..c0263df5 100644
--- a/interpreter/binary/encode.ml
+++ b/interpreter/binary/encode.ml
@@ -98,7 +98,7 @@ let encode m =
 
     let ref_type = function
       | FuncRefType -> vs7 (-0x10)
-      | AnyRefType -> vs7 (-0x11)
+      | ExternRefType -> vs7 (-0x11)
 
     let value_type = function
       | NumType t -> num_type t
diff --git a/interpreter/script/js.ml b/interpreter/script/js.ml
index 55851301..66efeb73 100644
--- a/interpreter/script/js.ml
+++ b/interpreter/script/js.ml
@@ -10,19 +10,19 @@ let harness =
 {|
 'use strict';
 
-let hostrefs = {};
-let hostsym = Symbol("hostref");
-function hostref(s) {
-  if (! (s in hostrefs)) hostrefs[s] = {[hostsym]: s};
-  return hostrefs[s];
+let externrefs = {};
+let externsym = Symbol("externref");
+function externref(s) {
+  if (! (s in externrefs)) externrefs[s] = {[externsym]: s};
+  return externrefs[s];
 }
-function is_hostref(x) {
-  return (x !== null && hostsym in x) ? 1 : 0;
+function is_externref(x) {
+  return (x !== null && externsym in x) ? 1 : 0;
 }
 function is_funcref(x) {
   return typeof x === "function" ? 1 : 0;
 }
-function eq_hostref(x, y) {
+function eq_externref(x, y) {
   return x === y ? 1 : 0;
 }
 function eq_funcref(x, y) {
@@ -30,8 +30,8 @@ function eq_funcref(x, y) {
 }
 
 let spectest = {
-  hostref: hostref,
-  is_hostref: is_hostref,
+  externref: externref,
+  is_externref: is_externref,
   is_funcref: is_funcref,
   eq_ref: eq_ref,
   print: console.log.bind(console),
@@ -160,7 +160,7 @@ function assert_return(action, expected) {
         throw new Error("Wasm function return value expected, got " + actual);
       };
       return;
-    case "ref.any":
+    case "ref.extern":
       if (actual === null) {
         throw new Error("Wasm reference return value expected, got " + actual);
       };
@@ -214,10 +214,10 @@ let lookup (mods : modules) x_opt name at =
 (* Wrappers *)
 
 let subject_idx = 0l
-let hostref_idx = 1l
-let is_hostref_idx = 2l
+let externref_idx = 1l
+let is_externref_idx = 2l
 let is_funcref_idx = 3l
-let eq_hostref_idx = 4l
+let eq_externref_idx = 4l
 let _eq_funcref_idx = 5l
 let subject_type_idx = 6l
 
@@ -249,8 +249,8 @@ let value v =
   match v.it with
   | Values.Num num -> [Const (num @@ v.at) @@ v.at]
   | Values.Ref (Values.NullRef t) -> [RefNull t @@ v.at]
-  | Values.Ref (HostRef n) ->
-    [Const (Values.I32 n @@ v.at) @@ v.at; Call (hostref_idx @@ v.at) @@ v.at]
+  | Values.Ref (ExternRef n) ->
+    [Const (Values.I32 n @@ v.at) @@ v.at; Call (externref_idx @@ v.at) @@ v.at]
   | Values.Ref _ -> assert false
 
 let invoke ft vs at =
@@ -278,10 +278,10 @@ let assert_return ress ts at =
       [ RefIsNull t @@ at;
         Test (Values.I32 I32Op.Eqz) @@ at;
         BrIf (0l @@ at) @@ at ]
-    | LitResult {it = Values.Ref (HostRef n); _} ->
+    | LitResult {it = Values.Ref (ExternRef n); _} ->
       [ Const (Values.I32 n @@ at) @@ at;
-        Call (hostref_idx @@ at) @@ at;
-        Call (eq_hostref_idx @@ at)  @@ at;
+        Call (externref_idx @@ at) @@ at;
+        Call (eq_externref_idx @@ at)  @@ at;
         Test (Values.I32 I32Op.Eqz) @@ at;
         BrIf (0l @@ at) @@ at ]
     | LitResult {it = Values.Ref _; _} ->
@@ -309,8 +309,8 @@ let assert_return ress ts at =
     | RefResult t ->
       let is_ref_idx =
         match t with
-        | AnyRefType -> is_hostref_idx
         | FuncRefType -> is_funcref_idx
+        | ExternRefType -> is_externref_idx
       in
       [ Call (is_ref_idx @@ at) @@ at;
         Test (Values.I32 I32Op.Eqz) @@ at;
@@ -322,22 +322,22 @@ let wrap item_name wrap_action wrap_assertion at =
   let locals, assertion = wrap_assertion at in
   let types =
     (FuncType ([], []) @@ at) ::
-    (FuncType ([NumType I32Type], [RefType AnyRefType]) @@ at) ::
-    (FuncType ([RefType AnyRefType], [NumType I32Type]) @@ at) ::
+    (FuncType ([NumType I32Type], [RefType ExternRefType]) @@ at) ::
+    (FuncType ([RefType ExternRefType], [NumType I32Type]) @@ at) ::
     (FuncType ([RefType FuncRefType], [NumType I32Type]) @@ at) ::
-    (FuncType ([RefType AnyRefType; RefType AnyRefType], [NumType I32Type]) @@ at) ::
+    (FuncType ([RefType ExternRefType; RefType ExternRefType], [NumType I32Type]) @@ at) ::
     (FuncType ([RefType FuncRefType; RefType FuncRefType], [NumType I32Type]) @@ at) ::
     itypes
   in
   let imports =
     [ {module_name = Utf8.decode "module"; item_name; idesc} @@ at;
-      {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "hostref";
+      {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_hostref";
+      {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_funcref";
        idesc = FuncImport (3l @@ at) @@ at} @@ at;
-      {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "eq_hostref";
+      {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "eq_externref";
        idesc = FuncImport (4l @@ at) @@ at} @@ at;
       {module_name = Utf8.decode "spectest"; item_name = Utf8.decode "eq_funcref";
        idesc = FuncImport (5l @@ at) @@ at} @@ at ]
@@ -416,7 +416,7 @@ let of_value v =
   | Num (F32 z) -> of_float (F32.to_float z)
   | Num (F64 z) -> of_float (F64.to_float z)
   | Ref (NullRef _) -> "null"
-  | Ref (HostRef n) -> "hostref(" ^ Int32.to_string n ^ ")"
+  | Ref (ExternRef n) -> "externref(" ^ Int32.to_string n ^ ")"
   | _ -> assert false
 
 let of_nan = function
diff --git a/interpreter/script/run.ml b/interpreter/script/run.ml
index 618099ea..3eacacca 100644
--- a/interpreter/script/run.ml
+++ b/interpreter/script/run.ml
@@ -375,8 +375,8 @@ let assert_result at got expect =
         )
       | RefResult t ->
         (match t, v with
-        | Types.AnyRefType, Ref (HostRef _)
-        | Types.FuncRefType, Ref (Instance.FuncRef _) -> false
+        | Types.FuncRefType, Ref (Instance.FuncRef _)
+        | Types.ExternRefType, Ref (ExternRef _) -> false
         | _ -> true
         )
     ) got expect
diff --git a/interpreter/script/script.ml b/interpreter/script/script.ml
index 07812aed..50531b2f 100644
--- a/interpreter/script/script.ml
+++ b/interpreter/script/script.ml
@@ -1,6 +1,6 @@
 type var = string Source.phrase
 
-type Values.ref_ += HostRef of int32
+type Values.ref_ += ExternRef of int32
 type value = Values.value Source.phrase
 
 type definition = definition' Source.phrase
@@ -56,11 +56,11 @@ exception Syntax of Source.region * string
 let () =
   let type_of_ref' = !Values.type_of_ref' in
   Values.type_of_ref' := function
-    | HostRef _ -> Types.AnyRefType
+    | ExternRef _ -> Types.ExternRefType
     | r -> type_of_ref' r
 
 let () =
   let string_of_ref' = !Values.string_of_ref' in
   Values.string_of_ref' := function
-    | HostRef n -> "ref " ^ Int32.to_string n
+    | ExternRef n -> "ref " ^ Int32.to_string n
     | r -> string_of_ref' r
diff --git a/interpreter/syntax/types.ml b/interpreter/syntax/types.ml
index 280a1af6..82faaf6e 100644
--- a/interpreter/syntax/types.ml
+++ b/interpreter/syntax/types.ml
@@ -1,7 +1,7 @@
 (* Types *)
 
 type num_type = I32Type | I64Type | F32Type | F64Type
-type ref_type = AnyRefType | FuncRefType
+type ref_type = FuncRefType | ExternRefType
 type value_type = NumType of num_type | RefType of ref_type
 type stack_type = value_type list
 type func_type = FuncType of stack_type * stack_type
@@ -84,12 +84,12 @@ let string_of_num_type = function
   | F64Type -> "f64"
 
 let string_of_ref_type = function
-  | AnyRefType -> "anyref"
   | FuncRefType -> "funcref"
+  | ExternRefType -> "externref"
 
 let string_of_refed_type = function
-  | AnyRefType -> "any"
   | FuncRefType -> "func"
+  | ExternRefType -> "extern"
 
 let string_of_value_type = function
   | NumType t -> string_of_num_type t
diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml
index f496846f..a6733c1a 100644
--- a/interpreter/text/arrange.ml
+++ b/interpreter/text/arrange.ml
@@ -433,7 +433,7 @@ let value v =
   | Num (Values.F32 z) -> Node ("f32.const " ^ F32.to_string z, [])
   | Num (Values.F64 z) -> Node ("f64.const " ^ F64.to_string z, [])
   | Ref (NullRef t) -> Node ("ref.null", [Atom (refed_type t)])
-  | Ref (HostRef n) -> Node ("ref.host " ^ Int32.to_string n, [])
+  | Ref (ExternRef n) -> Node ("ref.extern " ^ Int32.to_string n, [])
   | _ -> assert false
 
 let definition mode x_opt def =
diff --git a/interpreter/text/lexer.mll b/interpreter/text/lexer.mll
index 6667f611..36524d23 100644
--- a/interpreter/text/lexer.mll
+++ b/interpreter/text/lexer.mll
@@ -160,8 +160,8 @@ rule token = parse
   | '"'character*'\\'_
     { error_nest (Lexing.lexeme_end_p lexbuf) lexbuf "illegal escape" }
 
-  | "any" { ANY }
-  | "anyref" { ANYREF }
+  | "extern" { EXTERN }
+  | "externref" { EXTERNREF }
   | "funcref" { FUNCREF }
   | (nxx as t) { NUM_TYPE (num_type t) }
   | "mut" { MUT }
@@ -180,7 +180,7 @@ rule token = parse
     }
   | "ref.null" { REF_NULL }
   | "ref.func" { REF_FUNC }
-  | "ref.host" { REF_HOST }
+  | "ref.extern" { REF_EXTERN }
   | "ref.is_null" { REF_IS_NULL }
 
   | "nop" { NOP }
@@ -370,7 +370,6 @@ rule token = parse
   | "assert_exhaustion" { ASSERT_EXHAUSTION }
   | "nan:canonical" { NAN Script.CanonicalNan }
   | "nan:arithmetic" { NAN Script.ArithmeticNan }
-  | "ref.any" { REF_ANY }
   | "input" { INPUT }
   | "output" { OUTPUT }
 
diff --git a/interpreter/text/parser.mly b/interpreter/text/parser.mly
index 93beee70..445c6db3 100644
--- a/interpreter/text/parser.mly
+++ b/interpreter/text/parser.mly
@@ -164,7 +164,7 @@ let inline_type_explicit (c : context) x ft at =
 
 %token LPAR RPAR
 %token NAT INT FLOAT STRING VAR
-%token ANY ANYREF FUNCREF NUM_TYPE MUT
+%token NUM_TYPE FUNCREF EXTERNREF EXTERN MUT
 %token UNREACHABLE NOP DROP SELECT
 %token BLOCK END IF THEN ELSE LOOP BR BR_IF BR_TABLE
 %token CALL CALL_INDIRECT RETURN
@@ -174,7 +174,7 @@ let inline_type_explicit (c : context) x ft at =
 %token MEMORY_SIZE MEMORY_GROW MEMORY_FILL MEMORY_COPY MEMORY_INIT DATA_DROP
 %token LOAD STORE OFFSET_EQ_NAT ALIGN_EQ_NAT
 %token CONST UNARY BINARY TEST COMPARE CONVERT
-%token REF_ANY REF_NULL REF_FUNC REF_HOST REF_IS_NULL
+%token REF_NULL REF_FUNC REF_EXTERN REF_IS_NULL
 %token FUNC START TYPE PARAM RESULT LOCAL GLOBAL
 %token TABLE ELEM MEMORY DATA DECLARE OFFSET ITEM IMPORT EXPORT
 %token MODULE BIN QUOTE
@@ -227,12 +227,12 @@ string_list :
 /* Types */
 
 ref_kind :
-  | ANY { AnyRefType }
   | FUNC { FuncRefType }
+  | EXTERN { ExternRefType }
 
 ref_type :
-  | ANYREF { AnyRefType }
   | FUNCREF { FuncRefType }
+  | EXTERNREF { ExternRefType }
 
 value_type :
   | NUM_TYPE { NumType $1 }
@@ -990,7 +990,7 @@ meta :
 const :
   | LPAR CONST num RPAR { Values.Num (snd (num $2 $3)) @@ at () }
   | LPAR REF_NULL ref_kind RPAR { Values.Ref (Values.NullRef $3) @@ at () }
-  | LPAR REF_HOST NAT RPAR { Values.Ref (HostRef (nat32 $3 (ati 3))) @@ at () }
+  | LPAR REF_EXTERN NAT RPAR { Values.Ref (ExternRef (nat32 $3 (ati 3))) @@ at () }
 
 const_list :
   | /* empty */ { [] }
@@ -999,8 +999,8 @@ const_list :
 result :
   | const { LitResult $1 @@ at () }
   | LPAR CONST NAN RPAR { NanResult (nanop $2 ($3 @@ ati 3)) @@ at () }
-  | LPAR REF_ANY RPAR { RefResult AnyRefType @@ at () }
   | LPAR REF_FUNC RPAR { RefResult FuncRefType @@ at () }
+  | LPAR REF_EXTERN RPAR { RefResult ExternRefType @@ at () }
 
 result_list :
   | /* empty */ { [] }
diff --git a/proposals/reference-types/Overview.md b/proposals/reference-types/Overview.md
index 5eb13267..1c8ee29d 100644
--- a/proposals/reference-types/Overview.md
+++ b/proposals/reference-types/Overview.md
@@ -7,7 +7,7 @@ TODO: more text, motivation, explanation
 Motivation:
 
 * Easier and more efficient interop with host environment (see e.g. the [Interface Types proposal](https://github.com/WebAssembly/interface-types/blob/master/proposals/interface-types/Explainer.md))
-  - allow host references to be represented directly by type `anyref` (see [here](https://github.com/WebAssembly/interface-types/issues/9))
+  - allow host references to be represented directly by type `externref` (see [here](https://github.com/WebAssembly/interface-types/issues/9))
   - without having to go through tables, allocating slots, and maintaining index bijections at the boundaries
 
 * Basic manipulation of tables inside Wasm
@@ -25,7 +25,7 @@ by repurposing tables as a general memory for opaque data types
 Get the most important parts soon!
 
 Summary:
-* Add new type `anyref` that can be used as both a value types and a table element type.
+* Add new type `externref` that can be used as both a value types and a table element type.
 
 * Also allow `funcref` as a value type.
 
@@ -46,8 +46,8 @@ Notes:
 
 Typing extensions:
 
-* Introduce `anyref` and `funcref` as a new class of *reference types*.
-  - `reftype ::= anyref | funcref`
+* Introduce `funref` and `externref` as a new class of *reference types*.
+  - `reftype ::= funcref | externref`
 
 * Value types (of locals, globals, function parameters and results) can now be either numeric types or reference types.
   - `numtype ::= i32 | i64 | f32 | f64`
@@ -62,12 +62,12 @@ New/extended instructions:
 
 * The new instruction `ref.null` evaluates to the null reference constant.
   - `ref.null rt : [] -> [rtref]`
-    - iff `rt = any` or `rt = func`
+    - iff `rt = func` or `rt = extern`
   - allowed in constant expressions
 
 * The new instruction `ref.is_null` checks for null.
   - `ref.is_null rt : [rtref] -> [i32]`
-    - iff `rt = any` or `rt = func`
+    - iff `rt = func` or `rt = extern`
 
 * The new instruction `ref.func` creates a reference to a given function.
   - `ref.func $x : [] -> [funcref]`
@@ -132,7 +132,7 @@ Table extensions:
 
 API extensions:
 
-* Any JS value can be passed as `anyref` to a Wasm function, stored in a global, or in a table.
+* Any JS value can be passed as `externref` to a Wasm function, stored in a global, or in a table.
 
 * Any Wasm exported function object or `null` can be passed as `funcref` to a Wasm function, stored in a global, or in a table.
 
diff --git a/test/core/br_table.wast b/test/core/br_table.wast
index c5a5ffcd..fc84e2f0 100644
--- a/test/core/br_table.wast
+++ b/test/core/br_table.wast
@@ -1243,9 +1243,9 @@
     )
   )
 
-  (func (export "meet-anyref") (param i32) (param anyref) (result anyref)
-    (block $l1 (result anyref)
-      (block $l2 (result anyref)
+  (func (export "meet-externref") (param i32) (param externref) (result externref)
+    (block $l1 (result externref)
+      (block $l2 (result externref)
         (br_table $l1 $l2 $l1 (local.get 1) (local.get 0))
       )
     )
@@ -1433,9 +1433,9 @@
 
 (assert_return (invoke "nested-br_table-loop-block" (i32.const 1)) (i32.const 3))
 
-(assert_return (invoke "meet-anyref" (i32.const 0) (ref.host 1)) (ref.host 1))
-(assert_return (invoke "meet-anyref" (i32.const 1) (ref.host 1)) (ref.host 1))
-(assert_return (invoke "meet-anyref" (i32.const 2) (ref.host 1)) (ref.host 1))
+(assert_return (invoke "meet-externref" (i32.const 0) (ref.extern 1)) (ref.extern 1))
+(assert_return (invoke "meet-externref" (i32.const 1) (ref.extern 1)) (ref.extern 1))
+(assert_return (invoke "meet-externref" (i32.const 2) (ref.extern 1)) (ref.extern 1))
 
 (assert_invalid
   (module (func $type-arg-void-vs-num (result i32)
@@ -1566,14 +1566,14 @@
 
 
 (assert_invalid
-  (module (func $meet-bottom (param i32) (result anyref)
-    (block $l1 (result anyref)
+  (module (func $meet-bottom (param i32) (result externref)
+    (block $l1 (result externref)
       (drop
         (block $l2 (result i32)
-          (br_table $l2 $l1 $l2 (ref.null any) (local.get 0))
+          (br_table $l2 $l1 $l2 (ref.null extern) (local.get 0))
         )
       )
-      (ref.null any)
+      (ref.null extern)
     )
   ))
   "type mismatch"
diff --git a/test/core/global.wast b/test/core/global.wast
index ef0ccf72..a19ae5e7 100644
--- a/test/core/global.wast
+++ b/test/core/global.wast
@@ -11,12 +11,12 @@
   (global (;6;) (mut f64) (f64.const -14))
   (global $y (mut i64) (i64.const -15))
 
-  (global $r anyref (ref.null any))
+  (global $r externref (ref.null extern))
   (global funcref (ref.null func))
 
   (func (export "get-a") (result i32) (global.get $a))
   (func (export "get-b") (result i64) (global.get $b))
-  (func (export "get-r") (result anyref) (global.get $r))
+  (func (export "get-r") (result externref) (global.get $r))
   (func (export "get-x") (result i32) (global.get $x))
   (func (export "get-y") (result i64) (global.get $y))
   (func (export "set-x") (param i32) (global.set $x (local.get 0)))
@@ -184,7 +184,7 @@
 
 (assert_return (invoke "get-a") (i32.const -2))
 (assert_return (invoke "get-b") (i64.const -5))
-(assert_return (invoke "get-r") (ref.null any))
+(assert_return (invoke "get-r") (ref.null extern))
 (assert_return (invoke "get-x") (i32.const -12))
 (assert_return (invoke "get-y") (i64.const -15))
 
@@ -294,7 +294,7 @@
 )
 
 (assert_invalid
-  (module (global (import "" "") anyref) (global funcref (global.get 0)))
+  (module (global (import "" "") externref) (global funcref (global.get 0)))
   "type mismatch"
 )
 
diff --git a/test/core/linking.wast b/test/core/linking.wast
index 38366425..08484781 100644
--- a/test/core/linking.wast
+++ b/test/core/linking.wast
@@ -96,17 +96,17 @@
 (module $Mref_ex
   (global (export "g-const-func") funcref (ref.null func))
   (global (export "g-var-func") (mut funcref) (ref.null func))
-  (global (export "g-const-any") anyref (ref.null any))
-  (global (export "g-var-any") (mut anyref) (ref.null any))
+  (global (export "g-const-any") externref (ref.null extern))
+  (global (export "g-var-any") (mut externref) (ref.null extern))
 )
 (register "Mref_ex" $Mref_ex)
 
 (module $Mref_im
   (global (import "Mref_ex" "g-const-func") funcref)
-  (global (import "Mref_ex" "g-const-any") anyref)
+  (global (import "Mref_ex" "g-const-any") externref)
 
   (global (import "Mref_ex" "g-var-func") (mut funcref))
-  (global (import "Mref_ex" "g-var-any") (mut anyref))
+  (global (import "Mref_ex" "g-var-any") (mut externref))
 )
 
 (assert_unlinkable
@@ -114,13 +114,13 @@
   "incompatible import type"
 )
 (assert_unlinkable
-  (module (global (import "Mref_ex" "g-const-func") anyref))
+  (module (global (import "Mref_ex" "g-const-func") externref))
   "incompatible import type"
 )
 
 
 (assert_unlinkable
-  (module (global (import "Mref_ex" "g-var-func") (mut anyref)))
+  (module (global (import "Mref_ex" "g-var-func") (mut externref)))
   "incompatible import type"
 )
 (assert_unlinkable
@@ -289,17 +289,17 @@
 
 (module $Mtable_ex
   (table $t1 (export "t-func") 1 funcref)
-  (table $t2 (export "t-any") 1 anyref)
+  (table $t2 (export "t-any") 1 externref)
 )
 (register "Mtable_ex" $Mtable_ex)
 
 (module
   (table (import "Mtable_ex" "t-func") 1 funcref)
-  (table (import "Mtable_ex" "t-any") 1 anyref)
+  (table (import "Mtable_ex" "t-any") 1 externref)
 )
 
 (assert_unlinkable
-  (module (table (import "Mtable_ex" "t-func") 1 anyref))
+  (module (table (import "Mtable_ex" "t-func") 1 externref))
   "incompatible import type"
 )
 (assert_unlinkable
diff --git a/test/core/ref_func.wast b/test/core/ref_func.wast
index 6bc470b0..3ace5141 100644
--- a/test/core/ref_func.wast
+++ b/test/core/ref_func.wast
@@ -9,8 +9,8 @@
     (i32.add (local.get $x) (i32.const 1))
   )
 
-  (global anyref (ref.null any))
-  (global anyref (ref.null any))
+  (global externref (ref.null extern))
+  (global externref (ref.null extern))
   (global funcref (ref.func $f))
   (global funcref (ref.func $g))
   (global $v (mut funcref) (ref.func $f))
diff --git a/test/core/ref_is_null.wast b/test/core/ref_is_null.wast
index 68c935bc..7c01bb54 100644
--- a/test/core/ref_is_null.wast
+++ b/test/core/ref_is_null.wast
@@ -1,49 +1,49 @@
 (module
-  (func $f1 (export "anyref") (param $x anyref) (result i32)
-    (ref.is_null any (local.get $x))
-  )
-  (func $f2 (export "funcref") (param $x funcref) (result i32)
+  (func $f1 (export "funcref") (param $x funcref) (result i32)
     (ref.is_null func (local.get $x))
   )
+  (func $f2 (export "externref") (param $x externref) (result i32)
+    (ref.is_null extern (local.get $x))
+  )
 
-  (table $t1 2 anyref)
-  (table $t2 2 funcref)
-  (elem (table $t2) (i32.const 1) func $dummy)
+  (table $t1 2 funcref)
+  (table $t2 2 externref)
+  (elem (table $t1) (i32.const 1) func $dummy)
   (func $dummy)
 
-  (func (export "init") (param $r anyref)
-    (table.set $t1 (i32.const 1) (local.get $r))
+  (func (export "init") (param $r externref)
+    (table.set $t2 (i32.const 1) (local.get $r))
   )
   (func (export "deinit")
-    (table.set $t1 (i32.const 1) (ref.null any))
-    (table.set $t2 (i32.const 1) (ref.null func))
+    (table.set $t1 (i32.const 1) (ref.null func))
+    (table.set $t2 (i32.const 1) (ref.null extern))
   )
 
-  (func (export "anyref-elem") (param $x i32) (result i32)
+  (func (export "funcref-elem") (param $x i32) (result i32)
     (call $f1 (table.get $t1 (local.get $x)))
   )
-  (func (export "funcref-elem") (param $x i32) (result i32)
+  (func (export "externref-elem") (param $x i32) (result i32)
     (call $f2 (table.get $t2 (local.get $x)))
   )
 )
 
-(assert_return (invoke "anyref" (ref.null any)) (i32.const 1))
 (assert_return (invoke "funcref" (ref.null func)) (i32.const 1))
+(assert_return (invoke "externref" (ref.null extern)) (i32.const 1))
 
-(assert_return (invoke "anyref" (ref.host 1)) (i32.const 0))
+(assert_return (invoke "externref" (ref.extern 1)) (i32.const 0))
 
-(invoke "init" (ref.host 0))
+(invoke "init" (ref.extern 0))
 
-(assert_return (invoke "anyref-elem" (i32.const 0)) (i32.const 1))
 (assert_return (invoke "funcref-elem" (i32.const 0)) (i32.const 1))
+(assert_return (invoke "externref-elem" (i32.const 0)) (i32.const 1))
 
-(assert_return (invoke "anyref-elem" (i32.const 1)) (i32.const 0))
 (assert_return (invoke "funcref-elem" (i32.const 1)) (i32.const 0))
+(assert_return (invoke "externref-elem" (i32.const 1)) (i32.const 0))
 
 (invoke "deinit")
 
-(assert_return (invoke "anyref-elem" (i32.const 0)) (i32.const 1))
 (assert_return (invoke "funcref-elem" (i32.const 0)) (i32.const 1))
+(assert_return (invoke "externref-elem" (i32.const 0)) (i32.const 1))
 
-(assert_return (invoke "anyref-elem" (i32.const 1)) (i32.const 1))
 (assert_return (invoke "funcref-elem" (i32.const 1)) (i32.const 1))
+(assert_return (invoke "externref-elem" (i32.const 1)) (i32.const 1))
diff --git a/test/core/ref_null.wast b/test/core/ref_null.wast
index 0155d3dc..b88b0888 100644
--- a/test/core/ref_null.wast
+++ b/test/core/ref_null.wast
@@ -1,10 +1,10 @@
 (module
-  (func (export "anyref") (result anyref) (ref.null any))
+  (func (export "externref") (result externref) (ref.null extern))
   (func (export "funcref") (result funcref) (ref.null func))
 
-  (global anyref (ref.null any))
+  (global externref (ref.null extern))
   (global funcref (ref.null func))
 )
 
-(assert_return (invoke "anyref") (ref.null any))
+(assert_return (invoke "externref") (ref.null extern))
 (assert_return (invoke "funcref") (ref.null func))
diff --git a/test/core/select.wast b/test/core/select.wast
index c11f1261..61edfd9e 100644
--- a/test/core/select.wast
+++ b/test/core/select.wast
@@ -32,8 +32,8 @@
   (func (export "select-funcref") (param funcref funcref i32) (result funcref)
     (select (result funcref) (local.get 0) (local.get 1) (local.get 2))
   )
-  (func (export "select-anyref") (param anyref anyref i32) (result anyref)
-    (select (result anyref) (local.get 0) (local.get 1) (local.get 2))
+  (func (export "select-externref") (param externref externref i32) (result externref)
+    (select (result externref) (local.get 0) (local.get 1) (local.get 2))
   )
 
   ;; Check that both sides of the select are evaluated
@@ -230,14 +230,14 @@
 (assert_return (invoke "select-f32-t" (f32.const 1) (f32.const 2) (i32.const 1)) (f32.const 1))
 (assert_return (invoke "select-f64-t" (f64.const 1) (f64.const 2) (i32.const 1)) (f64.const 1))
 (assert_return (invoke "select-funcref" (ref.null func) (ref.null func) (i32.const 1)) (ref.null func))
-(assert_return (invoke "select-anyref" (ref.host 1) (ref.host 2) (i32.const 1)) (ref.host 1))
+(assert_return (invoke "select-externref" (ref.extern 1) (ref.extern 2) (i32.const 1)) (ref.extern 1))
 
 (assert_return (invoke "select-i32-t" (i32.const 1) (i32.const 2) (i32.const 0)) (i32.const 2))
 (assert_return (invoke "select-i32-t" (i32.const 2) (i32.const 1) (i32.const 0)) (i32.const 1))
 (assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const -1)) (i64.const 2))
 (assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const 0xf0f0f0f0)) (i64.const 2))
-(assert_return (invoke "select-anyref" (ref.host 1) (ref.host 2) (i32.const 0)) (ref.host 2))
-(assert_return (invoke "select-anyref" (ref.host 2) (ref.host 1) (i32.const 0)) (ref.host 1))
+(assert_return (invoke "select-externref" (ref.extern 1) (ref.extern 2) (i32.const 0)) (ref.extern 2))
+(assert_return (invoke "select-externref" (ref.extern 2) (ref.extern 1) (i32.const 0)) (ref.extern 1))
 
 (assert_return (invoke "select-f32-t" (f32.const nan) (f32.const 1) (i32.const 1)) (f32.const nan))
 (assert_return (invoke "select-f32-t" (f32.const nan:0x20304) (f32.const 1) (i32.const 1)) (f32.const nan:0x20304))
@@ -359,7 +359,7 @@
 
 
 (assert_invalid
-  (module (func $type-anyref-implicit (param $r anyref)
+  (module (func $type-externref-implicit (param $r externref)
     (drop (select (local.get $r) (local.get $r) (i32.const 1)))
   ))
   "type mismatch"
diff --git a/test/core/table-sub.wast b/test/core/table-sub.wast
index 780b38f7..08787bdd 100644
--- a/test/core/table-sub.wast
+++ b/test/core/table-sub.wast
@@ -1,7 +1,7 @@
 (assert_invalid
   (module
     (table $t1 10 funcref)
-    (table $t2 10 anyref)
+    (table $t2 10 externref)
     (func $f
       (table.copy $t1 $t2 (i32.const 0) (i32.const 1) (i32.const 2))
     )
@@ -12,7 +12,7 @@
 (assert_invalid
   (module
     (table $t 10 funcref)
-    (elem $el anyref)
+    (elem $el externref)
     (func $f
       (table.init $t $el (i32.const 0) (i32.const 1) (i32.const 2))
     )
diff --git a/test/core/table_fill.wast b/test/core/table_fill.wast
index 2d77bb4e..29c556db 100644
--- a/test/core/table_fill.wast
+++ b/test/core/table_fill.wast
@@ -1,66 +1,66 @@
 (module
-  (table $t 10 anyref)
+  (table $t 10 externref)
 
-  (func (export "fill") (param $i i32) (param $r anyref) (param $n i32)
+  (func (export "fill") (param $i i32) (param $r externref) (param $n i32)
     (table.fill $t (local.get $i) (local.get $r) (local.get $n))
   )
 
-  (func (export "get") (param $i i32) (result anyref)
+  (func (export "get") (param $i i32) (result externref)
     (table.get $t (local.get $i))
   )
 )
 
-(assert_return (invoke "get" (i32.const 1)) (ref.null any))
-(assert_return (invoke "get" (i32.const 2)) (ref.null any))
-(assert_return (invoke "get" (i32.const 3)) (ref.null any))
-(assert_return (invoke "get" (i32.const 4)) (ref.null any))
-(assert_return (invoke "get" (i32.const 5)) (ref.null any))
-
-(assert_return (invoke "fill" (i32.const 2) (ref.host 1) (i32.const 3)))
-(assert_return (invoke "get" (i32.const 1)) (ref.null any))
-(assert_return (invoke "get" (i32.const 2)) (ref.host 1))
-(assert_return (invoke "get" (i32.const 3)) (ref.host 1))
-(assert_return (invoke "get" (i32.const 4)) (ref.host 1))
-(assert_return (invoke "get" (i32.const 5)) (ref.null any))
-
-(assert_return (invoke "fill" (i32.const 4) (ref.host 2) (i32.const 2)))
-(assert_return (invoke "get" (i32.const 3)) (ref.host 1))
-(assert_return (invoke "get" (i32.const 4)) (ref.host 2))
-(assert_return (invoke "get" (i32.const 5)) (ref.host 2))
-(assert_return (invoke "get" (i32.const 6)) (ref.null any))
-
-(assert_return (invoke "fill" (i32.const 4) (ref.host 3) (i32.const 0)))
-(assert_return (invoke "get" (i32.const 3)) (ref.host 1))
-(assert_return (invoke "get" (i32.const 4)) (ref.host 2))
-(assert_return (invoke "get" (i32.const 5)) (ref.host 2))
-
-(assert_return (invoke "fill" (i32.const 8) (ref.host 4) (i32.const 2)))
-(assert_return (invoke "get" (i32.const 7)) (ref.null any))
-(assert_return (invoke "get" (i32.const 8)) (ref.host 4))
-(assert_return (invoke "get" (i32.const 9)) (ref.host 4))
-
-(assert_return (invoke "fill" (i32.const 9) (ref.null any) (i32.const 1)))
-(assert_return (invoke "get" (i32.const 8)) (ref.host 4))
-(assert_return (invoke "get" (i32.const 9)) (ref.null any))
-
-(assert_return (invoke "fill" (i32.const 10) (ref.host 5) (i32.const 0)))
-(assert_return (invoke "get" (i32.const 9)) (ref.null any))
+(assert_return (invoke "get" (i32.const 1)) (ref.null extern))
+(assert_return (invoke "get" (i32.const 2)) (ref.null extern))
+(assert_return (invoke "get" (i32.const 3)) (ref.null extern))
+(assert_return (invoke "get" (i32.const 4)) (ref.null extern))
+(assert_return (invoke "get" (i32.const 5)) (ref.null extern))
+
+(assert_return (invoke "fill" (i32.const 2) (ref.extern 1) (i32.const 3)))
+(assert_return (invoke "get" (i32.const 1)) (ref.null extern))
+(assert_return (invoke "get" (i32.const 2)) (ref.extern 1))
+(assert_return (invoke "get" (i32.const 3)) (ref.extern 1))
+(assert_return (invoke "get" (i32.const 4)) (ref.extern 1))
+(assert_return (invoke "get" (i32.const 5)) (ref.null extern))
+
+(assert_return (invoke "fill" (i32.const 4) (ref.extern 2) (i32.const 2)))
+(assert_return (invoke "get" (i32.const 3)) (ref.extern 1))
+(assert_return (invoke "get" (i32.const 4)) (ref.extern 2))
+(assert_return (invoke "get" (i32.const 5)) (ref.extern 2))
+(assert_return (invoke "get" (i32.const 6)) (ref.null extern))
+
+(assert_return (invoke "fill" (i32.const 4) (ref.extern 3) (i32.const 0)))
+(assert_return (invoke "get" (i32.const 3)) (ref.extern 1))
+(assert_return (invoke "get" (i32.const 4)) (ref.extern 2))
+(assert_return (invoke "get" (i32.const 5)) (ref.extern 2))
+
+(assert_return (invoke "fill" (i32.const 8) (ref.extern 4) (i32.const 2)))
+(assert_return (invoke "get" (i32.const 7)) (ref.null extern))
+(assert_return (invoke "get" (i32.const 8)) (ref.extern 4))
+(assert_return (invoke "get" (i32.const 9)) (ref.extern 4))
+
+(assert_return (invoke "fill" (i32.const 9) (ref.null extern) (i32.const 1)))
+(assert_return (invoke "get" (i32.const 8)) (ref.extern 4))
+(assert_return (invoke "get" (i32.const 9)) (ref.null extern))
+
+(assert_return (invoke "fill" (i32.const 10) (ref.extern 5) (i32.const 0)))
+(assert_return (invoke "get" (i32.const 9)) (ref.null extern))
 
 (assert_trap
-  (invoke "fill" (i32.const 8) (ref.host 6) (i32.const 3))
+  (invoke "fill" (i32.const 8) (ref.extern 6) (i32.const 3))
   "out of bounds"
 )
-(assert_return (invoke "get" (i32.const 7)) (ref.null any))
-(assert_return (invoke "get" (i32.const 8)) (ref.host 4))
-(assert_return (invoke "get" (i32.const 9)) (ref.null any))
+(assert_return (invoke "get" (i32.const 7)) (ref.null extern))
+(assert_return (invoke "get" (i32.const 8)) (ref.extern 4))
+(assert_return (invoke "get" (i32.const 9)) (ref.null extern))
 
 (assert_trap
-  (invoke "fill" (i32.const 11) (ref.null any) (i32.const 0))
+  (invoke "fill" (i32.const 11) (ref.null extern) (i32.const 0))
   "out of bounds"
 )
 
 (assert_trap
-  (invoke "fill" (i32.const 11) (ref.null any) (i32.const 10))
+  (invoke "fill" (i32.const 11) (ref.null extern) (i32.const 10))
   "out of bounds"
 )
 
@@ -69,7 +69,7 @@
 
 (assert_invalid
   (module
-    (table $t 10 anyref)
+    (table $t 10 externref)
     (func $type-index-value-length-empty-vs-i32-i32
       (table.fill $t)
     )
@@ -78,16 +78,16 @@
 )
 (assert_invalid
   (module
-    (table $t 10 anyref)
+    (table $t 10 externref)
     (func $type-index-empty-vs-i32
-      (table.fill $t (ref.null any) (i32.const 1))
+      (table.fill $t (ref.null extern) (i32.const 1))
     )
   )
   "type mismatch"
 )
 (assert_invalid
   (module
-    (table $t 10 anyref)
+    (table $t 10 externref)
     (func $type-value-empty-vs
       (table.fill $t (i32.const 1) (i32.const 1))
     )
@@ -96,18 +96,18 @@
 )
 (assert_invalid
   (module
-    (table $t 10 anyref)
+    (table $t 10 externref)
     (func $type-length-empty-vs-i32
-      (table.fill $t (i32.const 1) (ref.null any))
+      (table.fill $t (i32.const 1) (ref.null extern))
     )
   )
   "type mismatch"
 )
 (assert_invalid
   (module
-    (table $t 0 anyref)
+    (table $t 0 externref)
     (func $type-index-f32-vs-i32
-      (table.fill $t (f32.const 1) (ref.null any) (i32.const 1))
+      (table.fill $t (f32.const 1) (ref.null extern) (i32.const 1))
     )
   )
   "type mismatch"
@@ -115,7 +115,7 @@
 (assert_invalid
   (module
     (table $t 0 funcref)
-    (func $type-value-vs-funcref (param $r anyref)
+    (func $type-value-vs-funcref (param $r externref)
       (table.fill $t (i32.const 1) (local.get $r) (i32.const 1))
     )
   )
@@ -123,9 +123,9 @@
 )
 (assert_invalid
   (module
-    (table $t 0 anyref)
+    (table $t 0 externref)
     (func $type-length-f32-vs-i32
-      (table.fill $t (i32.const 1) (ref.null any) (f32.const 1))
+      (table.fill $t (i32.const 1) (ref.null extern) (f32.const 1))
     )
   )
   "type mismatch"
@@ -133,9 +133,9 @@
 
 (assert_invalid
   (module
-    (table $t1 1 anyref)
+    (table $t1 1 externref)
     (table $t2 1 funcref)
-    (func $type-value-anyref-vs-funcref-multi (param $r anyref)
+    (func $type-value-externref-vs-funcref-multi (param $r externref)
       (table.fill $t2 (i32.const 0) (local.get $r) (i32.const 1))
     )
   )
@@ -144,9 +144,9 @@
 
 (assert_invalid
   (module
-    (table $t 1 anyref)
+    (table $t 1 externref)
     (func $type-result-empty-vs-num (result i32)
-      (table.fill $t (i32.const 0) (ref.null any) (i32.const 1))
+      (table.fill $t (i32.const 0) (ref.null extern) (i32.const 1))
     )
   )
   "type mismatch"
diff --git a/test/core/table_get.wast b/test/core/table_get.wast
index 506b7a9d..3df7190e 100644
--- a/test/core/table_get.wast
+++ b/test/core/table_get.wast
@@ -1,15 +1,15 @@
 (module
-  (table $t2 2 anyref)
+  (table $t2 2 externref)
   (table $t3 3 funcref)
   (elem (table $t3) (i32.const 1) func $dummy)
   (func $dummy)
 
-  (func (export "init") (param $r anyref)
+  (func (export "init") (param $r externref)
     (table.set $t2 (i32.const 1) (local.get $r))
     (table.set $t3 (i32.const 2) (table.get $t3 (i32.const 1)))
   )
 
-  (func (export "get-anyref") (param $i i32) (result anyref)
+  (func (export "get-externref") (param $i i32) (result externref)
     (table.get $t2 (local.get $i))
   )
   (func $f3 (export "get-funcref") (param $i i32) (result funcref)
@@ -21,18 +21,18 @@
   )
 )
 
-(invoke "init" (ref.host 1))
+(invoke "init" (ref.extern 1))
 
-(assert_return (invoke "get-anyref" (i32.const 0)) (ref.null any))
-(assert_return (invoke "get-anyref" (i32.const 1)) (ref.host 1))
+(assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern))
+(assert_return (invoke "get-externref" (i32.const 1)) (ref.extern 1))
 
 (assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func))
 (assert_return (invoke "is_null-funcref" (i32.const 1)) (i32.const 0))
 (assert_return (invoke "is_null-funcref" (i32.const 2)) (i32.const 0))
 
-(assert_trap (invoke "get-anyref" (i32.const 2)) "out of bounds")
+(assert_trap (invoke "get-externref" (i32.const 2)) "out of bounds")
 (assert_trap (invoke "get-funcref" (i32.const 3)) "out of bounds")
-(assert_trap (invoke "get-anyref" (i32.const -1)) "out of bounds")
+(assert_trap (invoke "get-externref" (i32.const -1)) "out of bounds")
 (assert_trap (invoke "get-funcref" (i32.const -1)) "out of bounds")
 
 
@@ -40,8 +40,8 @@
 
 (assert_invalid
   (module
-    (table $t 10 anyref)
-    (func $type-index-empty-vs-i32 (result anyref)
+    (table $t 10 externref)
+    (func $type-index-empty-vs-i32 (result externref)
       (table.get $t)
     )
   )
@@ -49,8 +49,8 @@
 )
 (assert_invalid
   (module
-    (table $t 10 anyref)
-    (func $type-index-f32-vs-i32 (result anyref)
+    (table $t 10 externref)
+    (func $type-index-f32-vs-i32 (result externref)
       (table.get $t (f32.const 1))
     )
   )
@@ -59,8 +59,8 @@
 
 (assert_invalid
   (module
-    (table $t 10 anyref)
-    (func $type-result-anyref-vs-empty
+    (table $t 10 externref)
+    (func $type-result-externref-vs-empty
       (table.get $t (i32.const 0))
     )
   )
@@ -68,8 +68,8 @@
 )
 (assert_invalid
   (module
-    (table $t 10 anyref)
-    (func $type-result-anyref-vs-funcref (result funcref)
+    (table $t 10 externref)
+    (func $type-result-externref-vs-funcref (result funcref)
       (table.get $t (i32.const 1))
     )
   )
@@ -79,8 +79,8 @@
 (assert_invalid
   (module
     (table $t1 1 funcref)
-    (table $t2 1 anyref)
-    (func $type-result-anyref-vs-funcref-multi (result funcref)
+    (table $t2 1 externref)
+    (func $type-result-externref-vs-funcref-multi (result funcref)
       (table.get $t2 (i32.const 0))
     )
   )
diff --git a/test/core/table_grow.wast b/test/core/table_grow.wast
index 26b289d8..2b992ff7 100644
--- a/test/core/table_grow.wast
+++ b/test/core/table_grow.wast
@@ -1,37 +1,37 @@
 (module
-  (table $t 0 anyref)
+  (table $t 0 externref)
 
-  (func (export "get") (param $i i32) (result anyref) (table.get $t (local.get $i)))
-  (func (export "set") (param $i i32) (param $r anyref) (table.set $t (local.get $i) (local.get $r)))
+  (func (export "get") (param $i i32) (result externref) (table.get $t (local.get $i)))
+  (func (export "set") (param $i i32) (param $r externref) (table.set $t (local.get $i) (local.get $r)))
 
-  (func (export "grow") (param $sz i32) (param $init anyref) (result i32)
+  (func (export "grow") (param $sz i32) (param $init externref) (result i32)
     (table.grow $t (local.get $init) (local.get $sz))
   )
   (func (export "size") (result i32) (table.size $t))
 )
 
 (assert_return (invoke "size") (i32.const 0))
-(assert_trap (invoke "set" (i32.const 0) (ref.host 2)) "out of bounds table access")
+(assert_trap (invoke "set" (i32.const 0) (ref.extern 2)) "out of bounds table access")
 (assert_trap (invoke "get" (i32.const 0)) "out of bounds table access")
 
-(assert_return (invoke "grow" (i32.const 1) (ref.null any)) (i32.const 0))
+(assert_return (invoke "grow" (i32.const 1) (ref.null extern)) (i32.const 0))
 (assert_return (invoke "size") (i32.const 1))
-(assert_return (invoke "get" (i32.const 0)) (ref.null any))
-(assert_return (invoke "set" (i32.const 0) (ref.host 2)))
-(assert_return (invoke "get" (i32.const 0)) (ref.host 2))
-(assert_trap (invoke "set" (i32.const 1) (ref.host 2)) "out of bounds table access")
+(assert_return (invoke "get" (i32.const 0)) (ref.null extern))
+(assert_return (invoke "set" (i32.const 0) (ref.extern 2)))
+(assert_return (invoke "get" (i32.const 0)) (ref.extern 2))
+(assert_trap (invoke "set" (i32.const 1) (ref.extern 2)) "out of bounds table access")
 (assert_trap (invoke "get" (i32.const 1)) "out of bounds table access")
 
-(assert_return (invoke "grow" (i32.const 4) (ref.host 3)) (i32.const 1))
+(assert_return (invoke "grow" (i32.const 4) (ref.extern 3)) (i32.const 1))
 (assert_return (invoke "size") (i32.const 5))
-(assert_return (invoke "get" (i32.const 0)) (ref.host 2))
-(assert_return (invoke "set" (i32.const 0) (ref.host 2)))
-(assert_return (invoke "get" (i32.const 0)) (ref.host 2))
-(assert_return (invoke "get" (i32.const 1)) (ref.host 3))
-(assert_return (invoke "get" (i32.const 4)) (ref.host 3))
-(assert_return (invoke "set" (i32.const 4) (ref.host 4)))
-(assert_return (invoke "get" (i32.const 4)) (ref.host 4))
-(assert_trap (invoke "set" (i32.const 5) (ref.host 2)) "out of bounds table access")
+(assert_return (invoke "get" (i32.const 0)) (ref.extern 2))
+(assert_return (invoke "set" (i32.const 0) (ref.extern 2)))
+(assert_return (invoke "get" (i32.const 0)) (ref.extern 2))
+(assert_return (invoke "get" (i32.const 1)) (ref.extern 3))
+(assert_return (invoke "get" (i32.const 4)) (ref.extern 3))
+(assert_return (invoke "set" (i32.const 4) (ref.extern 4)))
+(assert_return (invoke "get" (i32.const 4)) (ref.extern 4))
+(assert_trap (invoke "set" (i32.const 5) (ref.extern 2)) "out of bounds table access")
 (assert_trap (invoke "get" (i32.const 5)) "out of bounds table access")
 
 
@@ -48,9 +48,9 @@
 
 
 (module
-  (table $t 0 anyref)
+  (table $t 0 externref)
   (func (export "grow") (param i32) (result i32)
-    (table.grow $t (ref.null any) (local.get 0))
+    (table.grow $t (ref.null extern) (local.get 0))
   )
 )
 
@@ -62,9 +62,9 @@
 
 
 (module
-  (table $t 0 10 anyref)
+  (table $t 0 10 externref)
   (func (export "grow") (param i32) (result i32)
-    (table.grow $t (ref.null any) (local.get 0))
+    (table.grow $t (ref.null extern) (local.get 0))
   )
 )
 
@@ -109,8 +109,8 @@
 
 (assert_invalid
   (module
-    (table $t 0 anyref)
-    (func $type-init-size-empty-vs-i32-anyref (result i32)
+    (table $t 0 externref)
+    (func $type-init-size-empty-vs-i32-externref (result i32)
       (table.grow $t)
     )
   )
@@ -118,17 +118,17 @@
 )
 (assert_invalid
   (module
-    (table $t 0 anyref)
+    (table $t 0 externref)
     (func $type-size-empty-vs-i32 (result i32)
-      (table.grow $t (ref.null any))
+      (table.grow $t (ref.null extern))
     )
   )
   "type mismatch"
 )
 (assert_invalid
   (module
-    (table $t 0 anyref)
-    (func $type-init-empty-vs-anyref (result i32)
+    (table $t 0 externref)
+    (func $type-init-empty-vs-externref (result i32)
       (table.grow $t (i32.const 1))
     )
   )
@@ -136,9 +136,9 @@
 )
 (assert_invalid
   (module
-    (table $t 0 anyref)
+    (table $t 0 externref)
     (func $type-size-f32-vs-i32 (result i32)
-      (table.grow $t (ref.null any) (f32.const 1))
+      (table.grow $t (ref.null extern) (f32.const 1))
     )
   )
   "type mismatch"
@@ -146,7 +146,7 @@
 (assert_invalid
   (module
     (table $t 0 funcref)
-    (func $type-init-anyref-vs-funcref (param $r anyref) (result i32)
+    (func $type-init-externref-vs-funcref (param $r externref) (result i32)
       (table.grow $t (local.get $r) (i32.const 1))
     )
   )
@@ -155,18 +155,18 @@
 
 (assert_invalid
   (module
-    (table $t 1 anyref)
+    (table $t 1 externref)
     (func $type-result-i32-vs-empty
-      (table.grow $t (ref.null any) (i32.const 0))
+      (table.grow $t (ref.null extern) (i32.const 0))
     )
   )
   "type mismatch"
 )
 (assert_invalid
   (module
-    (table $t 1 anyref)
+    (table $t 1 externref)
     (func $type-result-i32-vs-f32 (result f32)
-      (table.grow $t (ref.null any) (i32.const 0))
+      (table.grow $t (ref.null extern) (i32.const 0))
     )
   )
   "type mismatch"
diff --git a/test/core/table_set.wast b/test/core/table_set.wast
index 2534bdf4..6da9db87 100644
--- a/test/core/table_set.wast
+++ b/test/core/table_set.wast
@@ -1,17 +1,17 @@
 (module
-  (table $t2 1 anyref)
+  (table $t2 1 externref)
   (table $t3 2 funcref)
   (elem (table $t3) (i32.const 1) func $dummy)
   (func $dummy)
 
-  (func (export "get-anyref") (param $i i32) (result anyref)
+  (func (export "get-externref") (param $i i32) (result externref)
     (table.get $t2 (local.get $i))
   )
   (func $f3 (export "get-funcref") (param $i i32) (result funcref)
     (table.get $t3 (local.get $i))
   )
 
-  (func (export "set-anyref") (param $i i32) (param $r anyref)
+  (func (export "set-externref") (param $i i32) (param $r externref)
     (table.set $t2 (local.get $i) (local.get $r))
   )
   (func (export "set-funcref") (param $i i32) (param $r funcref)
@@ -26,11 +26,11 @@
   )
 )
 
-(assert_return (invoke "get-anyref" (i32.const 0)) (ref.null any))
-(assert_return (invoke "set-anyref" (i32.const 0) (ref.host 1)))
-(assert_return (invoke "get-anyref" (i32.const 0)) (ref.host 1))
-(assert_return (invoke "set-anyref" (i32.const 0) (ref.null any)))
-(assert_return (invoke "get-anyref" (i32.const 0)) (ref.null any))
+(assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern))
+(assert_return (invoke "set-externref" (i32.const 0) (ref.extern 1)))
+(assert_return (invoke "get-externref" (i32.const 0)) (ref.extern 1))
+(assert_return (invoke "set-externref" (i32.const 0) (ref.null extern)))
+(assert_return (invoke "get-externref" (i32.const 0)) (ref.null extern))
 
 (assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func))
 (assert_return (invoke "set-funcref-from" (i32.const 0) (i32.const 1)))
@@ -38,14 +38,14 @@
 (assert_return (invoke "set-funcref" (i32.const 0) (ref.null func)))
 (assert_return (invoke "get-funcref" (i32.const 0)) (ref.null func))
 
-(assert_trap (invoke "set-anyref" (i32.const 2) (ref.null any)) "out of bounds")
+(assert_trap (invoke "set-externref" (i32.const 2) (ref.null extern)) "out of bounds")
 (assert_trap (invoke "set-funcref" (i32.const 3) (ref.null func)) "out of bounds")
-(assert_trap (invoke "set-anyref" (i32.const -1) (ref.null any)) "out of bounds")
+(assert_trap (invoke "set-externref" (i32.const -1) (ref.null extern)) "out of bounds")
 (assert_trap (invoke "set-funcref" (i32.const -1) (ref.null func)) "out of bounds")
 
-(assert_trap (invoke "set-anyref" (i32.const 2) (ref.host 0)) "out of bounds")
+(assert_trap (invoke "set-externref" (i32.const 2) (ref.extern 0)) "out of bounds")
 (assert_trap (invoke "set-funcref-from" (i32.const 3) (i32.const 1)) "out of bounds")
-(assert_trap (invoke "set-anyref" (i32.const -1) (ref.host 0)) "out of bounds")
+(assert_trap (invoke "set-externref" (i32.const -1) (ref.extern 0)) "out of bounds")
 (assert_trap (invoke "set-funcref-from" (i32.const -1) (i32.const 1)) "out of bounds")
 
 
@@ -53,8 +53,8 @@
 
 (assert_invalid
   (module
-    (table $t 10 anyref)
-    (func $type-index-value-empty-vs-i32-anyref 
+    (table $t 10 externref)
+    (func $type-index-value-empty-vs-i32-externref
       (table.set $t)
     )
   )
@@ -62,17 +62,17 @@
 )
 (assert_invalid
   (module
-    (table $t 10 anyref)
+    (table $t 10 externref)
     (func $type-index-empty-vs-i32
-      (table.set $t (ref.null any))
+      (table.set $t (ref.null extern))
     )
   )
   "type mismatch"
 )
 (assert_invalid
   (module
-    (table $t 10 anyref)
-    (func $type-value-empty-vs-anyref
+    (table $t 10 externref)
+    (func $type-value-empty-vs-externref
       (table.set $t (i32.const 1))
     )
   )
@@ -80,9 +80,9 @@
 )
 (assert_invalid
   (module
-    (table $t 10 anyref)
+    (table $t 10 externref)
     (func $type-size-f32-vs-i32
-      (table.set $t (f32.const 1) (ref.null any))
+      (table.set $t (f32.const 1) (ref.null extern))
     )
   )
   "type mismatch"
@@ -90,7 +90,7 @@
 (assert_invalid
   (module
     (table $t 10 funcref)
-    (func $type-value-anyref-vs-funcref (param $r anyref)
+    (func $type-value-externref-vs-funcref (param $r externref)
       (table.set $t (i32.const 1) (local.get $r))
     )
   )
@@ -99,9 +99,9 @@
 
 (assert_invalid
   (module
-    (table $t1 1 anyref)
+    (table $t1 1 externref)
     (table $t2 1 funcref)
-    (func $type-value-anyref-vs-funcref-multi (param $r anyref)
+    (func $type-value-externref-vs-funcref-multi (param $r externref)
       (table.set $t2 (i32.const 0) (local.get $r))
     )
   )
@@ -110,9 +110,9 @@
 
 (assert_invalid
   (module
-    (table $t 10 anyref)
+    (table $t 10 externref)
     (func $type-result-empty-vs-num (result i32)
-      (table.set $t (i32.const 0) (ref.null any))
+      (table.set $t (i32.const 0) (ref.null extern))
     )
   )
   "type mismatch"
diff --git a/test/core/table_size.wast b/test/core/table_size.wast
index 8c7cd1eb..ad293b5e 100644
--- a/test/core/table_size.wast
+++ b/test/core/table_size.wast
@@ -1,8 +1,8 @@
 (module
-  (table $t0 0 anyref)
-  (table $t1 1 anyref)
-  (table $t2 0 2 anyref)
-  (table $t3 3 8 anyref)
+  (table $t0 0 externref)
+  (table $t1 1 externref)
+  (table $t2 0 2 externref)
+  (table $t3 3 8 externref)
 
   (func (export "size-t0") (result i32) (table.size $t0))
   (func (export "size-t1") (result i32) (table.size $t1))
@@ -10,16 +10,16 @@
   (func (export "size-t3") (result i32) (table.size $t3))
 
   (func (export "grow-t0") (param $sz i32)
-    (drop (table.grow $t0 (ref.null any) (local.get $sz)))
+    (drop (table.grow $t0 (ref.null extern) (local.get $sz)))
   )
   (func (export "grow-t1") (param $sz i32)
-    (drop (table.grow $t1 (ref.null any) (local.get $sz)))
+    (drop (table.grow $t1 (ref.null extern) (local.get $sz)))
   )
   (func (export "grow-t2") (param $sz i32)
-    (drop (table.grow $t2 (ref.null any) (local.get $sz)))
+    (drop (table.grow $t2 (ref.null extern) (local.get $sz)))
   )
   (func (export "grow-t3") (param $sz i32)
-    (drop (table.grow $t3 (ref.null any) (local.get $sz)))
+    (drop (table.grow $t3 (ref.null extern) (local.get $sz)))
   )
 )
 
@@ -68,7 +68,7 @@
 
 (assert_invalid
   (module
-    (table $t 1 anyref)
+    (table $t 1 externref)
     (func $type-result-i32-vs-empty
       (table.size $t)
     )
@@ -77,7 +77,7 @@
 )
 (assert_invalid
   (module
-    (table $t 1 anyref)
+    (table $t 1 externref)
     (func $type-result-i32-vs-f32 (result f32)
       (table.size $t)
     )

From a5960f46273eb700e51e176cf011acfea096d069 Mon Sep 17 00:00:00 2001
From: Andreas Rossberg 
Date: Thu, 7 May 2020 09:35:58 +0200
Subject: [PATCH 6/6] Comments

---
 document/js-api/index.bs              |  4 ++--
 interpreter/README.md                 |  6 +++---
 proposals/reference-types/Overview.md |  2 +-
 test/core/linking.wast                | 18 +++++++++---------
 test/core/ref_func.wast               |  2 --
 5 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/document/js-api/index.bs b/document/js-api/index.bs
index d7b1b2ba..4ab7e0e5 100644
--- a/document/js-api/index.bs
+++ b/document/js-api/index.bs
@@ -834,7 +834,7 @@ enum ValueType {
   "i64",
   "f32",
   "f64",
-  "anyref",
+  "externref",
   "anyfunc",
 };
 
@@ -898,7 +898,7 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each 1. If |valuetype| equals [=π—‚πŸ¨πŸ¦=], return [=π—‚πŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] 0. 1. If |valuetype| equals [=𝖿πŸ₯𝟀=], return [=𝖿πŸ₯𝟀.π–Όπ—ˆπ—‡π—Œπ—=] 0. 1. If |valuetype| equals [=π–ΏπŸ¨πŸ¦=], return [=π–ΏπŸ¨πŸ¦.π–Όπ—ˆπ—‡π—Œπ—=] 0. - 1. If |valuetype| equals [=anyref=], return [=ToWebAssemblyValue=](undefined, |valuetype|). + 1. If |valuetype| equals [=externref=], return [=ToWebAssemblyValue=](undefined, |valuetype|). 1. Assert: This step is not reached. diff --git a/interpreter/README.md b/interpreter/README.md index 0704b2df..8af4fd77 100644 --- a/interpreter/README.md +++ b/interpreter/README.md @@ -184,8 +184,8 @@ align: align=(1|2|4|8|...) cvtop: trunc | extend | wrap | ... num_type: i32 | i64 | f32 | f64 -ref_kind: any | func -ref_type: anyref | funcref +ref_kind: func | extern +ref_type: funcref | externref val_type: num_type | ref_type block_type : ( result * )* func_type: ( type )? * * @@ -364,7 +364,7 @@ assertion: result: ( .const ) - ( ref.any ) + ( ref.extern ) ( ref.func ) numpat: diff --git a/proposals/reference-types/Overview.md b/proposals/reference-types/Overview.md index 1c8ee29d..14ff3b41 100644 --- a/proposals/reference-types/Overview.md +++ b/proposals/reference-types/Overview.md @@ -46,7 +46,7 @@ Notes: Typing extensions: -* Introduce `funref` and `externref` as a new class of *reference types*. +* Introduce `funcref` and `externref` as a new class of *reference types*. - `reftype ::= funcref | externref` * Value types (of locals, globals, function parameters and results) can now be either numeric types or reference types. diff --git a/test/core/linking.wast b/test/core/linking.wast index 08484781..ed551cb3 100644 --- a/test/core/linking.wast +++ b/test/core/linking.wast @@ -96,21 +96,21 @@ (module $Mref_ex (global (export "g-const-func") funcref (ref.null func)) (global (export "g-var-func") (mut funcref) (ref.null func)) - (global (export "g-const-any") externref (ref.null extern)) - (global (export "g-var-any") (mut externref) (ref.null extern)) + (global (export "g-const-extern") externref (ref.null extern)) + (global (export "g-var-extern") (mut externref) (ref.null extern)) ) (register "Mref_ex" $Mref_ex) (module $Mref_im (global (import "Mref_ex" "g-const-func") funcref) - (global (import "Mref_ex" "g-const-any") externref) + (global (import "Mref_ex" "g-const-extern") externref) (global (import "Mref_ex" "g-var-func") (mut funcref)) - (global (import "Mref_ex" "g-var-any") (mut externref)) + (global (import "Mref_ex" "g-var-extern") (mut externref)) ) (assert_unlinkable - (module (global (import "Mref_ex" "g-const-any") funcref)) + (module (global (import "Mref_ex" "g-const-extern") funcref)) "incompatible import type" ) (assert_unlinkable @@ -124,7 +124,7 @@ "incompatible import type" ) (assert_unlinkable - (module (global (import "Mref_ex" "g-var-any") (mut funcref))) + (module (global (import "Mref_ex" "g-var-extern") (mut funcref))) "incompatible import type" ) @@ -289,13 +289,13 @@ (module $Mtable_ex (table $t1 (export "t-func") 1 funcref) - (table $t2 (export "t-any") 1 externref) + (table $t2 (export "t-extern") 1 externref) ) (register "Mtable_ex" $Mtable_ex) (module (table (import "Mtable_ex" "t-func") 1 funcref) - (table (import "Mtable_ex" "t-any") 1 externref) + (table (import "Mtable_ex" "t-extern") 1 externref) ) (assert_unlinkable @@ -303,7 +303,7 @@ "incompatible import type" ) (assert_unlinkable - (module (table (import "Mtable_ex" "t-any") 1 funcref)) + (module (table (import "Mtable_ex" "t-extern") 1 funcref)) "incompatible import type" ) diff --git a/test/core/ref_func.wast b/test/core/ref_func.wast index 3ace5141..436b3866 100644 --- a/test/core/ref_func.wast +++ b/test/core/ref_func.wast @@ -9,8 +9,6 @@ (i32.add (local.get $x) (i32.const 1)) ) - (global externref (ref.null extern)) - (global externref (ref.null extern)) (global funcref (ref.func $f)) (global funcref (ref.func $g)) (global $v (mut funcref) (ref.func $f))