/* Copyright 2021 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// ./test/core/stack-switching/validation.wast

// ./test/core/stack-switching/validation.wast:8
let $0 = instantiate(`(module
  (type \$ft1 (func))
  (type \$ct1 (cont \$ft1))

  (type \$ft2 (func (param i32) (result i32)))
  (type \$ct2 (cont \$ft2))

  (func \$test
    (param \$p1 (ref cont))
    (param \$p2 (ref nocont))
    (param \$p3 (ref \$ct1))

    (local \$x1 (ref cont))
    (local \$x2 (ref nocont))
    (local \$x3 (ref \$ct1))
    (local \$x4 (ref \$ct2))
    (local \$x5 (ref null \$ct1))

    ;; nocont <: cont
    (local.set \$x1 (local.get \$p2))

    ;; nocont <: \$ct1
    (local.set \$x3 (local.get \$p2))

    ;; \$ct1 <: \$cont
    (local.set \$x3 (local.get \$p3))

    ;; (ref \$ct1) <: (ref null \$cont)
    (local.set \$x5 (local.get \$p3))
   )
)`);

// ./test/core/stack-switching/validation.wast:40
assert_invalid(
  () => instantiate(`(module
    (type \$ft1 (func))
    (type \$ct1 (cont \$ft1))

    (type \$ft2 (func (param i32) (result i32)))
    (type \$ct2 (cont \$ft2))

    (func \$test
      (param \$p1 (ref cont))
      (param \$p2 (ref nocont))
      (param \$p3 (ref \$ct1))

      (local \$x1 (ref cont))
      (local \$x2 (ref nocont))
      (local \$x3 (ref \$ct1))
      (local \$x4 (ref \$ct2))
      (local \$x5 (ref null \$ct1))

      ;; cont </: nocont
      (local.set \$p2 (local.get \$p1))
     )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:66
assert_invalid(
  () => instantiate(`(module
    (type \$ft1 (func))
    (type \$ct1 (cont \$ft1))

    (type \$ft2 (func (param i32) (result i32)))
    (type \$ct2 (cont \$ft2))

    (func \$test
      (param \$p1 (ref cont))
      (param \$p2 (ref nocont))
      (param \$p3 (ref \$ct1))

      (local \$x1 (ref cont))
      (local \$x2 (ref nocont))
      (local \$x3 (ref \$ct1))
      (local \$x4 (ref \$ct2))
      (local \$x5 (ref null \$ct1))

      ;; \$ct1 </: nocont
      (local.set \$p2 (local.get \$p3))
     )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:92
assert_invalid(
  () => instantiate(`(module
    (type \$ft1 (func))
    (type \$ct1 (cont \$ft1))

    (type \$ft2 (func (param i32) (result i32)))
    (type \$ct2 (cont \$ft2))

    (func \$test
      (param \$p1 (ref cont))
      (param \$p2 (ref nocont))
      (param \$p3 (ref \$ct1))

      (local \$x1 (ref cont))
      (local \$x2 (ref nocont))
      (local \$x3 (ref \$ct1))
      (local \$x4 (ref \$ct2))
      (local \$x5 (ref null \$ct1))

      ;; \$cont </: \$ct1
      (local.set \$p3 (local.get \$p1))
     )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:118
assert_invalid(
  () => instantiate(`(module
    (type \$ft1 (func))
    (type \$ct1 (cont \$ft1))

    (type \$ft2 (func (param i32) (result i32)))
    (type \$ct2 (cont \$ft2))

    (func \$test
      (param \$p1 (ref cont))
      (param \$p2 (ref nocont))
      (param \$p3 (ref \$ct1))
      (param \$p4 (ref \$ct2))
      (param \$p5 (ref null \$ct1))


      (local \$x1 (ref cont))
      (local \$x2 (ref nocont))
      (local \$x3 (ref \$ct1))
      (local \$x4 (ref \$ct2))
      (local \$x5 (ref null \$ct1))

      ;; (ref null \$ct1) </: (ref \$cont)
      (local.set \$x3 (local.get \$p5))
     )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:147
assert_invalid(
  () => instantiate(`(module
    (type \$ft1 (func))
    (type \$ct1 (cont \$ft1))

    (type \$ft2 (func (param i32) (result i32)))
    (type \$ct2 (cont \$ft2))

    (func \$test
      (param \$p1 (ref cont))
      (param \$p2 (ref nocont))
      (param \$p3 (ref \$ct1))
      (param \$p4 (ref \$ct2))
      (param \$p5 (ref null \$ct1))


      (local \$x1 (ref cont))
      (local \$x2 (ref nocont))
      (local \$x3 (ref \$ct1))
      (local \$x4 (ref \$ct2))
      (local \$x5 (ref null \$ct1))

      ;; (ref \$ct1) </: (ref \$ct2)
      (local.set \$p4 (local.get \$p3))
     )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:180
let $1 = instantiate(`(module
  (type \$ft0 (func (result i32)))
  (type \$ct0 (cont \$ft0))

  (type \$ft1 (func (param i32) (result i32)))
  (type \$ct1 (cont \$ft1))

  (type \$ft2 (func (param i64 i32) (result i32)))
  (type \$ct2 (cont \$ft2))


  (func \$test1
    (param \$p_ct1 (ref null \$ct1))
    (result (ref \$ct0))

    ;; cont.bind takes nullable ref, returns non-nullable one
    (i32.const 123)
    (local.get \$p_ct1)
    (cont.bind \$ct1 \$ct0)
  )

  (func \$test2
    (param \$p_ct2 (ref \$ct2))
    (result (ref \$ct1))

    ;; cont.bind does not have to apply continuation fully
    (i64.const 123)
    (local.get \$p_ct2)
    (cont.bind \$ct2 \$ct1)
  )

  (func \$test3
    (param \$p_ct1 (ref \$ct1))
    (result (ref \$ct1))

    ;; cont.bind can take same type twice, not actually apply anything
    (local.get \$p_ct1)
    (cont.bind \$ct1 \$ct1)
  )


 )`);

// ./test/core/stack-switching/validation.wast:223
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func (result i32)))
    (type \$ct0 (cont \$ft0))

    (func \$error
      (param \$p_ft0 (ref \$ft0))
      ;; error: non-continuation type on cont.bind
      (local.get \$p_ft0)
      (cont.bind \$ft0 \$ft0)
      (drop)
    )
  )`),
  `non-continuation type`,
);

// ./test/core/stack-switching/validation.wast:244
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func (result i32)))
    (type \$ct0 (cont \$ft0))

    (type \$ft1 (func (param i32) (result i32)))
    (type \$ct1 (cont \$ft1))

    (func \$error
      (param \$p_ct1 (ref \$ct1))
      ;; cont.bind type mismatch: passing wrong kind of continuation.
      ;; This is actually just checking type-matching, not cont.bind specific.
      (local.get \$p_ct1)
      (cont.bind \$ct0 \$ct0)
      (drop)
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:265
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func (result i32)))
    (type \$ct0 (cont \$ft0))

    (type \$ft1 (func (param i32) (result i32)))
    (type \$ct1 (cont \$ft1))

    (type \$ft2 (func (param i64 i32) (result i32)))
    (type \$ct2 (cont \$ft2))


    (type \$ft1_alt (func (param i64) (result i32)))
    (type \$ct1_alt (cont \$ft1_alt))

    (func \$error
      (param \$p_ct2 (ref \$ct2))
      ;; error: two continuation types not agreeing on arg types
      (i64.const 123)
      (local.get \$p_ct2)
      (cont.bind \$ct2 \$ct1_alt)
      (drop)
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:293
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func (result i32)))
    (type \$ct0 (cont \$ft0))

    (type \$ft1 (func (param i32) (result i32)))
    (type \$ct1 (cont \$ft1))

    (type \$ft2 (func (param i64 i32) (result i32)))
    (type \$ct2 (cont \$ft2))


    (type \$ft1_alt (func (param i32) (result i64)))
    (type \$ct1_alt (cont \$ft1_alt))

    (func \$error
      (param \$p_ct2 (ref \$ct2))
      ;; error: two continuation types not agreeing on return types
      (i64.const 123)
      (local.get \$p_ct2)
      (cont.bind \$ct2 \$ct1_alt)
      (drop)
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:321
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func (result i32)))
    (type \$ct0 (cont \$ft0))

    (type \$ft1 (func (param i32) (result i32)))
    (type \$ct1 (cont \$ft1))

    (func \$error
      (param \$p_ct0 (ref \$ct0))
      ;; error: trying to go from 0 to 1 args
      (local.get \$p_ct0)
      (cont.bind \$ct0 \$ct1)
      (drop)
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:341
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func (result i32)))
    (type \$ct0 (cont \$ft0))

    (type \$ft1 (func (param i32) (result i32)))
    (type \$ct1 (cont \$ft1))


    (func \$error
      (param \$p_ct1 (ref \$ct1))
      ;; error: Insufficient arguments::
      ;; This is really testing the general application of arguments to instructions,
      ;; but trying to trick parsers of the folded form
      (cont.bind \$ct1 \$ct0 (local.get \$p_ct1))
      (drop)
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:363
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func (result i32)))
    (type \$ct0 (cont \$ft0))

    (type \$ft1 (func (param i32) (result i32)))
    (type \$ct1 (cont \$ft1))

    (func \$error
      (param \$p_ct1 (ref \$ct1))
      ;; error: Too many arguments::
      ;; This is really testing the general application of arguments to instructions,
      ;; but trying to trick parsers of the folded form
      (cont.bind \$ct1 \$ct0 (i32.const 123) (i32.const 123) (local.get \$p_ct1))
      (drop)
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:388
let $2 = instantiate(`(module
  (type \$ft1 (func (param i32) (result i32)))
  (type \$ct1 (cont \$ft1))

  (type \$ft2 (func (param i32 i32) (result i32)))
  (type \$ct2 (cont \$ft2))

  (func \$f1 (export "f1") (param i32) (result i32)
    (i32.const 123)
  )

  (func \$drop_ct1 (param \$c (ref \$ct1)))

  ;; simple smoke test
  (func \$test_good1 (param \$x (ref \$ft1)) (result (ref \$ct1))
    (local.get \$x)
    (cont.new \$ct1)
  )

  ;; cont.new takes a nullable function
  (func \$test_good2 (param \$x (ref null \$ft1)) (result (ref \$ct1))
    (local.get \$x)
    (cont.new \$ct1)
  )


)`);

// ./test/core/stack-switching/validation.wast:416
assert_invalid(
  () => instantiate(`(module
    (type \$ft1 (func (param i32) (result i32)))
    (type \$ct1 (cont \$ft1))

    (func \$bad (param \$x (ref null \$ct1)) (result (ref \$ct1))
      (local.get \$x)
      (cont.new \$ct1)
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:432
assert_invalid(
  () => instantiate(`(module
    (type \$ft1 (func (param i32) (result i32)))
    (type \$ct1 (cont \$ft1))

    (type \$ft2 (func (param i32 i32) (result i32)))
    (type \$ct2 (cont \$ft2))

    (func \$drop_ct1 (param \$c (ref \$ct1)))

    (func \$bad (param \$x (ref null \$ft2)) (result (ref \$ct1))
      (local.get \$x)
      (cont.new \$ct1)
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:453
assert_invalid(
  () => instantiate(`(module
    (type \$ft1 (func (param i32) (result i32)))
    (type \$ct1 (cont \$ft1))

    (func \$bad (param \$x (ref null \$ct1))
      (local.get \$x)
      (cont.new \$ft1)
      (drop)
    )
  )`),
  `non-continuation type 0`,
);

// ./test/core/stack-switching/validation.wast:473
let $3 = instantiate(`(module
  (type \$ft0 (func))
  (type \$ct0 (cont \$ft0))

  (type \$ft1 (func (param f32) (result f64)))
  (type \$ct1 (cont \$ft1))

  (type \$ft2 (func (param i64) (result f64)))
  (type \$ct2 (cont \$ft2))

  (type \$ft3 (func (param i32) (result f64)))
  (type \$ct3 (cont \$ft3))

  (tag \$t0)
  (tag \$t1)
  (tag \$t2 (param i32) (result i64))
  (tag \$t3 (param i64) (result i32))

  ;; Multiple tags, all types handled correctly
  (func \$test0 (param \$x (ref \$ct1)) (result f64)
    (block \$handler0 (result i32 (ref \$ct2))
      (block \$handler1 (result i64 (ref \$ct3))
        (f32.const 1.23)
        (local.get \$x)
        (resume \$ct1 (on \$t2 \$handler0) (on \$t3 \$handler1))
        (return)
      )
      (unreachable)
    )
    (unreachable)
  )

  ;; Same as \$test0, but we provide two handlers for the same tag
  (func \$test1 (param \$x (ref \$ct1)) (result f64)
    (block \$handler0 (result i32 (ref \$ct2))
      (block \$handler1 (result i32 (ref \$ct2))
        (f32.const 1.23)
        (local.get \$x)
        (resume \$ct1 (on \$t2 \$handler0) (on \$t2 \$handler1))
        (return)
      )
      (unreachable)
    )
    (unreachable)
  )

  ;; resume takes a nullable reference
  (func \$test2 (param \$x (ref null \$ct0))
    (local.get \$x)
    (resume \$ct0)
  )

  ;; handler blocks take the continuation as nullable ref
  (func \$test3 (param \$x (ref \$ct0))
    (block \$handler (result (ref null \$ct0))
      (local.get \$x)
      (resume \$ct0 (on \$t0 \$handler))
      (return)
    )
    (unreachable)
  )

  ;; Nothing wrong with using the same handler block for multiple tags
  (func \$test4 (param \$x (ref \$ct0))
    (block \$handler (result (ref null \$ct0))
      (local.get \$x)
      (resume \$ct0 (on \$t0 \$handler) (on \$t1 \$handler))
      (return)
    )
    (unreachable)
  )

  ;; handler block can have params
  (func \$test5 (param \$x (ref \$ct0))
    (local.get \$x)
    (block \$handler (param (ref \$ct0)) (result (ref \$ct0))
      (resume \$ct0 (on \$t0 \$handler))
      (return)
    )
    (unreachable)
  )
)`);

// ./test/core/stack-switching/validation.wast:557
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func))
    (type \$ct0 (cont \$ft0))
    ;;(tag \$t0)
    (func \$error (param \$x (ref \$ct0))
      (block \$handler (result (ref null \$ct0))
        (local.get \$x)
        (resume \$ct0 (on 0 \$handler))
        (return)
      )
      (unreachable)
    )

  )`),
  `unknown tag`,
);

// ./test/core/stack-switching/validation.wast:576
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func))
    (type \$ct0 (cont \$ft0))
    (func \$error (param \$x (ref \$ct0))
      (local.get \$x)
      (resume \$ft0)
    )

  )`),
  `non-continuation type`,
);

// ./test/core/stack-switching/validation.wast:590
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func))
    (type \$ct0 (cont \$ft0))
    (tag \$t0)
    (func \$test1 (param \$x (ref \$ct0))
      (block \$handler (result (ref \$ft0))
        (local.get \$x)
        (resume \$ct0 (on \$t0 \$handler))
        (return)
      )
      (unreachable)
    )

  )`),
  `non-continuation type`,
);

// ./test/core/stack-switching/validation.wast:608
assert_invalid(
  () => instantiate(`(module
    (type \$ft (func (param i32)))
    (type \$ct (cont \$ft))

    (func \$error
      (param \$p (ref \$ct))
      ;; error: Too many arguments::
      ;; This is really testing the general application of arguments to instructions,
      ;; but trying to trick parsers of the folded form
      (resume \$ct (i32.const 123) (i32.const 123) (local.get \$p))
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:624
assert_invalid(
  () => instantiate(`(module
    (type \$ft (func (param i32)))
    (type \$ct (cont \$ft))

    (func \$error
      (param \$p (ref \$ct))
      ;; error: Too few arguments::
      ;; This is really testing the general application of arguments to instructions,
      ;; but trying to trick parsers of the folded form
      (resume \$ct (local.get \$p))
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:640
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func (param i32)))
    (type \$ct0 (cont \$ft0))

    (type \$ft1 (func (param i64)))
    (type \$ct1 (cont \$ft1))

    (func \$error
      (param \$p (ref \$ct1))
      ;; error: Mismatch between annotation on resume and actual argument
      ;; This is really testing the general application of arguments to instructions.
      (resume \$ct0 (i32.const 123) (local.get \$p))
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:658
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func))
    (type \$ct0 (cont \$ft0))

    (tag \$t (param i32))

    (func \$error
      (param \$p (ref \$ct0))
      (block \$handler (result (ref \$ct0))
        ;; error: handler block has insufficient number of results
        (local.get \$p)
        (resume \$ct0 (on \$t \$handler))
        (return)
      )
      (unreachable)
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:679
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func))
    (type \$ct0 (cont \$ft0))

    (tag \$t (param i32))

    (func \$error
      (param \$p (ref \$ct0))
      (block \$handler (result i32 i32 (ref \$ct0))
        ;; error: handler block has too many results
        (local.get \$p)
        (resume \$ct0 (on \$t \$handler))
        (return)
      )
      (unreachable)
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:700
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func))
    (type \$ct0 (cont \$ft0))

    (tag \$t (param i32))

    (func \$error
      (param \$p (ref \$ct0))
      (block \$handler (result i64 (ref \$ct0))
        ;; error: type mismatch in non-continuation handler result type
        (local.get \$p)
        (resume \$ct0 (on \$t \$handler))
        (return)
      )
      (unreachable)
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:721
assert_invalid(
  () => instantiate(`(module
    (type \$ft0 (func))
    (type \$ct0 (cont \$ft0))

    (type \$ft1 (func (param i32)))
    (type \$ct1 (cont \$ft1))

    (tag \$t (param i32))

    (func \$error
      (param \$p (ref \$ct0))
      (block \$handler (result i32 (ref \$ct1))
        ;; error: type mismatch in continuation handler result type
        (local.get \$p)
        (resume \$ct0 (on \$t \$handler))
        (return)
      )
      (unreachable)
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:749
let $4 = instantiate(`(module
  (tag \$t (param i64 i32) (result i32 i64))

  (func \$test (result i32 i64)
    (i64.const 123)
    (i32.const 123)
    (suspend \$t)
  )
)`);

// ./test/core/stack-switching/validation.wast:760
assert_invalid(
  () => instantiate(`(module
    (tag \$t (param i64 i32) (result i32 i64))

    (func \$test (result i32 i64)
      ;; error: Insufficient arguments::
      ;; This is really testing the general application of arguments to instructions,
      ;; but trying to trick parsers of the folded form

      (suspend \$t (i64.const 123))
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:775
assert_invalid(
  () => instantiate(`(module
    (tag \$t (param i32) (result i32 i64))

    (func \$test (result i32 i64)
      ;; error: Too many arguments:
      ;; This is really testing the general application of arguments to instructions,
      ;; but trying to trick parsers of the folded form

      (suspend \$t (i64.const 123) (i32.const 123))
    )
  )`),
  `type mismatch`,
);

// ./test/core/stack-switching/validation.wast:790
assert_invalid(
  () => instantiate(`(module
    (func \$test
      ;; error: Tag does not exist
      (suspend 0)
    )
  )`),
  `unknown tag`,
);

// ./test/core/stack-switching/validation.wast:803
assert_invalid(
  () => instantiate(`(module
    (func (drop (ref.test contref (unreachable))))
  )`),
  `invalid cast`,
);

// ./test/core/stack-switching/validation.wast:809
assert_invalid(
  () => instantiate(`(module
    (func (drop (ref.test nullcontref (unreachable))))
  )`),
  `invalid cast`,
);

// ./test/core/stack-switching/validation.wast:815
assert_invalid(
  () => instantiate(`(module
    (type \$f (func))
    (type \$c (cont \$f))
    (func (drop (ref.test (ref \$c) (unreachable))))
  )`),
  `invalid cast`,
);

// ./test/core/stack-switching/validation.wast:824
assert_invalid(
  () => instantiate(`(module
    (func (drop (ref.cast contref (unreachable))))
  )`),
  `invalid cast`,
);

// ./test/core/stack-switching/validation.wast:830
assert_invalid(
  () => instantiate(`(module
    (func (drop (ref.cast nullcontref (unreachable))))
  )`),
  `invalid cast`,
);

// ./test/core/stack-switching/validation.wast:836
assert_invalid(
  () => instantiate(`(module
    (type \$f (func))
    (type \$c (cont \$f))
    (func (drop (ref.cast (ref \$c) (unreachable))))
  )`),
  `invalid cast`,
);

// ./test/core/stack-switching/validation.wast:845
assert_invalid(
  () => instantiate(`(module
    (func
      (block (result contref) (br_on_cast 0 contref contref (unreachable)))
      (drop)
    )
  )`),
  `invalid cast`,
);

// ./test/core/stack-switching/validation.wast:854
assert_invalid(
  () => instantiate(`(module
    (func
      (block (result contref) (br_on_cast 0 nullcontref nullcontref (unreachable)))
      (drop)
    )
  )`),
  `invalid cast`,
);

// ./test/core/stack-switching/validation.wast:863
assert_invalid(
  () => instantiate(`(module
    (type \$f (func))
    (type \$c (cont \$f))
    (func
      (block (result contref) (br_on_cast 0 (ref \$c) (ref \$c) (unreachable)))
      (drop)
    )
  )`),
  `invalid cast`,
);

// ./test/core/stack-switching/validation.wast:875
assert_invalid(
  () => instantiate(`(module
    (func
      (block (result contref) (br_on_cast_fail 0 contref contref (unreachable)))
      (drop)
    )
  )`),
  `invalid cast`,
);

// ./test/core/stack-switching/validation.wast:884
assert_invalid(
  () => instantiate(`(module
    (func
      (block (result contref) (br_on_cast_fail 0 nullcontref nullcontref (unreachable)))
      (drop)
    )
  )`),
  `invalid cast`,
);

// ./test/core/stack-switching/validation.wast:893
assert_invalid(
  () => instantiate(`(module
    (type \$f (func))
    (type \$c (cont \$f))
    (func
      (block (result contref) (br_on_cast_fail 0 (ref \$c) (ref \$c) (unreachable)))
      (drop)
    )
  )`),
  `invalid cast`,
);
