This CL replaces the internal trace flag with Config.trace.
While unexported, it can still be set for testing via reflection.
The typical use is for manual tests, where -v (verbose) turns on
tracing output. Typical use:
go test -run Manual -v
This change makes go/types match types2 behavior.
Change-Id: I22842f4bba8fd632efe5929c950f4b1cab0a8569
Reviewed-on: https://go-review.googlesource.com/c/go/+/461081
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
// It is an error to set both FakeImportC and go115UsesCgo.
go115UsesCgo bool
+ // If trace is set, a debug trace is printed to stdout.
+ trace bool
+
// If Error != nil, it is called with each error found
// during type checking; err has dynamic type Error.
// Secondary errors (for instance, to enumerate all types
assert(check != nil)
assert(len(targs) == typ.TypeParams().Len())
- if trace {
+ if check.conf.trace {
check.trace(pos, "-- instantiating signature %s with %s", typ, targs)
check.indent++
defer func() {
)
// debugging/development support
-const (
- debug = false // leave on during development
- trace = false // turn on for detailed type resolution traces
-)
+const debug = false // leave on during development
// exprInfo stores information about an untyped expression.
type exprInfo struct {
defer check.handleBailout(&err)
print := func(msg string) {
- if trace {
+ if check.conf.trace {
fmt.Println()
fmt.Println(msg)
}
// this is a sufficiently bounded process.
for i := top; i < len(check.delayed); i++ {
a := &check.delayed[i]
- if trace {
+ if check.conf.trace {
if a.desc != nil {
check.trace(a.desc.pos.Pos(), "-- "+a.desc.format, a.desc.args...)
} else {
}
}
a.f() // may append to check.delayed
- if trace {
+ if check.conf.trace {
fmt.Println()
}
}
flags := flag.NewFlagSet("", flag.PanicOnError)
flags.StringVar(&conf.GoVersion, "lang", "", "")
flags.BoolVar(&conf.FakeImportC, "fakeImportC", false, "")
- flags.BoolVar(addrOldComparableSemantics(&conf), "oldComparableSemantics", false, "")
+ flags.BoolVar(boolFieldAddr(&conf, "oldComparableSemantics"), "oldComparableSemantics", false, "")
if err := parseFlags(filenames[0], srcs[0], flags); err != nil {
t.Fatal(err)
}
}
// typecheck and collect typechecker errors
+ *boolFieldAddr(&conf, "trace") = manual && testing.Verbose()
if imp == nil {
imp = importer.Default()
}
return int(v.FieldByName("go116code").Int())
}
-// addrOldComparableSemantics(conf) returns &conf.oldComparableSemantics (unexported field).
-func addrOldComparableSemantics(conf *Config) *bool {
+// boolFieldAddr(conf, name) returns the address of the boolean field conf.<name>.
+// For accessing unexported fields.
+func boolFieldAddr(conf *Config, name string) *bool {
v := reflect.Indirect(reflect.ValueOf(conf))
- return (*bool)(v.FieldByName("oldComparableSemantics").Addr().UnsafePointer())
+ return (*bool)(v.FieldByName(name).Addr().UnsafePointer())
}
// TestManual is for manual testing of a package - either provided
// objDecl type-checks the declaration of obj in its respective (file) environment.
// For the meaning of def, see Checker.definedType, in typexpr.go.
func (check *Checker) objDecl(obj Object, def *Named) {
- if trace && obj.Type() == nil {
+ if check.conf.trace && obj.Type() == nil {
if check.indent == 0 {
fmt.Println() // empty line between top-level objects for readability
}
}
}
- if trace {
+ if check.conf.trace {
check.trace(obj.Pos(), "## cycle detected: objPath = %s->%s (len = %d)", pathString(cycle), obj.Name(), len(cycle))
if tparCycle {
check.trace(obj.Pos(), "## cycle contains: generic type in a type parameter list")
tparams = append(tparams, tpar)
}
- if trace && len(names) > 0 {
+ if check.conf.trace && len(names) > 0 {
check.trace(names[0].Pos(), "type params = %v", tparams[len(tparams)-len(names):])
}
check.firstErr = err
}
- if trace {
+ if check.conf.trace {
pos := e.Pos
msg := e.Msg
check.trace(pos, "ERROR: %s", msg)
// If allowGeneric is set, the operand type may be an uninstantiated
// parameterized type or function value.
func (check *Checker) rawExpr(x *operand, e ast.Expr, hint Type, allowGeneric bool) exprKind {
- if trace {
+ if check.conf.trace {
check.trace(e.Pos(), "-- expr %s", e)
check.indent++
defer func() {
// returning the result. Returns Typ[Invalid] if there was an error.
func (n *Named) expandUnderlying() Type {
check := n.check
- if check != nil && trace {
+ if check != nil && check.conf.trace {
check.trace(n.obj.pos, "-- Named.expandUnderlying %s", n)
check.indent++
defer func() {
panic("function body not ignored")
}
- if trace {
+ if check.conf.trace {
check.trace(body.Pos(), "-- %s: %s", name, sig)
}
case *Named:
// dump is for debugging
dump := func(string, ...any) {}
- if subst.check != nil && trace {
+ if subst.check != nil && subst.check.conf.trace {
subst.check.indent++
defer func() {
subst.check.indent--
return &topTypeSet
}
- if check != nil && trace {
+ if check != nil && check.conf.trace {
// Types don't generally have position information.
// If we don't have a valid pos provided, try to use
// one close enough.
// typInternal drives type checking of types.
// Must only be called by definedType or genericType.
func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
- if trace {
+ if check.conf.trace {
check.trace(e0.Pos(), "-- type %s", e0)
check.indent++
defer func() {
}
func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (res Type) {
- if trace {
+ if check.conf.trace {
check.trace(ix.Pos(), "-- instantiating type %s with %s", ix.X, ix.Indices)
check.indent++
defer func() {