From: Matthew Dempsky Date: Sat, 14 Nov 2020 04:38:21 +0000 (-0800) Subject: [dev.regabi] cmd/compile: replace CTNIL with ONIL X-Git-Tag: go1.17beta1~1539^2~471 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=88a9e2f9ad0ad3ef1e254e9150f4649e57b0a296;p=gostls13.git [dev.regabi] cmd/compile: replace CTNIL with ONIL Properly speaking, "nil" is a zero value, not a constant. So go/constant does not have a representation for it. To allow replacing Val with constant.Value, we split out ONIL separately from OLITERAL so we can get rid of CTNIL. Passes toolstash-check. Change-Id: I4c8e60cae3b3c91bbac43b3b0cf2a4ade028d6cb Reviewed-on: https://go-review.googlesource.com/c/go/+/272650 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Trust: Matthew Dempsky --- diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index b92c8d66b5..42ac3a26f8 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -24,7 +24,6 @@ const ( CTCPLX CTSTR CTBOOL - CTNIL ) type Val struct { @@ -34,7 +33,6 @@ type Val struct { // *Mpflt float when Ctype() == CTFLT // *Mpcplx pair of floats when Ctype() == CTCPLX // string string when Ctype() == CTSTR - // *Nilval when Ctype() == CTNIL U interface{} } @@ -45,8 +43,6 @@ func (v Val) Ctype() Ctype { panic("unreachable") case nil: return CTxxx - case *NilVal: - return CTNIL case bool: return CTBOOL case *Mpint: @@ -71,8 +67,6 @@ func eqval(a, b Val) bool { default: Fatalf("unexpected Ctype for %T", a.U) panic("unreachable") - case *NilVal: - return true case bool: y := b.U.(bool) return x == y @@ -99,8 +93,6 @@ func (v Val) Interface() interface{} { default: Fatalf("unexpected Interface for %T", v.U) panic("unreachable") - case *NilVal: - return nil case bool, string: return x case *Mpint: @@ -112,8 +104,6 @@ func (v Val) Interface() interface{} { } } -type NilVal struct{} - // Int64Val returns n as an int64. // n must be an integer or rune constant. func (n *Node) Int64Val() int64 { @@ -245,7 +235,7 @@ func convlit1(n *Node, t *types.Type, explicit bool, context func() string) *Nod return n } - if n.Op == OLITERAL { + if n.Op == OLITERAL || n.Op == ONIL { // Can't always set n.Type directly on OLITERAL nodes. // See discussion on CL 20813. n = n.rawcopy() @@ -253,6 +243,9 @@ func convlit1(n *Node, t *types.Type, explicit bool, context func() string) *Nod // Nil is technically not a constant, so handle it specially. if n.Type.Etype == TNIL { + if n.Op != ONIL { + Fatalf("unexpected op: %v (%v)", n, n.Op) + } if t == nil { yyerror("use of untyped nil") n.SetDiag(true) @@ -1039,8 +1032,6 @@ func idealType(ct Ctype) *types.Type { return types.UntypedFloat case CTCPLX: return types.UntypedComplex - case CTNIL: - return types.Types[TNIL] } Fatalf("unexpected Ctype: %v", ct) return nil @@ -1189,7 +1180,7 @@ func indexconst(n *Node) int64 { // Expressions derived from nil, like string([]byte(nil)), while they // may be known at compile time, are not Go language constants. func (n *Node) isGoConst() bool { - return n.Op == OLITERAL && n.Val().Ctype() != CTNIL + return n.Op == OLITERAL } func hascallchan(n *Node) bool { diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go index 6f328ab5ea..b7d1dfc92a 100644 --- a/src/cmd/compile/internal/gc/esc.go +++ b/src/cmd/compile/internal/gc/esc.go @@ -152,7 +152,7 @@ func mayAffectMemory(n *Node) bool { // We're ignoring things like division by zero, index out of range, // and nil pointer dereference here. switch n.Op { - case ONAME, OCLOSUREVAR, OLITERAL: + case ONAME, OCLOSUREVAR, OLITERAL, ONIL: return false // Left+Right group. diff --git a/src/cmd/compile/internal/gc/escape.go b/src/cmd/compile/internal/gc/escape.go index 757b4652ca..bc0eb98d76 100644 --- a/src/cmd/compile/internal/gc/escape.go +++ b/src/cmd/compile/internal/gc/escape.go @@ -476,7 +476,7 @@ func (e *Escape) exprSkipInit(k EscHole, n *Node) { default: Fatalf("unexpected expr: %v", n) - case OLITERAL, OGETG, OCLOSUREVAR, OTYPE: + case OLITERAL, ONIL, OGETG, OCLOSUREVAR, OTYPE: // nop case ONAME: diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go index f61ea8aaac..9b57d131b1 100644 --- a/src/cmd/compile/internal/gc/fmt.go +++ b/src/cmd/compile/internal/gc/fmt.go @@ -571,9 +571,6 @@ func (v Val) vconv(s fmt.State, flag FmtFlag) { case bool: fmt.Fprint(s, u) - case *NilVal: - fmt.Fprint(s, "nil") - default: fmt.Fprintf(s, "", v.Ctype()) } @@ -1207,6 +1204,7 @@ var opprec = []int{ OMAPLIT: 8, ONAME: 8, ONEW: 8, + ONIL: 8, ONONAME: 8, OOFFSETOF: 8, OPACK: 8, @@ -1323,6 +1321,9 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { case OPAREN: mode.Fprintf(s, "(%v)", n.Left) + case ONIL: + fmt.Fprint(s, "nil") + case OLITERAL: // this is a bit of a mess if mode == FErr { if n.Orig != nil && n.Orig != n { @@ -1334,10 +1335,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) { return } } - if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n { - n.Orig.exprfmt(s, prec, mode) - return - } + if n.Type != nil && !n.Type.IsUntyped() { // Need parens when type begins with what might // be misinterpreted as a unary operator: * or <-. diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index 47910eb3b9..b48a840d00 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -759,8 +759,6 @@ func constTypeOf(typ *types.Type) Ctype { } switch typ.Etype { - case TCHAN, TFUNC, TMAP, TNIL, TINTER, TPTR, TSLICE, TUNSAFEPTR: - return CTNIL case TBOOL: return CTBOOL case TSTRING: @@ -790,9 +788,6 @@ func (w *exportWriter) value(typ *types.Type, v Val) { // and provides a useful consistency check. switch constTypeOf(typ) { - case CTNIL: - // Only one value; nothing to encode. - _ = v.U.(*NilVal) case CTBOOL: w.bool(v.U.(bool)) case CTSTR: @@ -1207,11 +1202,19 @@ func (w *exportWriter) expr(n *Node) { switch op := n.Op; op { // expressions // (somewhat closely following the structure of exprfmt in fmt.go) - case OLITERAL: - if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n { + case ONIL: + if !n.Type.HasNil() { + Fatalf("unexpected type for nil: %v", n.Type) + } + if n.Orig != nil && n.Orig != n { w.expr(n.Orig) break } + w.op(OLITERAL) + w.pos(n.Pos) + w.typ(n.Type) + + case OLITERAL: w.op(OLITERAL) w.pos(n.Pos) w.value(n.Type, n.Val()) diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index df193cd8e1..ac565a6632 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -293,7 +293,8 @@ func (r *importReader) doDecl(n *Node) { importalias(r.p.ipkg, pos, n.Sym, typ) case 'C': - typ, val := r.value() + typ := r.typ() + val := r.value(typ) importconst(r.p.ipkg, pos, n.Sym, typ, val) @@ -354,12 +355,8 @@ func (r *importReader) doDecl(n *Node) { } } -func (p *importReader) value() (typ *types.Type, v Val) { - typ = p.typ() - +func (p *importReader) value(typ *types.Type) (v Val) { switch constTypeOf(typ) { - case CTNIL: - v.U = &NilVal{} case CTBOOL: v.U = p.bool() case CTSTR: @@ -810,11 +807,20 @@ func (r *importReader) node() *Node { // case OPAREN: // unreachable - unpacked by exporter + // case ONIL: + // unreachable - mapped to OLITERAL + case OLITERAL: pos := r.pos() - typ, val := r.value() + typ := r.typ() - n := npos(pos, nodlit(val)) + var n *Node + if typ.HasNil() { + n = nodnil() + } else { + n = nodlit(r.value(typ)) + } + n = npos(pos, n) n.Type = typ return n diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 4aa561da6e..a882e91dce 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -459,7 +459,7 @@ func inlcopy(n *Node) *Node { } switch n.Op { - case ONAME, OTYPE, OLITERAL: + case ONAME, OTYPE, OLITERAL, ONIL: return n } @@ -1322,7 +1322,7 @@ func (subst *inlsubst) node(n *Node) *Node { } return n - case OLITERAL, OTYPE: + case OLITERAL, ONIL, OTYPE: // If n is a named constant or type, we can continue // using it in the inline copy. Otherwise, make a copy // so we can update the line number. diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index 8fe480b65f..77f9afb44d 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -591,12 +591,15 @@ func litsym(n, c *Node, wid int) { if n.Op != ONAME { Fatalf("litsym n op %v", n.Op) } - if c.Op != OLITERAL { - Fatalf("litsym c op %v", c.Op) - } if n.Sym == nil { Fatalf("litsym nil n sym") } + if c.Op == ONIL { + return + } + if c.Op != OLITERAL { + Fatalf("litsym c op %v", c.Op) + } s := n.Sym.Linksym() switch u := c.Val().U.(type) { case bool: diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index 863de5b6c7..11c8b1fa25 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -119,7 +119,7 @@ func (o *Order) cheapExpr(n *Node) *Node { } switch n.Op { - case ONAME, OLITERAL: + case ONAME, OLITERAL, ONIL: return n case OLEN, OCAP: l := o.cheapExpr(n.Left) @@ -143,7 +143,7 @@ func (o *Order) cheapExpr(n *Node) *Node { // The intended use is to apply to x when rewriting x += y into x = x + y. func (o *Order) safeExpr(n *Node) *Node { switch n.Op { - case ONAME, OLITERAL: + case ONAME, OLITERAL, ONIL: return n case ODOT, OLEN, OCAP: @@ -202,7 +202,7 @@ func isaddrokay(n *Node) bool { // The result of addrTemp MUST be assigned back to n, e.g. // n.Left = o.addrTemp(n.Left) func (o *Order) addrTemp(n *Node) *Node { - if consttype(n) != CTxxx { + if n.Op == OLITERAL || n.Op == ONIL { // TODO: expand this to all static composite literal nodes? n = defaultlit(n, nil) dowidth(n.Type) diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go index 212fcc022d..c199ff6317 100644 --- a/src/cmd/compile/internal/gc/sinit.go +++ b/src/cmd/compile/internal/gc/sinit.go @@ -104,6 +104,9 @@ func (s *InitSchedule) staticcopy(l *Node, r *Node) bool { s.append(nod(OAS, l, conv(r, l.Type))) return true + case ONIL: + return true + case OLITERAL: if isZero(r) { return true @@ -139,7 +142,7 @@ func (s *InitSchedule) staticcopy(l *Node, r *Node) bool { e := &p.E[i] n.Xoffset = l.Xoffset + e.Xoffset n.Type = e.Expr.Type - if e.Expr.Op == OLITERAL { + if e.Expr.Op == OLITERAL || e.Expr.Op == ONIL { litsym(n, e.Expr, int(n.Type.Width)) continue } @@ -171,6 +174,9 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool { case ONAME: return s.staticcopy(l, r) + case ONIL: + return true + case OLITERAL: if isZero(r) { return true @@ -232,7 +238,7 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool { e := &p.E[i] n.Xoffset = l.Xoffset + e.Xoffset n.Type = e.Expr.Type - if e.Expr.Op == OLITERAL { + if e.Expr.Op == OLITERAL || e.Expr.Op == ONIL { litsym(n, e.Expr, int(n.Type.Width)) continue } @@ -269,13 +275,14 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool { for val.Op == OCONVIFACE { val = val.Left } + if val.Type.IsInterface() { // val is an interface type. // If val is nil, we can statically initialize l; // both words are zero and so there no work to do, so report success. // If val is non-nil, we have no concrete type to record, // and we won't be able to statically initialize its value, so report failure. - return Isconst(val, CTNIL) + return val.Op == ONIL } markTypeUsedInInterface(val.Type, l.Sym.Linksym()) @@ -296,7 +303,7 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool { // Emit data. if isdirectiface(val.Type) { - if Isconst(val, CTNIL) { + if val.Op == ONIL { // Nil is zero, nothing to do. return true } @@ -462,7 +469,7 @@ func isStaticCompositeLiteral(n *Node) bool { } } return true - case OLITERAL: + case OLITERAL, ONIL: return true case OCONVIFACE: // See staticassign's OCONVIFACE case for comments. @@ -471,9 +478,9 @@ func isStaticCompositeLiteral(n *Node) bool { val = val.Left } if val.Type.IsInterface() { - return Isconst(val, CTNIL) + return val.Op == ONIL } - if isdirectiface(val.Type) && Isconst(val, CTNIL) { + if isdirectiface(val.Type) && val.Op == ONIL { return true } return isStaticCompositeLiteral(val) @@ -1105,13 +1112,14 @@ func (s *InitSchedule) addvalue(p *InitPlan, xoffset int64, n *Node) { func isZero(n *Node) bool { switch n.Op { + case ONIL: + return true + case OLITERAL: switch u := n.Val().U.(type) { default: Dump("unexpected literal", n) Fatalf("isZero") - case *NilVal: - return true case string: return u == "" case bool: diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 0b38e70cd2..709b2d434e 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1993,7 +1993,7 @@ func (s *state) ssaShiftOp(op Op, t *types.Type, u *types.Type) ssa.Op { // expr converts the expression n to ssa, adds it to s and returns the ssa result. func (s *state) expr(n *Node) *ssa.Value { - if !(n.Op == ONAME || n.Op == OLITERAL && n.Sym != nil) { + if hasUniquePos(n) { // ONAMEs and named OLITERALs have the line number // of the decl, not the use. See issue 14742. s.pushLine(n.Pos) @@ -2029,6 +2029,16 @@ func (s *state) expr(n *Node) *ssa.Value { case OCLOSUREVAR: addr := s.addr(n) return s.load(n.Type, addr) + case ONIL: + t := n.Type + switch { + case t.IsSlice(): + return s.constSlice(t) + case t.IsInterface(): + return s.constInterface(t) + default: + return s.constNil(t) + } case OLITERAL: switch u := n.Val().U.(type) { case *Mpint: @@ -2053,16 +2063,6 @@ func (s *state) expr(n *Node) *ssa.Value { return s.entryNewValue0A(ssa.OpConstString, n.Type, u) case bool: return s.constBool(u) - case *NilVal: - t := n.Type - switch { - case t.IsSlice(): - return s.constSlice(t) - case t.IsInterface(): - return s.constInterface(t) - default: - return s.constNil(t) - } case *Mpflt: switch n.Type.Size() { case 4: diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 849043bfe2..7c13aef214 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -41,7 +41,7 @@ func hasUniquePos(n *Node) bool { switch n.Op { case ONAME, OPACK: return false - case OLITERAL, OTYPE: + case OLITERAL, ONIL, OTYPE: if n.Sym != nil { return false } @@ -257,7 +257,9 @@ func nodintconst(v int64) *Node { } func nodnil() *Node { - return nodlit(Val{new(NilVal)}) + n := nod(ONIL, nil, nil) + n.Type = types.Types[TNIL] + return n } func nodbool(b bool) *Node { @@ -298,7 +300,7 @@ func treecopy(n *Node, pos src.XPos) *Node { // crashing (golang.org/issue/11361). fallthrough - case ONAME, ONONAME, OLITERAL, OTYPE: + case ONAME, ONONAME, OLITERAL, ONIL, OTYPE: return n } @@ -308,7 +310,7 @@ func treecopy(n *Node, pos src.XPos) *Node { func (n *Node) isNil() bool { // Check n.Orig because constant propagation may produce typed nil constants, // which don't exist in the Go spec. - return Isconst(n.Orig, CTNIL) + return n.Orig.Op == ONIL } func isptrto(t *types.Type, et types.EType) bool { @@ -807,7 +809,7 @@ func calcHasCall(n *Node) bool { } switch n.Op { - case OLITERAL, ONAME, OTYPE: + case OLITERAL, ONIL, ONAME, OTYPE: if n.HasCall() { Fatalf("OLITERAL/ONAME/OTYPE should never have calls: %+v", n) } @@ -926,7 +928,7 @@ func safeexpr(n *Node, init *Nodes) *Node { } switch n.Op { - case ONAME, OLITERAL: + case ONAME, OLITERAL, ONIL: return n case ODOT, OLEN, OCAP: @@ -988,7 +990,7 @@ func copyexpr(n *Node, t *types.Type, init *Nodes) *Node { // result may not be assignable. func cheapexpr(n *Node, init *Nodes) *Node { switch n.Op { - case ONAME, OLITERAL: + case ONAME, OLITERAL, ONIL: return n } diff --git a/src/cmd/compile/internal/gc/swt.go b/src/cmd/compile/internal/gc/swt.go index 9ab5f0c248..5f4e9e4b40 100644 --- a/src/cmd/compile/internal/gc/swt.go +++ b/src/cmd/compile/internal/gc/swt.go @@ -261,7 +261,7 @@ func walkExprSwitch(sw *Node) { } cond = walkexpr(cond, &sw.Ninit) - if cond.Op != OLITERAL { + if cond.Op != OLITERAL && cond.Op != ONIL { cond = copyexpr(cond, cond.Type, &sw.Nbody) } diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go index b86510a294..f364ed1527 100644 --- a/src/cmd/compile/internal/gc/syntax.go +++ b/src/cmd/compile/internal/gc/syntax.go @@ -294,7 +294,7 @@ func (n *Node) SetIota(x int64) { // Extra care must be taken when mutating such a node. func (n *Node) mayBeShared() bool { switch n.Op { - case ONAME, OLITERAL, OTYPE: + case ONAME, OLITERAL, ONIL, OTYPE: return true } return false diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index f13d9a3e26..32619b08d1 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -363,7 +363,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = types.UntypedString } - case ONONAME: + case ONIL, ONONAME: ok |= ctxExpr case ONAME: @@ -1590,7 +1590,7 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = t if !t.IsSlice() { - if Isconst(args.First(), CTNIL) { + if args.First().isNil() { yyerror("first argument to append must be typed slice; have untyped nil") n.Type = nil return n @@ -3193,6 +3193,9 @@ func samesafeexpr(l *Node, r *Node) bool { case OLITERAL: return eqval(l.Val(), r.Val()) + + case ONIL: + return true } return false @@ -3596,7 +3599,7 @@ func typecheckdef(n *Node) { } if !e.isGoConst() { if !e.Diag() { - if Isconst(e, CTNIL) { + if e.Op == ONIL { yyerrorl(n.Pos, "const initializer cannot be nil") } else { yyerrorl(n.Pos, "const initializer %v is not a constant", e) diff --git a/src/cmd/compile/internal/gc/universe.go b/src/cmd/compile/internal/gc/universe.go index 559d47da1a..32bf37e322 100644 --- a/src/cmd/compile/internal/gc/universe.go +++ b/src/cmd/compile/internal/gc/universe.go @@ -157,9 +157,7 @@ func lexinit() { types.Types[TNIL] = types.New(TNIL) s = builtinpkg.Lookup("nil") - var v Val - v.U = new(NilVal) - s.Def = asTypesNode(nodlit(v)) + s.Def = asTypesNode(nodnil()) asNode(s.Def).Sym = s asNode(s.Def).Name = new(Name) diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index a61cb3f651..ac43a8e1be 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -465,7 +465,7 @@ opswitch: case ONONAME, OEMPTY, OGETG, ONEWOBJ: - case OTYPE, ONAME, OLITERAL: + case OTYPE, ONAME, OLITERAL, ONIL: // TODO(mdempsky): Just return n; see discussion on CL 38655. // Perhaps refactor to use Node.mayBeShared for these instead. // If these return early, make sure to still call @@ -2277,7 +2277,7 @@ func varexpr(n *Node) bool { } switch n.Op { - case OLITERAL: + case OLITERAL, ONIL: return true case ONAME: @@ -2332,7 +2332,7 @@ func vmatch2(l *Node, r *Node) bool { case ONAME: return l == r - case OLITERAL: + case OLITERAL, ONIL: return false } @@ -2373,7 +2373,7 @@ func vmatch1(l *Node, r *Node) bool { return vmatch2(l, r) - case OLITERAL: + case OLITERAL, ONIL: return false } @@ -3190,7 +3190,7 @@ func eqfor(t *types.Type) (n *Node, needsize bool) { // The result of walkcompare MUST be assigned back to n, e.g. // n.Left = walkcompare(n.Left, init) func walkcompare(n *Node, init *Nodes) *Node { - if n.Left.Type.IsInterface() && n.Right.Type.IsInterface() && n.Left.Op != OLITERAL && n.Right.Op != OLITERAL { + if n.Left.Type.IsInterface() && n.Right.Type.IsInterface() && n.Left.Op != ONIL && n.Right.Op != ONIL { return walkcompareInterface(n, init) } @@ -3788,6 +3788,7 @@ func candiscard(n *Node) bool { OTYPE, OPACK, OLITERAL, + ONIL, OADD, OSUB, OOR, diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 62c5c34484..82db9e4dbc 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1265,7 +1265,7 @@ func (t *Type) IsPtrShaped() bool { // HasNil reports whether the set of values determined by t includes nil. func (t *Type) HasNil() bool { switch t.Etype { - case TCHAN, TFUNC, TINTER, TMAP, TPTR, TSLICE, TUNSAFEPTR: + case TCHAN, TFUNC, TINTER, TMAP, TNIL, TPTR, TSLICE, TUNSAFEPTR: return true } return false