mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[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 <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
2d6ff998ed
commit
f2311462ab
2 changed files with 38 additions and 42 deletions
|
|
@ -3434,33 +3434,28 @@ func setUnderlying(t, underlying *types.Type) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
n := ir.AsNode(t.Nod)
|
|
||||||
ft := t.ForwardType()
|
ft := t.ForwardType()
|
||||||
cache := t.Cache
|
|
||||||
|
|
||||||
// TODO(mdempsky): Fix Type rekinding.
|
// 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.
|
if underlying.NotInHeap() {
|
||||||
t.Nod = n
|
t.SetNotInHeap(true)
|
||||||
t.Sym = n.Sym()
|
}
|
||||||
if n.Name() != nil {
|
if underlying.Broke() {
|
||||||
t.Vargen = n.Name().Vargen
|
t.SetBroke(true)
|
||||||
}
|
}
|
||||||
t.Cache = cache
|
|
||||||
t.SetDeferwidth(false)
|
|
||||||
|
|
||||||
// spec: "The declared type does not inherit any methods bound
|
// spec: "The declared type does not inherit any methods bound
|
||||||
// to the existing type, but the method set of an interface
|
// to the existing type, but the method set of an interface
|
||||||
// type [...] remains unchanged."
|
// type [...] remains unchanged."
|
||||||
if !t.IsInterface() {
|
if t.IsInterface() {
|
||||||
*t.Methods() = types.Fields{}
|
*t.Methods() = *underlying.Methods()
|
||||||
*t.AllMethods() = types.Fields{}
|
*t.AllMethods() = *underlying.AllMethods()
|
||||||
}
|
|
||||||
|
|
||||||
// Propagate go:notinheap pragma from the Name to the Type.
|
|
||||||
if n.Name() != nil && n.Name().Pragma()&ir.NotInHeap != 0 {
|
|
||||||
t.SetNotInHeap(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update types waiting on this type.
|
// 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 {
|
if enableTrace && base.Flag.LowerT {
|
||||||
defer tracePrint("typecheckdeftype", n)(nil)
|
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.SetTypecheck(1)
|
||||||
n.Name().Ntype = typecheckNtype(n.Name().Ntype)
|
n.SetWalkdef(1)
|
||||||
t := n.Name().Ntype.Type()
|
|
||||||
if t == nil {
|
defercheckwidth()
|
||||||
|
errorsBefore := base.Errors()
|
||||||
|
n.Ntype = typecheckNtype(n.Ntype)
|
||||||
|
if underlying := n.Ntype.Type(); underlying != nil {
|
||||||
|
setUnderlying(t, underlying)
|
||||||
|
} else {
|
||||||
n.SetDiag(true)
|
n.SetDiag(true)
|
||||||
n.SetType(nil)
|
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) {
|
func typecheckdef(n ir.Node) {
|
||||||
|
|
@ -3655,20 +3664,7 @@ func typecheckdef(n ir.Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// regular type declaration
|
// 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)
|
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:
|
ret:
|
||||||
|
|
|
||||||
|
|
@ -13,5 +13,5 @@ import "unsafe"
|
||||||
type T [uintptr(unsafe.Pointer(nil))]int // ERROR "non-constant array bound"
|
type T [uintptr(unsafe.Pointer(nil))]int // ERROR "non-constant array bound"
|
||||||
|
|
||||||
func f() {
|
func f() {
|
||||||
_ = complex(1<<uintptr(unsafe.Pointer(nil)), 0)
|
_ = complex(1<<uintptr(unsafe.Pointer(nil)), 0) // ERROR "shift of type float64"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue