mirror of
https://github.com/golang/go
synced 2024-11-23 02:10:03 -07:00
cmd/compile/internal/typecheck: prune some useless code
This error checking code is all obsolete by types2. Change-Id: I247cee2c847236dfbd5a878441ad712481692927 Reviewed-on: https://go-review.googlesource.com/c/go/+/520607 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org> Auto-Submit: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
89eb6b76ae
commit
2a47bc9e4f
@ -8,7 +8,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go/constant"
|
"go/constant"
|
||||||
"go/token"
|
"go/token"
|
||||||
"internal/types/errors"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"cmd/compile/internal/base"
|
"cmd/compile/internal/base"
|
||||||
@ -152,39 +151,6 @@ func typekind(t *types.Type) string {
|
|||||||
return fmt.Sprintf("etype=%d", et)
|
return fmt.Sprintf("etype=%d", et)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cycleFor(start ir.Node) []ir.Node {
|
|
||||||
// Find the start node in typecheck_tcstack.
|
|
||||||
// We know that it must exist because each time we mark
|
|
||||||
// a node with n.SetTypecheck(2) we push it on the stack,
|
|
||||||
// and each time we mark a node with n.SetTypecheck(2) we
|
|
||||||
// pop it from the stack. We hit a cycle when we encounter
|
|
||||||
// a node marked 2 in which case is must be on the stack.
|
|
||||||
i := len(typecheck_tcstack) - 1
|
|
||||||
for i > 0 && typecheck_tcstack[i] != start {
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
|
|
||||||
// collect all nodes with same Op
|
|
||||||
var cycle []ir.Node
|
|
||||||
for _, n := range typecheck_tcstack[i:] {
|
|
||||||
if n.Op() == start.Op() {
|
|
||||||
cycle = append(cycle, n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cycle
|
|
||||||
}
|
|
||||||
|
|
||||||
func cycleTrace(cycle []ir.Node) string {
|
|
||||||
var s string
|
|
||||||
for i, n := range cycle {
|
|
||||||
s += fmt.Sprintf("\n\t%v: %v uses %v", ir.Line(n), n, cycle[(i+1)%len(cycle)])
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
var typecheck_tcstack []ir.Node
|
|
||||||
|
|
||||||
// typecheck type checks node n.
|
// typecheck type checks node n.
|
||||||
// The result of typecheck MUST be assigned back to n, e.g.
|
// The result of typecheck MUST be assigned back to n, e.g.
|
||||||
//
|
//
|
||||||
@ -200,6 +166,7 @@ func typecheck(n ir.Node, top int) (res ir.Node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lno := ir.SetPos(n)
|
lno := ir.SetPos(n)
|
||||||
|
defer func() { base.Pos = lno }()
|
||||||
|
|
||||||
// Skip over parens.
|
// Skip over parens.
|
||||||
for n.Op() == ir.OPAREN {
|
for n.Op() == ir.OPAREN {
|
||||||
@ -214,103 +181,18 @@ func typecheck(n ir.Node, top int) (res ir.Node) {
|
|||||||
break
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
base.Pos = lno
|
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Typecheck() == 2 {
|
if n.Typecheck() == 2 {
|
||||||
// Typechecking loop. Trying printing a meaningful message,
|
base.FatalfAt(n.Pos(), "typechecking loop")
|
||||||
// otherwise a stack trace of typechecking.
|
|
||||||
switch n.Op() {
|
|
||||||
// We can already diagnose variables used as types.
|
|
||||||
case ir.ONAME:
|
|
||||||
n := n.(*ir.Name)
|
|
||||||
if top&(ctxExpr|ctxType) == ctxType {
|
|
||||||
base.Errorf("%v is not a type", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
case ir.OTYPE:
|
|
||||||
// Only report a type cycle if we are expecting a type.
|
|
||||||
// Otherwise let other code report an error.
|
|
||||||
if top&ctxType == ctxType {
|
|
||||||
// A cycle containing only alias types is an error
|
|
||||||
// since it would expand indefinitely when aliases
|
|
||||||
// are substituted.
|
|
||||||
cycle := cycleFor(n)
|
|
||||||
for _, n1 := range cycle {
|
|
||||||
if n1.Name() != nil && !n1.Name().Alias() {
|
|
||||||
// Cycle is ok. But if n is an alias type and doesn't
|
|
||||||
// have a type yet, we have a recursive type declaration
|
|
||||||
// with aliases that we can't handle properly yet.
|
|
||||||
// Report an error rather than crashing later.
|
|
||||||
if n.Name() != nil && n.Name().Alias() && n.Type() == nil {
|
|
||||||
base.Pos = n.Pos()
|
|
||||||
base.Fatalf("cannot handle alias type declaration (issue #25838): %v", n)
|
|
||||||
}
|
|
||||||
base.Pos = lno
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base.ErrorfAt(n.Pos(), errors.InvalidDeclCycle, "invalid recursive type alias %v%s", n, cycleTrace(cycle))
|
|
||||||
}
|
|
||||||
|
|
||||||
case ir.OLITERAL:
|
|
||||||
if top&(ctxExpr|ctxType) == ctxType {
|
|
||||||
base.Errorf("%v is not a type", n)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
base.ErrorfAt(n.Pos(), errors.InvalidInitCycle, "constant definition loop%s", cycleTrace(cycleFor(n)))
|
|
||||||
}
|
|
||||||
|
|
||||||
if base.Errors() == 0 {
|
|
||||||
var trace string
|
|
||||||
for i := len(typecheck_tcstack) - 1; i >= 0; i-- {
|
|
||||||
x := typecheck_tcstack[i]
|
|
||||||
trace += fmt.Sprintf("\n\t%v %v", ir.Line(x), x)
|
|
||||||
}
|
|
||||||
base.Errorf("typechecking loop involving %v%s", n, trace)
|
|
||||||
}
|
|
||||||
|
|
||||||
base.Pos = lno
|
|
||||||
return n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typecheck_tcstack = append(typecheck_tcstack, n)
|
|
||||||
|
|
||||||
n.SetTypecheck(2)
|
n.SetTypecheck(2)
|
||||||
n = typecheck1(n, top)
|
n = typecheck1(n, top)
|
||||||
n.SetTypecheck(1)
|
n.SetTypecheck(1)
|
||||||
|
|
||||||
last := len(typecheck_tcstack) - 1
|
|
||||||
typecheck_tcstack[last] = nil
|
|
||||||
typecheck_tcstack = typecheck_tcstack[:last]
|
|
||||||
|
|
||||||
_, isExpr := n.(ir.Expr)
|
|
||||||
_, isStmt := n.(ir.Stmt)
|
|
||||||
isMulti := false
|
|
||||||
switch n.Op() {
|
|
||||||
case ir.OCALLFUNC, ir.OCALLINTER, ir.OCALLMETH:
|
|
||||||
n := n.(*ir.CallExpr)
|
|
||||||
if t := n.X.Type(); t != nil && t.Kind() == types.TFUNC {
|
|
||||||
nr := t.NumResults()
|
|
||||||
isMulti = nr > 1
|
|
||||||
if nr == 0 {
|
|
||||||
isExpr = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case ir.OAPPEND, ir.OMIN, ir.OMAX:
|
|
||||||
// Must be used.
|
|
||||||
isStmt = false
|
|
||||||
case ir.OCLEAR, ir.OCLOSE, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN:
|
|
||||||
// Must not be used.
|
|
||||||
isExpr = false
|
|
||||||
isStmt = true
|
|
||||||
case ir.OCOPY, ir.ORECOVER, ir.ORECV:
|
|
||||||
// Can be used or not.
|
|
||||||
isStmt = true
|
|
||||||
}
|
|
||||||
|
|
||||||
t := n.Type()
|
t := n.Type()
|
||||||
if t != nil && !t.IsFuncArgStruct() && n.Op() != ir.OTYPE {
|
if t != nil && !t.IsFuncArgStruct() && n.Op() != ir.OTYPE {
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
@ -323,25 +205,6 @@ func typecheck(n ir.Node, top int) (res ir.Node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(rsc): Lots of the complexity here is because typecheck can
|
|
||||||
// see OTYPE, ONAME, and OLITERAL nodes multiple times.
|
|
||||||
// Once we make the IR a proper tree, we should be able to simplify
|
|
||||||
// this code a bit, especially the final case.
|
|
||||||
switch {
|
|
||||||
case top&(ctxStmt|ctxExpr) == ctxExpr && !isExpr && n.Op() != ir.OTYPE && !isMulti:
|
|
||||||
base.Fatalf("%v used as value", n)
|
|
||||||
|
|
||||||
case top&ctxType == 0 && n.Op() == ir.OTYPE && t != nil:
|
|
||||||
base.Fatalf("type %v is not an expression", n.Type())
|
|
||||||
|
|
||||||
case top&(ctxStmt|ctxExpr) == ctxStmt && !isStmt && t != nil:
|
|
||||||
base.Fatalf("%v evaluated but not used", n)
|
|
||||||
|
|
||||||
case top&(ctxType|ctxExpr) == ctxType && n.Op() != ir.OTYPE && n.Op() != ir.ONONAME && (t != nil || n.Op() == ir.ONAME):
|
|
||||||
base.Fatalf("%v is not a type", n)
|
|
||||||
}
|
|
||||||
|
|
||||||
base.Pos = lno
|
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user