From f2311462ab6f2359006f42b7febd19ce95a9bbcf Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 1 Dec 2020 01:01:59 -0800 Subject: [PATCH] [dev.regabi] cmd/compile: cleanup type-checking of defined types 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 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Russ Cox --- src/cmd/compile/internal/gc/typecheck.go | 78 +++++++++++------------- test/fixedbugs/issue28079b.go | 2 +- 2 files changed, 38 insertions(+), 42 deletions(-) diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 874594d764..d9ec06c531 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -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: diff --git a/test/fixedbugs/issue28079b.go b/test/fixedbugs/issue28079b.go index 47cc16dfb2..9ff221baff 100644 --- a/test/fixedbugs/issue28079b.go +++ b/test/fixedbugs/issue28079b.go @@ -13,5 +13,5 @@ import "unsafe" type T [uintptr(unsafe.Pointer(nil))]int // ERROR "non-constant array bound" func f() { - _ = complex(1<