]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: cleanup type-checking of defined types
authorMatthew Dempsky <mdempsky@google.com>
Tue, 1 Dec 2020 09:01:59 +0000 (01:01 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Tue, 1 Dec 2020 17:15:12 +0000 (17:15 +0000)
The code for type-checking defined types was scattered between
typecheckdef, typecheckdeftype, and setUnderlying. There was redundant
work between them, and setUnderlying also needed to redo a lot of work
because of its brute-force solution of just copying all Type fields.

This CL reorders things so as many of the defined type's fields are
set in advance (in typecheckdeftype), and then setUnderlying only
copies over the details actually needed from the underlying type.

Incidentally, this evidently improves our error handling for an
existing test case, by allowing us to report an additional error.

Passes toolstash/buildall.

Change-Id: Id59a24341e7e960edd1f7366c3e2356da91b9fe7
Reviewed-on: https://go-review.googlesource.com/c/go/+/274432
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
src/cmd/compile/internal/gc/typecheck.go
test/fixedbugs/issue28079b.go

index 874594d764dcebf4411295324f2fbf4e1dd1ad9c..d9ec06c531e972a72c939902aaae037976f1e92f 100644 (file)
@@ -3434,33 +3434,28 @@ func setUnderlying(t, underlying *types.Type) {
                return
        }
 
-       n := ir.AsNode(t.Nod)
        ft := t.ForwardType()
-       cache := t.Cache
 
        // TODO(mdempsky): Fix Type rekinding.
-       *t = *underlying
+       t.Etype = underlying.Etype
+       t.Extra = underlying.Extra
+       t.Width = underlying.Width
+       t.Align = underlying.Align
+       t.Orig = underlying.Orig
 
-       // Restore unnecessarily clobbered attributes.
-       t.Nod = n
-       t.Sym = n.Sym()
-       if n.Name() != nil {
-               t.Vargen = n.Name().Vargen
+       if underlying.NotInHeap() {
+               t.SetNotInHeap(true)
+       }
+       if underlying.Broke() {
+               t.SetBroke(true)
        }
-       t.Cache = cache
-       t.SetDeferwidth(false)
 
        // spec: "The declared type does not inherit any methods bound
        // to the existing type, but the method set of an interface
        // type [...] remains unchanged."
-       if !t.IsInterface() {
-               *t.Methods() = types.Fields{}
-               *t.AllMethods() = types.Fields{}
-       }
-
-       // Propagate go:notinheap pragma from the Name to the Type.
-       if n.Name() != nil && n.Name().Pragma()&ir.NotInHeap != 0 {
-               t.SetNotInHeap(true)
+       if t.IsInterface() {
+               *t.Methods() = *underlying.Methods()
+               *t.AllMethods() = *underlying.AllMethods()
        }
 
        // Update types waiting on this type.
@@ -3476,24 +3471,38 @@ func setUnderlying(t, underlying *types.Type) {
        }
 }
 
-func typecheckdeftype(n ir.Node) {
+func typecheckdeftype(n *ir.Name) {
        if enableTrace && base.Flag.LowerT {
                defer tracePrint("typecheckdeftype", n)(nil)
        }
 
+       t := types.New(types.TFORW)
+       t.Sym = n.Sym()
+       t.Vargen = n.Vargen
+       t.Nod = n
+       if n.Pragma()&ir.NotInHeap != 0 {
+               t.SetNotInHeap(true)
+       }
+
+       n.SetType(t)
        n.SetTypecheck(1)
-       n.Name().Ntype = typecheckNtype(n.Name().Ntype)
-       t := n.Name().Ntype.Type()
-       if t == nil {
+       n.SetWalkdef(1)
+
+       defercheckwidth()
+       errorsBefore := base.Errors()
+       n.Ntype = typecheckNtype(n.Ntype)
+       if underlying := n.Ntype.Type(); underlying != nil {
+               setUnderlying(t, underlying)
+       } else {
                n.SetDiag(true)
                n.SetType(nil)
-       } else if n.Type() == nil {
-               n.SetDiag(true)
-       } else {
-               // copy new type and clear fields
-               // that don't come along.
-               setUnderlying(n.Type(), t)
        }
+       if t.Etype == types.TFORW && base.Errors() > errorsBefore {
+               // Something went wrong during type-checking,
+               // but it was reported. Silence future errors.
+               t.SetBroke(true)
+       }
+       resumecheckwidth()
 }
 
 func typecheckdef(n ir.Node) {
@@ -3655,20 +3664,7 @@ func typecheckdef(n ir.Node) {
                }
 
                // regular type declaration
-               defercheckwidth()
-               n.SetWalkdef(1)
-               t := types.New(types.TFORW)
-               t.Nod = n
-               t.Sym = n.Sym()
-               n.SetType(t)
-               errorsBefore := base.Errors()
                typecheckdeftype(n)
-               if n.Type().Etype == types.TFORW && base.Errors() > errorsBefore {
-                       // Something went wrong during type-checking,
-                       // but it was reported. Silence future errors.
-                       n.Type().SetBroke(true)
-               }
-               resumecheckwidth()
        }
 
 ret:
index 47cc16dfb2f6c9bb12f9fe39d3349bdfe775f301..9ff221baffd45400bef0ecf74790f2abea48e2f7 100644 (file)
@@ -13,5 +13,5 @@ import "unsafe"
 type T [uintptr(unsafe.Pointer(nil))]int // ERROR "non-constant array bound"
 
 func f() {
-       _ = complex(1<<uintptr(unsafe.Pointer(nil)), 0)
+       _ = complex(1<<uintptr(unsafe.Pointer(nil)), 0) // ERROR "shift of type float64"
 }