]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: make typecheck set n.Type.Nod when returning OTYPE
authorLE Manh Cuong <cuong.manhle.vn@gmail.com>
Sun, 25 Aug 2019 16:29:32 +0000 (23:29 +0700)
committerMatthew Dempsky <mdempsky@google.com>
Thu, 29 Aug 2019 16:43:07 +0000 (16:43 +0000)
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>
src/cmd/compile/internal/gc/align.go
src/cmd/compile/internal/gc/typecheck.go
test/fixedbugs/issue23823.go

index 9ef31ed92cf6145bc1f874f862bffb70b3c38a96..34e69676f7967212caaceabdf529da7860710f63 100644 (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
index 0e680f54ae002cbe2235a457fb43ceab5b0ab5c7..20d2af59e9120c1bca21420c2d2a2cfa8edce2e0 100644 (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)
+}
index 2f802d09886064a7a3c75e1e4546b5862b0a0e73..707cbd3624fdc3b5a542ffba07f6d75af02aa098 100644 (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
 }