From 3db6d46a4e0ee33eb34cef29f797ab7c12530a80 Mon Sep 17 00:00:00 2001 From: LE Manh Cuong Date: Fri, 16 Aug 2019 16:05:10 +0700 Subject: [PATCH] cmd/compile: add marker for skipping dowidth when tracing typecheck The root cause of #33658 is that fmt.Printf does have side effects when printing Type. typefmt for TINTER will call Type.Fields to get all embedded fields and methods. The thing is that type.Fields itself will call dowidth, which will expand the embedded interface, make it non-embedded anymore. To fix it, we add a marker while we are tracing, so dowidth can know and return immediately without doing anything. Fixes #33658 Change-Id: Id4b70ff68a3b802675deae96793fdb8f7ef1a4a7 Reviewed-on: https://go-review.googlesource.com/c/go/+/190537 Run-TryBot: Cuong Manh Le Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/align.go | 5 +++++ src/cmd/compile/internal/gc/typecheck.go | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go index a2b5b53740..44a06fd727 100644 --- a/src/cmd/compile/internal/gc/align.go +++ b/src/cmd/compile/internal/gc/align.go @@ -178,6 +178,11 @@ func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 { // have not already been calculated, it calls Fatal. // This is used to prevent data races in the back end. func dowidth(t *types.Type) { + // Calling dowidth when typecheck tracing enabled is not safe. + // See issue #33658. + if enableTrace && skipDowidthForTracing { + return + } if Widthptr == 0 { Fatalf("dowidth without betypeinit") } diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index d2ad2f04f0..140acb9062 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -16,6 +16,7 @@ const enableTrace = false var trace bool var traceIndent []byte +var skipDowidthForTracing bool func tracePrint(title string, n *Node) func(np **Node) { indent := traceIndent @@ -29,6 +30,8 @@ func tracePrint(title string, n *Node) func(np **Node) { tc = n.Typecheck() } + skipDowidthForTracing = true + defer func() { skipDowidthForTracing = false }() fmt.Printf("%s: %s%s %p %s %v tc=%d\n", pos, indent, title, n, op, n, tc) traceIndent = append(traceIndent, ". "...) @@ -51,6 +54,8 @@ func tracePrint(title string, n *Node) func(np **Node) { typ = n.Type } + skipDowidthForTracing = true + defer func() { skipDowidthForTracing = false }() fmt.Printf("%s: %s=> %p %s %v tc=%d type=%#L\n", pos, indent, n, op, n, tc, typ) } } -- 2.48.1