From: LE Manh Cuong Date: Sun, 25 Aug 2019 16:29:32 +0000 (+0700) Subject: cmd/compile: make typecheck set n.Type.Nod when returning OTYPE X-Git-Tag: go1.14beta1~1275 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e87fe0f1f521150641c8c64db6b919555c255c65;p=gostls13.git 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 TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky --- diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go index 9ef31ed92c..34e69676f7 100644 --- a/src/cmd/compile/internal/gc/align.go +++ b/src/cmd/compile/internal/gc/align.go @@ -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 diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 0e680f54ae..20d2af59e9 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -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) +} diff --git a/test/fixedbugs/issue23823.go b/test/fixedbugs/issue23823.go index 2f802d0988..707cbd3624 100644 --- a/test/fixedbugs/issue23823.go +++ b/test/fixedbugs/issue23823.go @@ -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 }