cmd/compile: allow importing and exporting of ODYNAMICTYPE

Change-Id: I2fca7a801c85ed93c002c23bfcb0cf9593f1bdf4
Reviewed-on: https://go-review.googlesource.com/c/go/+/356571
Trust: Keith Randall <khr@golang.org>
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dan Scales <danscales@google.com>
diff --git a/src/cmd/compile/internal/typecheck/iexport.go b/src/cmd/compile/internal/typecheck/iexport.go
index e3dd10a..46865ba 100644
--- a/src/cmd/compile/internal/typecheck/iexport.go
+++ b/src/cmd/compile/internal/typecheck/iexport.go
@@ -1763,6 +1763,19 @@
 		w.op(ir.OTYPE)
 		w.typ(n.Type())
 
+	case ir.ODYNAMICTYPE:
+		n := n.(*ir.DynamicType)
+		w.op(ir.ODYNAMICTYPE)
+		w.pos(n.Pos())
+		w.expr(n.X)
+		if n.ITab != nil {
+			w.bool(true)
+			w.expr(n.ITab)
+		} else {
+			w.bool(false)
+		}
+		w.typ(n.Type())
+
 	case ir.OTYPESW:
 		n := n.(*ir.TypeSwitchGuard)
 		w.op(ir.OTYPESW)
diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go
index 6351fc3..cb1e56b 100644
--- a/src/cmd/compile/internal/typecheck/iimport.go
+++ b/src/cmd/compile/internal/typecheck/iimport.go
@@ -1312,6 +1312,14 @@
 	case ir.OTYPE:
 		return ir.TypeNode(r.typ())
 
+	case ir.ODYNAMICTYPE:
+		n := ir.NewDynamicType(r.pos(), r.expr())
+		if r.bool() {
+			n.ITab = r.expr()
+		}
+		n.SetType(r.typ())
+		return n
+
 	case ir.OTYPESW:
 		pos := r.pos()
 		var tag *ir.Ident
diff --git a/test/typeparam/issue49027.dir/a.go b/test/typeparam/issue49027.dir/a.go
index d3ec27d..da88297 100644
--- a/test/typeparam/issue49027.dir/a.go
+++ b/test/typeparam/issue49027.dir/a.go
@@ -15,7 +15,41 @@
 func Conv2(v interface{}) (string, bool) {
 	return conv2[string](v)
 }
+
 func conv2[T any](v interface{}) (T, bool) {
 	x, ok := v.(T)
 	return x, ok
 }
+
+func Conv3(v interface{}) string {
+	return conv3[string](v)
+}
+
+func conv3[T any](v interface{}) T {
+	switch v := v.(type) {
+	case T:
+		return v
+	default:
+		var z T
+		return z
+	}
+}
+
+type Mystring string
+
+func (Mystring) Foo() {
+}
+
+func Conv4(v interface{Foo()}) Mystring {
+	return conv4[Mystring](v)
+}
+
+func conv4[T interface{Foo()}](v interface{Foo()}) T {
+	switch v := v.(type) {
+	case T:
+		return v
+	default:
+		var z T
+		return z
+	}
+}
diff --git a/test/typeparam/issue49027.dir/main.go b/test/typeparam/issue49027.dir/main.go
index d0dc33d..aa20a2f 100644
--- a/test/typeparam/issue49027.dir/main.go
+++ b/test/typeparam/issue49027.dir/main.go
@@ -22,4 +22,12 @@
 	if y != s {
 		panic(fmt.Sprintf("got %s wanted %s", y, s))
 	}
+	z := a.Conv3(s)
+	if z != s {
+		panic(fmt.Sprintf("got %s wanted %s", z, s))
+	}
+	w := a.Conv4(a.Mystring(s))
+	if w != a.Mystring(s) {
+		panic(fmt.Sprintf("got %s wanted %s", w, s))
+	}
 }