;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited.
;; RUN: wasm-opt %s -all --disable-custom-descriptors --dae --type-ssa -S -o - | filecheck %s

(module
  ;; CHECK:      (type $struct (struct))
  (type $struct (struct))

  ;; CHECK:      (type $array (sub (array (mut i32))))
  (type $array (sub (array (mut i32))))

  ;; Trigger TypeSSA
  ;; CHECK:      (type $2 (func))

  ;; CHECK:      (type $3 (func (result i32 (ref (exact $struct)))))

  ;; CHECK:      (type $array_1 (sub $array (array (mut i32))))

  ;; CHECK:      (type $5 (func (result i32 (ref $struct))))

  ;; CHECK:      (global $array (ref $array) (array.new $array_1
  ;; CHECK-NEXT:  (i32.const 0)
  ;; CHECK-NEXT:  (i32.const 0)
  ;; CHECK-NEXT: ))
  (global $array (ref $array)
    (array.new $array
      (i32.const 0)
      (i32.const 0)
    )
  )

  ;; CHECK:      (func $caller (type $2)
  ;; CHECK-NEXT:  (call $callee)
  ;; CHECK-NEXT: )
  (func $caller
    ;; Give DAE a constant null parameter to optimize.
    (tuple.drop 2
      (call $callee
        (ref.null none)
      )
    )
  )

  ;; CHECK:      (func $callee (type $2)
  ;; CHECK-NEXT:  (local $0 anyref)
  ;; CHECK-NEXT:  (tuple.drop 2
  ;; CHECK-NEXT:   (block (type $3) (result i32 (ref (exact $struct)))
  ;; CHECK-NEXT:    (local.set $0
  ;; CHECK-NEXT:     (ref.null none)
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:    (block (type $3) (result i32 (ref (exact $struct)))
  ;; CHECK-NEXT:     (tuple.make 2
  ;; CHECK-NEXT:      (i32.const 0)
  ;; CHECK-NEXT:      (struct.new_default $struct)
  ;; CHECK-NEXT:     )
  ;; CHECK-NEXT:    )
  ;; CHECK-NEXT:   )
  ;; CHECK-NEXT:  )
  ;; CHECK-NEXT: )
  (func $callee (param (ref null any)) (result i32 (ref $struct))
    ;; When applying the constant null, DAE will create a block with
    ;; (result i32 (ref (exact $struct)))
    (block (result i32 (ref $struct))
      (tuple.make 2
        (i32.const 0)
        (struct.new_default $struct)
      )
    )
  )

  ;; CHECK:      (func $other (type $5) (result i32 (ref $struct))
  ;; CHECK-NEXT:  (unreachable)
  ;; CHECK-NEXT: )
  (func $other (result i32 (ref $struct))
    ;; This will keep the (result i32 (ref $struct)) signature, which will
    ;; conflict with the (result i32 (ref (exact $struct))) of the block above
    ;; after binary writing. This will not be observable, though, since DAE only
    ;; optimizes non-referenced functions. TypeSSA should not crash or fail an
    ;; assertion due to the repeated type shape.
    (unreachable)
  )
)
