// Before type-checking, the type is Ntype.
type TypeAssertExpr struct {
miniExpr
- X Node
- Ntype Ntype
+ X Node
// Runtime type information provided by walkDotType for
// assertions from non-empty interface to concrete type.
Itab *AddrExpr `mknode:"-"` // *runtime.itab for Type implementing X's type
}
-func NewTypeAssertExpr(pos src.XPos, x Node, typ Ntype) *TypeAssertExpr {
- n := &TypeAssertExpr{X: x, Ntype: typ}
+func NewTypeAssertExpr(pos src.XPos, x Node, typ *types.Type) *TypeAssertExpr {
+ n := &TypeAssertExpr{X: x}
n.pos = pos
n.op = ODOTTYPE
+ if typ != nil {
+ n.SetType(typ)
+ }
return n
}
case ODOTTYPE, ODOTTYPE2:
n := n.(*TypeAssertExpr)
exprFmt(n.X, s, nprec)
- if n.Ntype != nil {
- fmt.Fprintf(s, ".(%v)", n.Ntype)
- return
- }
fmt.Fprintf(s, ".(%v)", n.Type())
case OINDEX, OINDEXMAP:
if n.X != nil && do(n.X) {
return true
}
- if n.Ntype != nil && do(n.Ntype) {
- return true
- }
return false
}
func (n *TypeAssertExpr) editChildren(edit func(Node) Node) {
if n.X != nil {
n.X = edit(n.X).(Node)
}
- if n.Ntype != nil {
- n.Ntype = edit(n.Ntype).(Ntype)
- }
}
func (n *TypeSwitchGuard) Format(s fmt.State, verb rune) { fmtNode(n, s, verb) }
if typ, ok := typ.(*ir.DynamicType); ok && typ.Op() == ir.ODYNAMICTYPE {
return typed(typ.Type(), ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, x, typ.X))
}
- return typecheck.Expr(ir.NewTypeAssertExpr(pos, x, typ.(ir.Ntype)))
+ return typecheck.Expr(ir.NewTypeAssertExpr(pos, x, typ.Type()))
case exprUnaryOp:
op := r.op()
// assertToBound returns a new node that converts a node rcvr with interface type to
// the 'dst' interface type.
func assertToBound(info *instInfo, dictVar *ir.Name, pos src.XPos, rcvr ir.Node, dst *types.Type) ir.Node {
- if dst.HasShape() {
- ix := findDictType(info, dst)
- assert(ix >= 0)
- rt := getDictionaryType(info, dictVar, pos, ix)
- rcvr = ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, rcvr, rt)
- typed(dst, rcvr)
- } else {
- rcvr = ir.NewTypeAssertExpr(pos, rcvr, nil)
- typed(dst, rcvr)
+ if !dst.HasShape() {
+ return typed(dst, ir.NewTypeAssertExpr(pos, rcvr, nil))
}
- return rcvr
+
+ ix := findDictType(info, dst)
+ assert(ix >= 0)
+ rt := getDictionaryType(info, dictVar, pos, ix)
+ return typed(dst, ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, rcvr, rt))
}
return n
}
- if n.Ntype != nil {
- n.Ntype = typecheckNtype(n.Ntype)
- n.SetType(n.Ntype.Type())
- n.Ntype = nil
- if n.Type() == nil {
- return n
- }
- }
+ base.AssertfAt(n.Type() != nil, n.Pos(), "missing type: %v", n)
if n.Type() != nil && !n.Type().IsInterface() {
var missing, have *types.Field
return n
case ir.ODOTTYPE, ir.ODOTTYPE2:
- n := ir.NewTypeAssertExpr(r.pos(), r.expr(), nil)
- n.SetType(r.typ())
+ n := ir.NewTypeAssertExpr(r.pos(), r.expr(), r.typ())
n.SetOp(op)
return n
}
}
-func typecheckNtype(n ir.Ntype) ir.Ntype {
- return typecheck(n, ctxType).(ir.Ntype)
-}
-
// typecheck type checks node n.
// The result of typecheck MUST be assigned back to n, e.g.
//
switch n1.Op() {
case ir.OTYPE:
// Static type assertion (non-generic)
- dot := ir.NewTypeAssertExpr(pos, s.facename, nil)
- dot.SetType(typ) // iface.(type)
+ dot := ir.NewTypeAssertExpr(pos, s.facename, typ) // iface.(type)
as.Rhs = []ir.Node{dot}
case ir.ODYNAMICTYPE:
// Dynamic type assertion (generic)