Skip continuation types in SignatureRefining (#8449)
diff --git a/src/passes/SignaturePruning.cpp b/src/passes/SignaturePruning.cpp
index e048b7b..10abe59 100644
--- a/src/passes/SignaturePruning.cpp
+++ b/src/passes/SignaturePruning.cpp
@@ -199,6 +199,17 @@
       allInfo[tag->type].optimizable = false;
     }
 
+    // Continuations must not have params refined, because we do not update
+    // their users (e.g. cont.bind, resume) with new types.
+    // TODO: support refining continuations
+    if (module->features.hasStackSwitching()) {
+      for (auto type : ModuleUtils::collectHeapTypes(*module)) {
+        if (type.isContinuation()) {
+          allInfo[type.getContinuation().type].optimizable = false;
+        }
+      }
+    }
+
     // Signature-called functions must also not be modified.
     // TODO: Explore whether removing parameters from the end could be
     //       beneficial (check if it does not regress call performance with JS).
diff --git a/test/lit/passes/signature-pruning.wast b/test/lit/passes/signature-pruning.wast
index 30ddd25..d86e855 100644
--- a/test/lit/passes/signature-pruning.wast
+++ b/test/lit/passes/signature-pruning.wast
@@ -1269,3 +1269,84 @@
     )
   )
 )
+
+(module
+  ;; If a signature is used in a continuation, we cannot refine its parameters,
+  ;; as we do not yet support updating continuation instructions with new types.
+  (rec
+    ;; CHECK:      (rec
+    ;; CHECK-NEXT:  (type $cont (cont $sig))
+
+    ;; CHECK:       (type $1 (func))
+
+    ;; CHECK:       (type $other (func))
+
+    ;; CHECK:       (type $sig (func (param anyref)))
+    (type $sig (func (param anyref)))
+    (type $other (func (param anyref)))
+    (type $cont (cont $sig))
+  )
+  ;; CHECK:      (elem declare func $cont $not-cont $other)
+
+  ;; CHECK:      (func $cont (type $sig) (param $0 anyref)
+  ;; CHECK-NEXT:  (nop)
+  ;; CHECK-NEXT: )
+  (func $cont (type $sig) (param anyref)
+    ;; The param is unused here, and in all functions below, so we want to
+    ;; remove it where possible.
+    (nop)
+  )
+
+  ;; CHECK:      (func $not-cont (type $sig) (param $0 anyref)
+  ;; CHECK-NEXT:  (nop)
+  ;; CHECK-NEXT: )
+  (func $not-cont (type $sig) (param anyref)
+    ;; This function cannot be optimized even though it is not used in a
+    ;; continuation. It is enough that it shares a type with a continuation
+    ;; function.
+    (nop)
+  )
+
+  ;; CHECK:      (func $other (type $other)
+  ;; CHECK-NEXT:  (local $0 anyref)
+  ;; CHECK-NEXT:  (local.set $0
+  ;; CHECK-NEXT:   (ref.null none)
+  ;; CHECK-NEXT:  )
+  ;; CHECK-NEXT:  (nop)
+  ;; CHECK-NEXT: )
+  (func $other (type $other) (param anyref)
+    ;; This function uses a different type, so it can be optimized.
+    (nop)
+  )
+
+
+  ;; CHECK:      (func $test (type $1)
+  ;; CHECK-NEXT:  (drop
+  ;; CHECK-NEXT:   (cont.new $cont
+  ;; CHECK-NEXT:    (ref.func $cont)
+  ;; CHECK-NEXT:   )
+  ;; CHECK-NEXT:  )
+  ;; CHECK-NEXT:  (call_ref $sig
+  ;; CHECK-NEXT:   (ref.null none)
+  ;; CHECK-NEXT:   (ref.func $not-cont)
+  ;; CHECK-NEXT:  )
+  ;; CHECK-NEXT:  (call_ref $other
+  ;; CHECK-NEXT:   (ref.func $other)
+  ;; CHECK-NEXT:  )
+  ;; CHECK-NEXT: )
+  (func $test
+    (drop
+      (cont.new $cont
+        (ref.func $cont)
+      )
+    )
+    (call_ref $sig
+      (ref.null none)
+      (ref.func $not-cont)
+    )
+    (call_ref $other
+      (ref.null none)
+      (ref.func $other)
+    )
+  )
+)
diff --git a/test/lit/passes/signature-refining.wast b/test/lit/passes/signature-refining.wast
index 26550a6..03742ca 100644
--- a/test/lit/passes/signature-refining.wast
+++ b/test/lit/passes/signature-refining.wast
@@ -1212,7 +1212,7 @@
   (func $not-cont (type $sig) (param anyref)
     ;; This function cannot be optimized even though it is not used in a
     ;; continuation. It is enough that it shares a type with a continuation
-    ;;function.
+    ;; function.
     (nop)
   )