;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. ;; RUN: foreach %s %t wasm-opt --experimental-type-generalizing -all -S -o - | filecheck %s (module ;; CHECK: (type $void (func)) (type $void (func)) ;; CHECK: (type $1 (func (result eqref))) ;; CHECK: (type $2 (func (param eqref))) ;; CHECK: (type $3 (func (param eqref anyref))) ;; CHECK: (type $4 (func (param anyref))) ;; CHECK: (type $5 (func (param i31ref))) ;; CHECK: (type $6 (func (param anyref eqref))) ;; CHECK: (type $7 (func (result i32))) ;; CHECK: (type $8 (func (result nullref))) ;; CHECK: (type $9 (func (result structref))) ;; CHECK: (type $10 (func (result (ref eq)))) ;; CHECK: (type $11 (func (param (ref noextern)) (result anyref))) ;; CHECK: (type $12 (func (param (ref noextern)) (result (ref any)))) ;; CHECK: (type $13 (func (result externref))) ;; CHECK: (type $14 (func (result (ref extern)))) ;; CHECK: (type $15 (func (param anyref anyref))) ;; CHECK: (global $global-eq (mut eqref) (ref.null none)) (global $global-eq (mut eqref) (ref.null none)) ;; CHECK: (global $global-i32 (mut i32) (i32.const 0)) (global $global-i32 (mut i32) (i32.const 0)) ;; CHECK: (table $func-table 0 0 funcref) (table $func-table 0 0 funcref) ;; CHECK: (table $eq-table 0 0 eqref) (table $eq-table 0 0 eqref) ;; CHECK: (elem declare func $ref-func) ;; CHECK: (func $unconstrained (type $void) ;; CHECK-NEXT: (local $x i32) ;; CHECK-NEXT: (local $y anyref) ;; CHECK-NEXT: (local $z (tuple anyref i32)) ;; CHECK-NEXT: (nop) ;; CHECK-NEXT: ) (func $unconstrained ;; This non-ref local should be unmodified (local $x i32) ;; There is no constraint on the type of this local, so make it top. (local $y i31ref) ;; We cannot optimize tuple locals yet, so leave it unchanged. (local $z (tuple anyref i32)) ) ;; CHECK: (func $implicit-return (type $1) (result eqref) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) (func $implicit-return (result eqref) ;; This will be optimized, but only to eqref because of the constraint from the ;; implicit return. (local $var i31ref) (local.get $var) ) ;; CHECK: (func $implicit-return-unreachable (type $1) (result eqref) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $implicit-return-unreachable (result eqref) ;; We will optimize this all the way to anyref because we don't analyze ;; unreachable code. This would not validate if we didn't run DCE first. (local $var i31ref) (unreachable) (local.get $var) ) ;; CHECK: (func $if (type $1) (result eqref) ;; CHECK-NEXT: (local $x eqref) ;; CHECK-NEXT: (local $y eqref) ;; CHECK-NEXT: (if (result eqref) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (then ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (else ;; CHECK-NEXT: (local.get $y) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $if (result eqref) (local $x i31ref) (local $y i31ref) (if (result i31ref) (i32.const 0) ;; Require that typeof($x) <: eqref. (then (local.get $x) ) ;; Require that typeof($y) <: eqref. (else (local.get $y) ) ) ) ;; CHECK: (func $loop (type $1) (result eqref) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (loop $loop-in (result eqref) ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $loop (result eqref) (local $var i31ref) ;; Require that typeof($var) <: eqref. (loop (result i31ref) (local.get $var) ) ) ;; CHECK: (func $br-sent (type $1) (result eqref) ;; CHECK-NEXT: (local $var1 anyref) ;; CHECK-NEXT: (local $var2 eqref) ;; CHECK-NEXT: (block $l (result eqref) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $var1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $l ;; CHECK-NEXT: (local.get $var2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $br-sent (result eqref) (local $var1 i31ref) (local $var2 i31ref) (block $l (result i31ref) ;; The call will be DCEd out, but this test and the implementation for `br` ;; should be forward-compatible with a future where we do not have to run DCE ;; before this pass. (call $helper-any_any ;; No requirements on $var1 (local.get $var1) ;; Require that typeof($var2) <: eqref. (br $l (local.get $var2) ) ) ) ) ;; CHECK: (func $br-no-sent (type $void) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (block $l ;; CHECK-NEXT: (block ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (br $l) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $br-no-sent (local $var i31ref) (block $l ;; This call is DCEd out just like in the previous test. (call $helper-any_any ;; No requirements on $var (local.get $var) (br $l) ) ) ) ;; CHECK: (func $br_table-sent (type $3) (param $eq eqref) (param $any anyref) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (local.set $eq ;; CHECK-NEXT: (block $l1 (result eqref) ;; CHECK-NEXT: (local.set $any ;; CHECK-NEXT: (block $l2 (result eqref) ;; CHECK-NEXT: (br_table $l1 $l2 ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $br_table-sent (param $eq eqref) (param $any anyref) (local $var i31ref) ;; Require typeof($var) <: eqref. (local.set $eq (block $l1 (result i31ref) ;; Require typeof($var) <: anyref. (local.set $any (block $l2 (result i31ref) (br_table $l1 $l2 (local.get $var) (i32.const 0) ) ) ) (unreachable) ) ) ) ;; CHECK: (func $br_table-sent-reversed (type $3) (param $eq eqref) (param $any anyref) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (local.set $any ;; CHECK-NEXT: (block $l1 (result eqref) ;; CHECK-NEXT: (local.set $eq ;; CHECK-NEXT: (block $l2 (result eqref) ;; CHECK-NEXT: (br_table $l1 $l2 ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $br_table-sent-reversed (param $eq eqref) (param $any anyref) ;; Same as above, but with the sources of requirements flipped. (local $var i31ref) ;; Require typeof($var) <: anyref. (local.set $any (block $l1 (result i31ref) ;; Require typeof($var) <: eqref. (local.set $eq (block $l2 (result i31ref) (br_table $l1 $l2 (local.get $var) (i32.const 0) ) ) ) (unreachable) ) ) ) ;; CHECK: (func $local-set (type $void) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (local.set $var ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $local-set ;; This will be optimized to anyref. (local $var i31ref) ;; Require that (ref i31) <: typeof($var). (local.set $var (i31.new (i32.const 0) ) ) ) ;; CHECK: (func $local-get-set (type $4) (param $dest anyref) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (local.set $dest ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $local-get-set (param $dest anyref) ;; This will be optimized to anyref. (local $var i31ref) ;; Require that typeof($var) <: typeof($dest). (local.set $dest (local.get $var) ) ) ;; CHECK: (func $local-get-set-unreachable (type $5) (param $dest i31ref) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $local-get-set-unreachable (param $dest i31ref) ;; This is not constrained by reachable code, so we will optimize it. (local $var i31ref) (unreachable) ;; This would require that typeof($var) <: typeof($dest), except it is ;; unreachable. This would not validate if we didn't run DCE first. (local.set $dest (local.tee $var (local.get $var) ) ) ) ;; CHECK: (func $local-get-set-join (type $6) (param $dest1 anyref) (param $dest2 eqref) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (local.set $dest1 ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $dest2 ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $local-get-set-join (param $dest1 anyref) (param $dest2 eqref) ;; This wll be optimized to eqref. (local $var i31ref) ;; Require that typeof($var) <: typeof($dest1). (local.set $dest1 (local.get $var) ) ;; Also require that typeof($var) <: typeof($dest2). (local.set $dest2 (local.get $var) ) ) ;; CHECK: (func $local-get-set-chain (type $1) (result eqref) ;; CHECK-NEXT: (local $a eqref) ;; CHECK-NEXT: (local $b eqref) ;; CHECK-NEXT: (local $c eqref) ;; CHECK-NEXT: (local.set $b ;; CHECK-NEXT: (local.get $a) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $c ;; CHECK-NEXT: (local.get $b) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $c) ;; CHECK-NEXT: ) (func $local-get-set-chain (result eqref) (local $a i31ref) (local $b i31ref) (local $c i31ref) ;; Require that typeof($a) <: typeof($b). (local.set $b (local.get $a) ) ;; Require that typeof($b) <: typeof($c). (local.set $c (local.get $b) ) ;; Require that typeof($c) <: eqref. (local.get $c) ) ;; CHECK: (func $local-get-set-chain-out-of-order (type $1) (result eqref) ;; CHECK-NEXT: (local $a eqref) ;; CHECK-NEXT: (local $b eqref) ;; CHECK-NEXT: (local $c eqref) ;; CHECK-NEXT: (local.set $c ;; CHECK-NEXT: (local.get $b) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $b ;; CHECK-NEXT: (local.get $a) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.get $c) ;; CHECK-NEXT: ) (func $local-get-set-chain-out-of-order (result eqref) (local $a i31ref) (local $b i31ref) (local $c i31ref) ;; Require that typeof($b) <: typeof($c). (local.set $c (local.get $b) ) ;; Require that typeof($a) <: typeof($b). We don't know until we evaluate the ;; set above that this will constrain $a to eqref. (local.set $b (local.get $a) ) ;; Require that typeof($c) <: eqref. (local.get $c) ) ;; CHECK: (func $local-tee (type $2) (param $dest eqref) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.tee $dest ;; CHECK-NEXT: (local.tee $var ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $local-tee (param $dest eqref) ;; This will be optimized to eqref. (local $var i31ref) (drop (local.tee $dest (local.tee $var (i31.new (i32.const 0) ) ) ) ) ) ;; CHECK: (func $i31-get (type $void) ;; CHECK-NEXT: (local $nullable i31ref) ;; CHECK-NEXT: (local $nonnullable i31ref) ;; CHECK-NEXT: (local.set $nonnullable ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i31.get_s ;; CHECK-NEXT: (local.get $nullable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i31.get_u ;; CHECK-NEXT: (local.get $nonnullable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $i31-get ;; This must stay an i31ref. (local $nullable i31ref) ;; We relax this one to be nullable i31ref as well. (local $nonnullable (ref i31)) ;; Initialize the non-nullable local for validation purposes. (local.set $nonnullable (i31.new (i32.const 0) ) ) (drop ;; Require that typeof($nullable) <: i31ref. (i31.get_s (local.get $nullable) ) ) (drop ;; Require that typeof($nonnullable) <: i31ref. (i31.get_u (local.get $nonnullable) ) ) ) ;; CHECK: (func $call (type $2) (param $x eqref) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (call $call ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $call (param $x eqref) ;; This will be optimized to eqref. (local $var i31ref) ;; Requires typeof($var) <: eqref. (call $call (local.get $var) ) ) ;; CHECK: (func $call_indirect (type $void) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (call_indirect $func-table (type $2) ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $call_indirect ;; This will be optimized to eqref. (local $var i31ref) ;; Requires typeof($var) <: eqref. (call_indirect (param eqref) (local.get $var) (i32.const 0) ) ) ;; CHECK: (func $global-get (type $void) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (local $i32 i32) ;; CHECK-NEXT: (local.set $var ;; CHECK-NEXT: (global.get $global-eq) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $i32 ;; CHECK-NEXT: (global.get $global-i32) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $global-get (local $var eqref) (local $i32 i32) ;; The global type will remain unchanged and the local will be generalized. (local.set $var (global.get $global-eq) ) ;; Non-reference typed globals are ok, too. (local.set $i32 (global.get $global-i32) ) ) ;; CHECK: (func $global-set (type $void) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (local $i32 i32) ;; CHECK-NEXT: (global.set $global-eq ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (global.set $global-i32 ;; CHECK-NEXT: (local.get $i32) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $global-set (local $var i31ref) (local $i32 i32) ;; Requires typeof($var) <: eqref. (global.set $global-eq (local.get $var) ) ;; Non-reference typed globals are ok, too. (global.set $global-i32 (local.get $i32) ) ) ;; CHECK: (func $select (type $1) (result eqref) ;; CHECK-NEXT: (local $var1 eqref) ;; CHECK-NEXT: (local $var2 eqref) ;; CHECK-NEXT: (select (result eqref) ;; CHECK-NEXT: (local.get $var1) ;; CHECK-NEXT: (local.get $var2) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $select (result eqref) ;; Both of these will be generalized to eqref. (local $var1 i31ref) (local $var2 i31ref) ;; Requires typeof($var1) <: eqref and typeof($var2) <: eqref. (select (result i31ref) (local.get $var1) (local.get $var2) (i32.const 0) ) ) ;; CHECK: (func $ref-null (type $void) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (local.set $var ;; CHECK-NEXT: (ref.null none) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $ref-null (local $var i31ref) ;; No constraints on $var. (local.set $var (ref.null none) ) ) ;; CHECK: (func $ref-is-null (type $void) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.is_null ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $ref-is-null (local $var i31ref) (drop ;; No constraints on $var. (ref.is_null (local.get $var) ) ) ) ;; CHECK: (func $ref-func (type $void) ;; CHECK-NEXT: (local $var funcref) ;; CHECK-NEXT: (local.set $var ;; CHECK-NEXT: (ref.func $ref-func) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $ref-func (local $var (ref null $void)) ;; No constraints on $var. (local.set $var (ref.func $ref-func) ) ) ;; CHECK: (func $ref-eq (type $void) ;; CHECK-NEXT: (local $var1 eqref) ;; CHECK-NEXT: (local $var2 eqref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.eq ;; CHECK-NEXT: (local.get $var1) ;; CHECK-NEXT: (local.get $var2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $ref-eq (local $var1 i31ref) (local $var2 i31ref) (drop ;; Require that typeof($var1) <: eqref and that typeof($var2) <: eqref. (ref.eq (local.get $var1) (local.get $var2) ) ) ) ;; CHECK: (func $table-get (type $void) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (local.set $var ;; CHECK-NEXT: (table.get $eq-table ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $table-get (local $var eqref) ;; No constraints on $var. (local.set $var (table.get $eq-table (i32.const 0) ) ) ) ;; CHECK: (func $table-set (type $void) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (table.set $eq-table ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $table-set (local $var i31ref) ;; Require typeof($var) <: eqref. (table.set $eq-table (i32.const 0) (local.get $var) ) ) ;; CHECK: (func $table-fill (type $void) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (table.fill $eq-table ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $table-fill (local $var i31ref) ;; Require typeof($var) <: eqref. (table.fill $eq-table (i32.const 0) (local.get $var) (i32.const 0) ) ) ;; CHECK: (func $ref-test (type $7) (result i32) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (ref.test nullref ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $ref-test (result i32) (local $var i31ref) ;; No constraint on $var. (ref.test structref (local.get $var) ) ) ;; CHECK: (func $ref-cast (type $void) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.cast i31ref ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $ref-cast (local $var i31ref) ;; No constraint on $var. (drop (ref.cast i31ref (local.get $var) ) ) ) ;; CHECK: (func $ref-cast-limited (type $1) (result eqref) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (ref.cast i31ref ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $ref-cast-limited (result eqref) (local $var i31ref) ;; No constraint on $var. ;; TODO: We could eliminate the cast if we did constrain $var. (ref.cast i31ref (local.get $var) ) ) ;; CHECK: (func $ref-cast-more-limited (type $8) (result nullref) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (ref.cast nullref ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $ref-cast-more-limited (result nullref) (local $var i31ref) ;; No constraint on $var. (ref.cast nullref (local.get $var) ) ) ;; CHECK: (func $ref-cast-lub (type $9) (result structref) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (ref.cast nullref ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $ref-cast-lub (result structref) (local $var i31ref) ;; No constraint on $var. (ref.cast structref (local.get $var) ) ) ;; CHECK: (func $ref-as-non-null (type $10) (result (ref eq)) ;; CHECK-NEXT: (local $var eqref) ;; CHECK-NEXT: (ref.as_non_null ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $ref-as-non-null (result (ref eq)) (local $var i31ref) ;; Require that typeof($var) <: eqref. (ref.as_non_null (local.get $var) ) ) ;; CHECK: (func $any-convert-extern-nullable (type $11) (param $x (ref noextern)) (result anyref) ;; CHECK-NEXT: (local $var externref) ;; CHECK-NEXT: (local.set $var ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (extern.internalize ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $any-convert-extern-nullable (param $x (ref noextern)) (result anyref) (local $var (ref noextern)) (local.set $var (local.get $x) ) ;; Require that typeof($var) <: externref. (extern.internalize (local.get $var) ) ) ;; CHECK: (func $any-convert-extern-non-nullable (type $12) (param $x (ref noextern)) (result (ref any)) ;; CHECK-NEXT: (local $var (ref extern)) ;; CHECK-NEXT: (local.set $var ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (extern.internalize ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $any-convert-extern-non-nullable (param $x (ref noextern)) (result (ref any)) (local $var (ref noextern)) (local.set $var (local.get $x) ) ;; Require that typeof($var) <: (ref extern). (extern.internalize (local.get $var) ) ) ;; CHECK: (func $extern-convert-any-nullable (type $13) (result externref) ;; CHECK-NEXT: (local $var anyref) ;; CHECK-NEXT: (local.set $var ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (extern.externalize ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $extern-convert-any-nullable (result externref) (local $var (ref i31)) (local.set $var (i31.new (i32.const 0) ) ) ;; Require that typeof($var) <: anyref. (extern.externalize (local.get $var) ) ) ;; CHECK: (func $extern-convert-any-non-nullable (type $14) (result (ref extern)) ;; CHECK-NEXT: (local $var (ref any)) ;; CHECK-NEXT: (local.set $var ;; CHECK-NEXT: (ref.i31 ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (extern.externalize ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $extern-convert-any-non-nullable (result (ref extern)) (local $var (ref i31)) (local.set $var (i31.new (i32.const 0) ) ) ;; Require that typeof($var) <: anyref. (extern.externalize (local.get $var) ) ) ;; CHECK: (func $helper-any_any (type $15) (param $0 anyref) (param $1 anyref) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $helper-any_any (param anyref anyref) (unreachable) ) ) (module ;; CHECK: (type $top (sub (func (param i31ref) (result anyref)))) (type $top (sub (func (param i31ref) (result anyref)))) ;; CHECK: (type $mid (sub $top (func (param eqref) (result anyref)))) (type $mid (sub $top (func (param eqref) (result anyref)))) ;; CHECK: (type $2 (func (result eqref))) ;; CHECK: (type $bot (sub $mid (func (param eqref) (result eqref)))) (type $bot (sub $mid (func (param eqref) (result eqref)))) ;; CHECK: (type $4 (func (result anyref))) ;; CHECK: (func $call-ref-params-limited (type $4) (result anyref) ;; CHECK-NEXT: (local $f (ref null $mid)) ;; CHECK-NEXT: (local $arg eqref) ;; CHECK-NEXT: (call_ref $mid ;; CHECK-NEXT: (local.get $arg) ;; CHECK-NEXT: (local.get $f) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $call-ref-params-limited (result anyref) (local $f (ref null $bot)) (local $arg i31ref) ;; Require that typeof($f) <: $mid and that typeof($arg) <: eqref. In ;; principle we could generalize $f up to $top, but then we wouldn't be able ;; to generalize $arg at all. (call_ref $bot (local.get $arg) (local.get $f) ) ) ;; CHECK: (func $call-ref-results-limited (type $2) (result eqref) ;; CHECK-NEXT: (local $f (ref null $bot)) ;; CHECK-NEXT: (local $arg eqref) ;; CHECK-NEXT: (call_ref $bot ;; CHECK-NEXT: (local.get $arg) ;; CHECK-NEXT: (local.get $f) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $call-ref-results-limited (result eqref) (local $f (ref null $bot)) (local $arg i31ref) ;; Require that typeof($f) <: $bot because anything better would require a ;; cast on the output. Also require that typeof($arg) <: eqref. (call_ref $bot (local.get $arg) (local.get $f) ) ) ;; CHECK: (func $call-ref-impossible (type $2) (result eqref) ;; CHECK-NEXT: (local $f nullfuncref) ;; CHECK-NEXT: (local $arg anyref) ;; CHECK-NEXT: (block ;; (replaces unreachable CallRef we can't emit) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $arg) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $f) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $call-ref-impossible (result eqref) (local $f nullfuncref) (local $arg i31ref) ;; Require that typeof($f) <: nullref, but do not constrain $arg because the ;; call_ref will not be reached. (call_ref $bot (local.get $arg) (local.get $f) ) ) ) (module ;; CHECK: (type $top (sub (func (result anyref)))) (type $top (sub (func (result anyref)))) (type $mid (sub $top (func (result eqref)))) (type $bot (sub $mid (func (result i31ref)))) ;; CHECK: (type $1 (func (result anyref))) ;; CHECK: (func $call-ref-no-limit (type $1) (result anyref) ;; CHECK-NEXT: (local $f (ref null $top)) ;; CHECK-NEXT: (call_ref $top ;; CHECK-NEXT: (local.get $f) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $call-ref-no-limit (result anyref) (local $f (ref null $bot)) ;; Require that typeof($f) <: $top because that does not limit us in any way ;; and we cannot possibly do better. (call_ref $bot (local.get $f) ) ) ) (module ;; CHECK: (type $0 (func (result anyref))) ;; CHECK: (type $top (sub (struct (field (mut eqref)) (field eqref)))) (type $top (sub (struct (field (mut eqref)) (field eqref)))) ;; CHECK: (type $mid (sub $top (struct (field (mut eqref)) (field eqref) (field (mut eqref))))) (type $mid (sub $top (struct (field (mut eqref)) (field eqref) (field (mut eqref))))) ;; CHECK: (type $3 (func)) ;; CHECK: (type $bot (sub $mid (struct (field (mut eqref)) (field i31ref) (field (mut eqref))))) (type $bot (sub $mid (struct (field (mut eqref)) (field i31ref) (field (mut eqref))))) ;; CHECK: (type $struct (struct (field eqref) (field anyref))) (type $struct (struct (field eqref) (field anyref))) ;; CHECK: (type $6 (func (result i31ref))) ;; CHECK: (func $struct-new (type $0) (result anyref) ;; CHECK-NEXT: (local $var1 eqref) ;; CHECK-NEXT: (local $var2 anyref) ;; CHECK-NEXT: (struct.new $struct ;; CHECK-NEXT: (local.get $var1) ;; CHECK-NEXT: (local.get $var2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $struct-new (result anyref) (local $var1 i31ref) (local $var2 i31ref) ;; Require that typeof($var1) <: eqref and that typeof($var2) <: anyref. (struct.new $struct (local.get $var1) (local.get $var2) ) ) ;; CHECK: (func $struct-get (type $0) (result anyref) ;; CHECK-NEXT: (local $var (ref null $top)) ;; CHECK-NEXT: (struct.get $top 1 ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $struct-get (result anyref) (local $var (ref null $bot)) ;; Require that typeof($var) <: (ref null $top) because it has a field of the ;; right type at index 1. (struct.get $bot 1 (local.get $var) ) ) ;; CHECK: (func $struct-get-type (type $6) (result i31ref) ;; CHECK-NEXT: (local $var (ref null $bot)) ;; CHECK-NEXT: (struct.get $bot 1 ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $struct-get-type (result i31ref) (local $var (ref null $bot)) ;; Require that typeof($var) <: (ref null $bot) because further supertypes do ;; not satisfy the requirement on the result type. (struct.get $bot 1 (local.get $var) ) ) ;; CHECK: (func $struct-get-index (type $0) (result anyref) ;; CHECK-NEXT: (local $var (ref null $mid)) ;; CHECK-NEXT: (struct.get $mid 2 ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $struct-get-index (result anyref) (local $var (ref null $bot)) ;; Require that typeof($var) <: (ref null $mid) because further supertypes do ;; not have a field at index 2. (struct.get $bot 2 (local.get $var) ) ) ;; CHECK: (func $struct-get-impossible (type $0) (result anyref) ;; CHECK-NEXT: (local $var nullref) ;; CHECK-NEXT: (block ;; (replaces unreachable StructGet we can't emit) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $var) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $struct-get-impossible (result anyref) (local $var nullref) (struct.get $bot 0 (local.get $var) ) ) ;; CHECK: (func $struct-set (type $3) ;; CHECK-NEXT: (local $ref (ref null $top)) ;; CHECK-NEXT: (local $val eqref) ;; CHECK-NEXT: (struct.set $top 0 ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (local.get $val) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $struct-set (local $ref (ref null $bot)) (local $val i31ref) ;; Require that typeof($ref) <: (ref null $top) because it has a field at ;; index 0 and require that typeof($val) <: eqref because that is the type of ;; the field. (struct.set $bot 0 (local.get $ref) (local.get $val) ) ) ;; CHECK: (func $struct-set-index (type $3) ;; CHECK-NEXT: (local $ref (ref null $mid)) ;; CHECK-NEXT: (local $val eqref) ;; CHECK-NEXT: (struct.set $mid 2 ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (local.get $val) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $struct-set-index (local $ref (ref null $bot)) (local $val i31ref) ;; Require that typeof($ref) <: (ref null $mid) because further supertypes do ;; not have a field at index 2 and require that typeof($val) <: eqref because ;; that is the type of the field. (struct.set $bot 2 (local.get $ref) (local.get $val) ) ) ;; CHECK: (func $struct-set-impossible (type $3) ;; CHECK-NEXT: (local $ref nullref) ;; CHECK-NEXT: (local $val anyref) ;; CHECK-NEXT: (block ;; (replaces unreachable StructSet we can't emit) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $val) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $struct-set-impossible (local $ref nullref) (local $val nullref) ;; Require that typeof($ref) <: nullref, but do not constrain $val. (struct.set $bot 0 (local.get $ref) (local.get $val) ) ) ) (module ;; CHECK: (type $0 (func)) ;; CHECK: (type $super-mut (sub (array (mut eqref)))) ;; CHECK: (type $super (sub (array eqref))) (type $super (sub (array (field eqref)))) ;; CHECK: (type $3 (func (result anyref))) ;; CHECK: (type $mut-bytes (sub (array (mut i8)))) ;; CHECK: (type $bytes (sub (array i8))) ;; CHECK: (type $sub (sub $super (array i31ref))) (type $sub (sub $super (array (field i31ref)))) (type $super-mut (sub (array (field (mut eqref))))) (type $sub-mut (sub $super-mut (array (field (mut eqref))))) (type $bytes (sub (array i8))) (type $sub-bytes (sub $bytes (array i8))) (type $mut-bytes (sub (array (mut i8)))) (type $sub-mut-bytes (sub $mut-bytes (array (mut i8)))) ;; CHECK: (data $data "") ;; CHECK: (elem $elem i31ref) (elem $elem i31ref) (data $data "") ;; CHECK: (func $array-new (type $3) (result anyref) ;; CHECK-NEXT: (local $val eqref) ;; CHECK-NEXT: (array.new $super ;; CHECK-NEXT: (local.get $val) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-new (result anyref) (local $val i31ref) ;; Require that typeof($val) <: eqref. (array.new $super (local.get $val) (i32.const 0) ) ) ;; CHECK: (func $array-new-data (type $0) ;; CHECK-NEXT: (local $val anyref) ;; CHECK-NEXT: (local.set $val ;; CHECK-NEXT: (array.new_data $bytes $data ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-new-data (local $val arrayref) ;; No constraint on $val. (local.set $val (array.new_data $bytes $data (i32.const 0) (i32.const 0) ) ) ) ;; CHECK: (func $array-new-elem (type $0) ;; CHECK-NEXT: (local $val anyref) ;; CHECK-NEXT: (local.set $val ;; CHECK-NEXT: (array.new_elem $sub $elem ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-new-elem (local $val arrayref) ;; No constraint on $val. (local.set $val (array.new_elem $sub $elem (i32.const 0) (i32.const 0) ) ) ) ;; CHECK: (func $array-new-fixed (type $3) (result anyref) ;; CHECK-NEXT: (local $val1 eqref) ;; CHECK-NEXT: (local $val2 eqref) ;; CHECK-NEXT: (array.new_fixed $super 2 ;; CHECK-NEXT: (local.get $val1) ;; CHECK-NEXT: (local.get $val2) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-new-fixed (result anyref) (local $val1 i31ref) (local $val2 i31ref) ;; Require that typeof($val1) <: eqref and that typeof($val2) <: eqref. (array.new_fixed $super 2 (local.get $val1) (local.get $val2) ) ) ;; CHECK: (func $array-get (type $3) (result anyref) ;; CHECK-NEXT: (local $val (ref null $super)) ;; CHECK-NEXT: (array.get $super ;; CHECK-NEXT: (local.get $val) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-get (result anyref) (local $val (ref null $sub)) ;; Require that typeof($val) <: (ref null $super). (array.get $sub (local.get $val) (i32.const 0) ) ) ;; CHECK: (func $array-get-impossible (type $3) (result anyref) ;; CHECK-NEXT: (local $val nullref) ;; CHECK-NEXT: (block ;; (replaces unreachable ArrayGet we can't emit) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $val) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-get-impossible (result anyref) (local $val nullref) ;; Require that typeof($val) <: nullref. (array.get $sub (local.get $val) (i32.const 0) ) ) ;; CHECK: (func $array-set (type $0) ;; CHECK-NEXT: (local $ref (ref null $super-mut)) ;; CHECK-NEXT: (local $val eqref) ;; CHECK-NEXT: (array.set $super-mut ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (local.get $val) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-set (local $ref (ref null $sub-mut)) (local $val i31ref) ;; Require that typeof($ref) <: (ref null $super-mut) and that typeof($val) <: ;; eqref. (array.set $sub-mut (local.get $ref) (i32.const 0) (local.get $val) ) ) ;; CHECK: (func $array-set-impossible (type $0) ;; CHECK-NEXT: (local $ref nullref) ;; CHECK-NEXT: (local $val anyref) ;; CHECK-NEXT: (block ;; (replaces unreachable ArraySet we can't emit) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $val) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-set-impossible (local $ref nullref) (local $val i31ref) ;; Require that typeof($ref) <: nullref and do not constrain $ref. (array.set $sub-mut (local.get $ref) (i32.const 0) (local.get $val) ) ) ;; CHECK: (func $array-len (type $0) ;; CHECK-NEXT: (local $ref arrayref) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (array.len ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-len (local $ref (ref null $super)) (drop ;; Require that typeof($ref) <: arrayref. (array.len (local.get $ref) ) ) ) ;; CHECK: (func $array-copy-ref (type $0) ;; CHECK-NEXT: (local $dest (ref null $super-mut)) ;; CHECK-NEXT: (local $src (ref null $super)) ;; CHECK-NEXT: (array.copy $super-mut $super ;; CHECK-NEXT: (local.get $dest) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (local.get $src) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-copy-ref (local $dest (ref null $sub-mut)) (local $src (ref null $sub)) ;; Require that typeof($dest) <: $super-mut and that typeof($src) <: $super. (array.copy $sub-mut $sub (local.get $dest) (i32.const 0) (local.get $src) (i32.const 0) (i32.const 0) ) ) ;; CHECK: (func $array-copy-i8 (type $0) ;; CHECK-NEXT: (local $dest (ref null $mut-bytes)) ;; CHECK-NEXT: (local $src (ref null $bytes)) ;; CHECK-NEXT: (array.copy $mut-bytes $bytes ;; CHECK-NEXT: (local.get $dest) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (local.get $src) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-copy-i8 ;; Same as above, but now the copied element type is not a ref. (local $dest (ref null $sub-mut-bytes)) (local $src (ref null $sub-bytes)) ;; Require that typeof($dest) <: $mut-bytes and that typeof($src) <: $bytes. (array.copy $sub-mut-bytes $sub-bytes (local.get $dest) (i32.const 0) (local.get $src) (i32.const 0) (i32.const 0) ) ) ;; CHECK: (func $array-copy-impossible-dest (type $0) ;; CHECK-NEXT: (local $dest nullref) ;; CHECK-NEXT: (local $src anyref) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.get $dest) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (local.get $src) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-copy-impossible-dest ;; Same as above, but now the dest is bottom. (local $dest nullref) (local $src (ref null $sub)) ;; Require that typeof($dest) <: nullref but do not constrain $src. (array.copy $sub-mut $sub (local.get $dest) (i32.const 0) (local.get $src) (i32.const 0) (i32.const 0) ) ) ;; CHECK: (func $array-copy-impossible-src (type $0) ;; CHECK-NEXT: (local $dest anyref) ;; CHECK-NEXT: (local $src nullref) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.get $dest) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (local.get $src) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-copy-impossible-src ;; Same as above, but now the src is bottom instead. (local $dest (ref null $sub-mut)) (local $src nullref) ;; Require that typeof($src) <: nullref but do not constrain $dest. (array.copy $sub-mut $sub (local.get $dest) (i32.const 0) (local.get $src) (i32.const 0) (i32.const 0) ) ) ;; CHECK: (func $array-copy-impossible-both (type $0) ;; CHECK-NEXT: (local $dest nullref) ;; CHECK-NEXT: (local $src nullref) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.get $dest) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (local.get $src) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-copy-impossible-both ;; Same as above, but now both src and dest are bottom. (local $dest nullref) (local $src nullref) ;; Do not constrain $src or $dest. (array.copy $sub-mut $sub (local.get $dest) (i32.const 0) (local.get $src) (i32.const 0) (i32.const 0) ) ) ;; CHECK: (func $array-fill (type $0) ;; CHECK-NEXT: (local $ref (ref null $super-mut)) ;; CHECK-NEXT: (local $val eqref) ;; CHECK-NEXT: (array.fill $super-mut ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (local.get $val) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-fill (local $ref (ref null $sub-mut)) (local $val i31ref) ;; Require that typeof($ref) <: (ref null $super-mut) and that typeof($val) <: ;; eqref. (array.fill $sub-mut (local.get $ref) (i32.const 0) (local.get $val) (i32.const 0) ) ) ;; CHECK: (func $array-fill-impossible (type $0) ;; CHECK-NEXT: (local $ref nullref) ;; CHECK-NEXT: (local $val anyref) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (local.get $val) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-fill-impossible (local $ref nullref) (local $val i31ref) ;; Require that typeof($ref) <: nullref, but do not constrain $val. (array.fill $sub-mut (local.get $ref) (i32.const 0) (local.get $val) (i32.const 0) ) ) ;; CHECK: (func $array-init-data (type $0) ;; CHECK-NEXT: (local $ref (ref null $mut-bytes)) ;; CHECK-NEXT: (array.init_data $mut-bytes $data ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-init-data (local $ref (ref null $sub-mut-bytes)) ;; Require that typeof($ref) <: (ref null $mut-bytes). (array.init_data $sub-mut-bytes $data (local.get $ref) (i32.const 0) (i32.const 0) (i32.const 0) ) ) ;; CHECK: (func $array-init-data-impossible (type $0) ;; CHECK-NEXT: (local $ref nullref) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-init-data-impossible (local $ref nullref) ;; Require that typeof($ref) <: nullref. (array.init_data $sub-mut-bytes $data (local.get $ref) (i32.const 0) (i32.const 0) (i32.const 0) ) ) ;; CHECK: (func $array-init-elem (type $0) ;; CHECK-NEXT: (local $ref (ref null $super-mut)) ;; CHECK-NEXT: (array.init_elem $super-mut $elem ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-init-elem (local $ref (ref null $sub-mut)) ;; Require that typeof($ref) <: (ref null $super-mut). (array.init_elem $sub-mut $elem (local.get $ref) (i32.const 0) (i32.const 0) (i32.const 0) ) ) ;; CHECK: (func $array-init-elem-impossible (type $0) ;; CHECK-NEXT: (local $ref nullref) ;; CHECK-NEXT: (block ;; CHECK-NEXT: (local.get $ref) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $array-init-elem-impossible (local $ref nullref) ;; Require that typeof($ref) <: nullref. (array.init_elem $sub-mut $elem (local.get $ref) (i32.const 0) (i32.const 0) (i32.const 0) ) ) )