Commit 380ef6b7 authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/compile: simplify {defer,resume}checkwidth logic

This CL extends {defer,resume}checkwidth to support nesting, which
simplifies usage.

Updates #33658.

Change-Id: Ib3ffb8a7cabfae2cbeba74e21748c228436f4726
Reviewed-on: https://go-review.googlesource.com/c/go/+/192721
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarCuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent adf20ee3
...@@ -217,7 +217,7 @@ func dowidth(t *types.Type) { ...@@ -217,7 +217,7 @@ func dowidth(t *types.Type) {
} }
// defer checkwidth calls until after we're done // defer checkwidth calls until after we're done
defercalc++ defercheckwidth()
lno := lineno lno := lineno
if asNode(t.Nod) != nil { if asNode(t.Nod) != nil {
...@@ -391,11 +391,7 @@ func dowidth(t *types.Type) { ...@@ -391,11 +391,7 @@ func dowidth(t *types.Type) {
lineno = lno lineno = lno
if defercalc == 1 { resumecheckwidth()
resumecheckwidth()
} else {
defercalc--
}
} }
// when a type's width should be known, we call checkwidth // when a type's width should be known, we call checkwidth
...@@ -440,24 +436,18 @@ func checkwidth(t *types.Type) { ...@@ -440,24 +436,18 @@ func checkwidth(t *types.Type) {
} }
func defercheckwidth() { func defercheckwidth() {
// we get out of sync on syntax errors, so don't be pedantic. defercalc++
if defercalc != 0 && nerrors == 0 {
Fatalf("defercheckwidth")
}
defercalc = 1
} }
func resumecheckwidth() { func resumecheckwidth() {
if defercalc == 0 { if defercalc == 1 {
Fatalf("resumecheckwidth") for len(deferredTypeStack) > 0 {
} t := deferredTypeStack[len(deferredTypeStack)-1]
deferredTypeStack = deferredTypeStack[:len(deferredTypeStack)-1]
for len(deferredTypeStack) > 0 { t.SetDeferwidth(false)
t := deferredTypeStack[len(deferredTypeStack)-1] dowidth(t)
deferredTypeStack = deferredTypeStack[:len(deferredTypeStack)-1] }
t.SetDeferwidth(false)
dowidth(t)
} }
defercalc = 0 defercalc--
} }
...@@ -298,21 +298,10 @@ func (r *importReader) doDecl(n *Node) { ...@@ -298,21 +298,10 @@ func (r *importReader) doDecl(n *Node) {
// We also need to defer width calculations until // We also need to defer width calculations until
// after the underlying type has been assigned. // after the underlying type has been assigned.
// defercheckwidth()
// TODO(mdempsky): Add nesting support directly to
// {defer,resume}checkwidth? Width calculations are
// already deferred during initial typechecking, but
// not when we're expanding inline function bodies, so
// we currently need to handle both cases here.
deferring := defercalc != 0
if !deferring {
defercheckwidth()
}
underlying := r.typ() underlying := r.typ()
copytype(typenod(t), underlying) copytype(typenod(t), underlying)
if !deferring { resumecheckwidth()
resumecheckwidth()
}
if underlying.IsInterface() { if underlying.IsInterface() {
break break
......
...@@ -527,7 +527,6 @@ func Main(archInit func(*Arch)) { ...@@ -527,7 +527,6 @@ func Main(archInit func(*Arch)) {
// We also defer type alias declarations until phase 2 // We also defer type alias declarations until phase 2
// to avoid cycles like #18640. // to avoid cycles like #18640.
// TODO(gri) Remove this again once we have a fix for #25838. // TODO(gri) Remove this again once we have a fix for #25838.
defercheckwidth()
// Don't use range--typecheck can add closures to xtop. // Don't use range--typecheck can add closures to xtop.
timings.Start("fe", "typecheck", "top1") timings.Start("fe", "typecheck", "top1")
...@@ -549,7 +548,6 @@ func Main(archInit func(*Arch)) { ...@@ -549,7 +548,6 @@ func Main(archInit func(*Arch)) {
xtop[i] = typecheck(n, ctxStmt) xtop[i] = typecheck(n, ctxStmt)
} }
} }
resumecheckwidth()
// Phase 3: Type check function bodies. // Phase 3: Type check function bodies.
// Don't use range--typecheck can add closures to xtop. // Don't use range--typecheck can add closures to xtop.
...@@ -1035,7 +1033,6 @@ func loadsys() { ...@@ -1035,7 +1033,6 @@ func loadsys() {
inimport = true inimport = true
typecheckok = true typecheckok = true
defercheckwidth()
typs := runtimeTypes() typs := runtimeTypes()
for _, d := range runtimeDecls { for _, d := range runtimeDecls {
...@@ -1052,7 +1049,6 @@ func loadsys() { ...@@ -1052,7 +1049,6 @@ func loadsys() {
} }
typecheckok = false typecheckok = false
resumecheckwidth()
inimport = false inimport = false
} }
......
...@@ -3669,9 +3669,7 @@ func typecheckdef(n *Node) { ...@@ -3669,9 +3669,7 @@ func typecheckdef(n *Node) {
} }
// regular type declaration // regular type declaration
if Curfn != nil { defercheckwidth()
defercheckwidth()
}
n.SetWalkdef(1) n.SetWalkdef(1)
setTypeNode(n, types.New(TFORW)) setTypeNode(n, types.New(TFORW))
n.Type.Sym = n.Sym n.Type.Sym = n.Sym
...@@ -3682,9 +3680,7 @@ func typecheckdef(n *Node) { ...@@ -3682,9 +3680,7 @@ func typecheckdef(n *Node) {
// but it was reported. Silence future errors. // but it was reported. Silence future errors.
n.Type.SetBroke(true) n.Type.SetBroke(true)
} }
if Curfn != nil { resumecheckwidth()
resumecheckwidth()
}
} }
ret: ret:
......
...@@ -18,10 +18,10 @@ type I4 interface { // GC_ERROR "invalid recursive type" ...@@ -18,10 +18,10 @@ type I4 interface { // GC_ERROR "invalid recursive type"
I4 // GCCGO_ERROR "interface" I4 // GCCGO_ERROR "interface"
} }
type I5 interface { type I5 interface { // GC_ERROR "invalid recursive type"
I6 // GCCGO_ERROR "interface" I6 // GCCGO_ERROR "interface"
} }
type I6 interface { // GC_ERROR "invalid recursive type" type I6 interface {
I5 // GCCGO_ERROR "interface" I5 // GCCGO_ERROR "interface"
} }
...@@ -6,10 +6,10 @@ ...@@ -6,10 +6,10 @@
package p package p
type I1 = interface { // ERROR "invalid recursive type" type I1 = interface {
I2 I2
} }
type I2 interface { type I2 interface { // ERROR "invalid recursive type"
I1 I1
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment