go/packages: include dependency errors when CompiledGoFiles is missing

When go list fails during cgo processing, go/packages reports a
generic "go list failed to return CompiledGoFiles" error. This hides
underlying dependency errors returned by go list.

Include errors from DepsErrors in the reported message so that tools
like gopls can surface the actual compiler failure when available.

Fixes golang/go#78083

Change-Id: I4af7baf6424aeaa21df184d9bfb8e0fdf75b4da6
Reviewed-on: https://go-review.googlesource.com/c/tools/+/754340
Auto-Submit: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Peter Weinberger <pjw@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
diff --git a/go/packages/golist.go b/go/packages/golist.go
index dc09a98..8e60cbb 100644
--- a/go/packages/golist.go
+++ b/go/packages/golist.go
@@ -562,8 +562,18 @@
 			} else {
 				// golang/go#38990: go list silently fails to do cgo processing
 				pkg.CompiledGoFiles = nil
+
+				var msg strings.Builder
+				fmt.Fprintf(&msg, "go list failed to return CompiledGoFiles for %q.\n", p.Name)
+
+				for _, err := range p.DepsErrors {
+					msg.WriteString(strings.TrimSpace(err.Err))
+					msg.WriteByte('\n')
+				}
+
+				msg.WriteString("This may indicate failure to perform cgo processing; try building at the command line. See https://golang.org/issue/38990.")
 				pkg.Errors = append(pkg.Errors, Error{
-					Msg:  "go list failed to return CompiledGoFiles. This may indicate failure to perform cgo processing; try building at the command line. See https://golang.org/issue/38990.",
+					Msg:  msg.String(),
 					Kind: ListError,
 				})
 			}
diff --git a/go/packages/packages_test.go b/go/packages/packages_test.go
index a78c152..102eb48 100644
--- a/go/packages/packages_test.go
+++ b/go/packages/packages_test.go
@@ -3455,6 +3455,57 @@
 	t.Logf("Packages: %+v", pkgs)
 }
 
+// TestCompiledGoFilesIncludesDepsErrors ensures that when CompiledGoFiles
+// is missing, errors reported by go/packages include underlying dependency
+// errors from go list, rather than only a generic message.
+//
+// See golang/go#78083.
+func TestCompiledGoFilesIncludesDepsErrors(t *testing.T) {
+	testenv.NeedsGoPackages(t)
+
+	dir := writeTree(t, `
+-- go.mod --
+module example.com
+go 1.18
+
+-- a/a.go --
+package a
+
+/*
+#cgo CFLAGS: -I/nonexistent
+#include <missing.h>
+*/
+import "C"
+
+func Foo() {}
+`)
+	pkgs, err := packages.Load(&packages.Config{
+		Dir:  dir,
+		Mode: packages.LoadAllSyntax,
+		Env: append(os.Environ(),
+			"CGO_ENABLED=1",
+		),
+	}, "example.com/a")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(pkgs) == 0 {
+		t.Fatal("no packages loaded")
+	}
+	found := false
+	// Expected error should include something like:
+	//   fatal error: missing.h: No such file or directory
+	// We assert only "missing.h" for portability across systems.
+	for _, err := range pkgs[0].Errors {
+		if strings.Contains(err.Msg, "missing.h") {
+			found = true
+		}
+	}
+	if !found {
+		t.Errorf("expected error message to include underlying dependency errors, got: %+v", pkgs[0].Errors)
+	}
+}
+
 // TestMainPackagePathInModeTypes tests (*types.Package).Path() for
 // main packages in mode NeedTypes, a regression test for #70742, a
 // bug in cmd/compile's export data that caused them to appear as