go/internal/packagesdriver: report stderr when failed to determine types.Sizes

Provide more information to help users when the go list command intended to determine
the GOARCH and Go compiler fails. This usually happens because there's an issue in
the main module.

Fixes golang/go#30355

Change-Id: I0ce1cfc55cb0ee793bdd1e6fd261a4f98a44abd8
Reviewed-on: https://go-review.googlesource.com/c/tools/+/204357
Run-TryBot: Michael Matloob <matloob@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
diff --git a/go/internal/packagesdriver/sizes.go b/go/internal/packagesdriver/sizes.go
index ea15d57..db0c9a7 100644
--- a/go/internal/packagesdriver/sizes.go
+++ b/go/internal/packagesdriver/sizes.go
@@ -81,13 +81,13 @@
 	args := []string{"list", "-f", "{{context.GOARCH}} {{context.Compiler}}"}
 	args = append(args, buildFlags...)
 	args = append(args, "--", "unsafe")
-	stdout, err := InvokeGo(ctx, env, dir, usesExportData, args...)
+	stdout, stderr, err := invokeGo(ctx, env, dir, usesExportData, args...)
 	var goarch, compiler string
 	if err != nil {
 		if strings.Contains(err.Error(), "cannot find main module") {
 			// User's running outside of a module. All bets are off. Get GOARCH and guess compiler is gc.
 			// TODO(matloob): Is this a problem in practice?
-			envout, enverr := InvokeGo(ctx, env, dir, usesExportData, "env", "GOARCH")
+			envout, _, enverr := invokeGo(ctx, env, dir, usesExportData, "env", "GOARCH")
 			if enverr != nil {
 				return nil, err
 			}
@@ -99,7 +99,8 @@
 	} else {
 		fields := strings.Fields(stdout.String())
 		if len(fields) < 2 {
-			return nil, fmt.Errorf("could not determine GOARCH and Go compiler")
+			return nil, fmt.Errorf("could not parse GOARCH and Go compiler in format \"<GOARCH> <compiler>\" from stdout of go command:\n%s\ndir: %s\nstdout: <<%s>>\nstderr: <<%s>>",
+				cmdDebugStr(env, args...), dir, stdout.String(), stderr.String())
 		}
 		goarch = fields[0]
 		compiler = fields[1]
@@ -107,8 +108,8 @@
 	return types.SizesFor(compiler, goarch), nil
 }
 
-// InvokeGo returns the stdout of a go command invocation.
-func InvokeGo(ctx context.Context, env []string, dir string, usesExportData bool, args ...string) (*bytes.Buffer, error) {
+// invokeGo returns the stdout and stderr of a go command invocation.
+func invokeGo(ctx context.Context, env []string, dir string, usesExportData bool, args ...string) (*bytes.Buffer, *bytes.Buffer, error) {
 	if debug {
 		defer func(start time.Time) { log.Printf("%s for %v", time.Since(start), cmdDebugStr(env, args...)) }(time.Now())
 	}
@@ -131,7 +132,7 @@
 			// Catastrophic error:
 			// - executable not found
 			// - context cancellation
-			return nil, fmt.Errorf("couldn't exec 'go %v': %s %T", args, err, err)
+			return nil, nil, fmt.Errorf("couldn't exec 'go %v': %s %T", args, err, err)
 		}
 
 		// Export mode entails a build.
@@ -139,7 +140,7 @@
 		// (despite the -e flag) and the Export field is blank.
 		// Do not fail in that case.
 		if !usesExportData {
-			return nil, fmt.Errorf("go %v: %s: %s", args, exitErr, stderr)
+			return nil, nil, fmt.Errorf("go %v: %s: %s", args, exitErr, stderr)
 		}
 	}
 
@@ -158,7 +159,7 @@
 		fmt.Fprintf(os.Stderr, "%s stdout: <<%s>>\n", cmdDebugStr(env, args...), stdout)
 	}
 
-	return stdout, nil
+	return stdout, stderr, nil
 }
 
 func cmdDebugStr(envlist []string, args ...string) string {