[dev.typeparams] cmd/compile: refactor top-level typechecking in unified IR

This CL is a first step towards incremental typechecking during IR
construction within unified IR. Namely, all top-level declarations are
now typechecked as they're constructed, except for assignments (which
aren't really declarations anyway).

Change-Id: I65763a7659bf2e0f5e89dfe9e709d60e0fa4c631
Reviewed-on: https://go-review.googlesource.com/c/go/+/332097
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
Matthew Dempsky 2021-06-30 19:20:28 -07:00
parent ad7e5b219e
commit 372b312735
2 changed files with 53 additions and 18 deletions

View file

@ -109,6 +109,16 @@ func unified(noders []*noder) {
r.ext = r
r.pkgInit(types.LocalPkg, target)
// Type-check any top-level assignments. We ignore non-assignments
// here because other declarations are typechecked as they're
// constructed.
for i, ndecls := 0, len(target.Decls); i < ndecls; i++ {
switch n := target.Decls[i]; n.Op() {
case ir.OAS, ir.OAS2:
target.Decls[i] = typecheck.Stmt(n)
}
}
// Don't use range--bodyIdx can add closures to todoBodies.
for len(todoBodies) > 0 {
// The order we expand bodies doesn't matter, so pop from the end
@ -122,22 +132,12 @@ func unified(noders []*noder) {
// Instantiated generic function: add to Decls for typechecking
// and compilation.
if pri.dict != nil && len(pri.dict.targs) != 0 && fn.OClosure == nil {
if fn.OClosure == nil && len(pri.dict.targs) != 0 {
target.Decls = append(target.Decls, fn)
}
}
todoBodies = nil
if !quirksMode() {
// TODO(mdempsky): Investigate generating wrappers in quirks mode too.
r.wrapTypes(target)
}
// Don't use range--typecheck can add closures to Target.Decls.
for i := 0; i < len(target.Decls); i++ {
target.Decls[i] = typecheck.Stmt(target.Decls[i])
}
// Don't use range--typecheck can add closures to Target.Decls.
for i := 0; i < len(target.Decls); i++ {
if fn, ok := target.Decls[i].(*ir.Func); ok {
@ -145,8 +145,9 @@ func unified(noders []*noder) {
s := fmt.Sprintf("\nbefore typecheck %v", fn)
ir.Dump(s, fn)
}
ir.CurFunc = fn
typecheck.Stmts(fn.Body)
ir.WithFunc(fn, func() {
typecheck.Stmts(fn.Body)
})
if base.Flag.W > 1 {
s := fmt.Sprintf("\nafter typecheck %v", fn)
ir.Dump(s, fn)
@ -154,6 +155,26 @@ func unified(noders []*noder) {
}
}
if !quirksMode() {
// TODO(mdempsky): Investigate generating wrappers in quirks mode too.
r.wrapTypes(target)
}
// Check that nothing snuck past typechecking.
for _, n := range target.Decls {
if n.Typecheck() == 0 {
base.FatalfAt(n.Pos(), "missed typecheck: %v", n)
}
// For functions, check that at least their first statement (if
// any) was typechecked too.
if fn, ok := n.(*ir.Func); ok && len(fn.Body) != 0 {
if stmt := fn.Body[0]; stmt.Typecheck() == 0 {
base.FatalfAt(stmt.Pos(), "missed typecheck: %v", stmt)
}
}
}
base.ExitIfErrors() // just in case
}