cmd/compile: make typecheck set n.Type.Nod when returning OTYPE

typecheck only set n.Type.Nod for declared type, and leave it nil for
anonymous types, type alias. It leads to compiler crashes, because
n.Type.Nod is nil at the time dowidth was called.

Fixing it by set n.Type.Nod right after n.Type initialization if n.Op is
OTYPE.

When embedding interface cycles involve in type alias, it also helps
pointing the error message to the position of the type alias
declaration, instead of position of embedding interface.

Fixes #31872

Change-Id: Ia18391e987036a91f42ba0c08b5506f52d07f683
Reviewed-on: https://go-review.googlesource.com/c/go/+/191540
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
LE Manh Cuong 2019-08-25 23:29:32 +07:00 committed by Matthew Dempsky
parent 647dc1afc5
commit e87fe0f1f5
3 changed files with 22 additions and 36 deletions

View File

@ -189,16 +189,7 @@ func dowidth(t *types.Type) {
if t.Width == -2 {
if !t.Broke() {
t.SetBroke(true)
// t.Nod should not be nil here, but in some cases is appears to be
// (see issue #23823). For now (temporary work-around) at a minimum
// don't crash and provide a meaningful error message.
// TODO(gri) determine the correct fix during a regular devel cycle
// (see issue #31872).
if t.Nod == nil {
yyerror("invalid recursive type %v", t)
} else {
yyerrorl(asNode(t.Nod).Pos, "invalid recursive type %v", t)
}
yyerrorl(asNode(t.Nod).Pos, "invalid recursive type %v", t)
}
t.Width = 0

View File

@ -456,8 +456,7 @@ func typecheck1(n *Node, top int) (res *Node) {
t = types.NewArray(r.Type, bound)
}
n.Op = OTYPE
n.Type = t
setTypeNode(n, t)
n.Left = nil
n.Right = nil
if !t.IsDDDArray() {
@ -480,8 +479,8 @@ func typecheck1(n *Node, top int) (res *Node) {
if r.Type.NotInHeap() {
yyerror("go:notinheap map value not allowed")
}
n.Op = OTYPE
n.Type = types.NewMap(l.Type, r.Type)
setTypeNode(n, types.NewMap(l.Type, r.Type))
mapqueue = append(mapqueue, n) // check map keys when all types are settled
n.Left = nil
n.Right = nil
@ -497,37 +496,28 @@ func typecheck1(n *Node, top int) (res *Node) {
if l.Type.NotInHeap() {
yyerror("chan of go:notinheap type not allowed")
}
t := types.NewChan(l.Type, n.TChanDir())
n.Op = OTYPE
n.Type = t
setTypeNode(n, types.NewChan(l.Type, n.TChanDir()))
n.Left = nil
n.ResetAux()
case OTSTRUCT:
ok |= Etype
n.Op = OTYPE
n.Type = tostruct(n.List.Slice())
if n.Type == nil || n.Type.Broke() {
t := tostruct(n.List.Slice())
if t.Broke() {
n.Type = nil
return n
}
setTypeNode(n, t)
n.List.Set(nil)
case OTINTER:
ok |= Etype
n.Op = OTYPE
n.Type = tointerface(n.List.Slice())
if n.Type == nil {
return n
}
setTypeNode(n, tointerface(n.List.Slice()))
case OTFUNC:
ok |= Etype
n.Op = OTYPE
n.Type = functype(n.Left, n.List.Slice(), n.Rlist.Slice())
if n.Type == nil {
return n
}
setTypeNode(n, functype(n.Left, n.List.Slice(), n.Rlist.Slice()))
n.Left = nil
n.List.Set(nil)
n.Rlist.Set(nil)
@ -543,8 +533,7 @@ func typecheck1(n *Node, top int) (res *Node) {
}
if l.Op == OTYPE {
ok |= Etype
n.Op = OTYPE
n.Type = types.NewPtr(l.Type)
setTypeNode(n, types.NewPtr(l.Type))
// Ensure l.Type gets dowidth'd for the backend. Issue 20174.
// Don't checkwidth [...] arrays, though, since they
// will be replaced by concrete-sized arrays. Issue 20333.
@ -3683,8 +3672,7 @@ func typecheckdef(n *Node) {
defercheckwidth()
}
n.SetWalkdef(1)
n.Type = types.New(TFORW)
n.Type.Nod = asTypesNode(n)
setTypeNode(n, types.New(TFORW))
n.Type.Sym = n.Sym // TODO(gri) this also happens in typecheckdeftype(n) - where should it happen?
nerrors0 := nerrors
typecheckdeftype(n)
@ -3951,3 +3939,10 @@ func deadcodeexpr(n *Node) *Node {
}
return n
}
// setTypeNode sets n to an OTYPE node representing t.
func setTypeNode(n *Node, t *types.Type) {
n.Op = OTYPE
n.Type = t
n.Type.Nod = asTypesNode(n)
}

View File

@ -6,10 +6,10 @@
package p
type I1 = interface {
type I1 = interface { // ERROR "invalid recursive type"
I2
}
type I2 interface { // ERROR "invalid recursive type"
type I2 interface {
I1
}