Repository: knative/pkg
Pull request #1853 (2020-10-27 15:40:45)

Add a test package for making assertions about dependencies.
See the example test for illustrative examples of usage.  It is notable that the gofuzz test failed until I rebased on Ville's recent change.

The goal here is ultimately to assert that our key libraries don't take on heavy dependencies to combat the binary-size bloat that currently afflicts the queue-proxy.

knative-prow-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/knative/pkg/pull/1853#" title="Author self-approved">mattmoor</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=knative%2Fpkg).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/knative/pkg/blob/master/OWNERS)~~ [mattmoor]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
codecov[bot]: # [Codecov](https://codecov.io/gh/knative/pkg/pull/1853?src=pr&el=h1) Report
> Merging [#1853](https://codecov.io/gh/knative/pkg/pull/1853?src=pr&el=desc) into [master](https://codecov.io/gh/knative/pkg/commit/273ba59a1132a6d3036e609db955b9930a50091d?el=desc) will **decrease** coverage by `0.00%`.
> The diff coverage is `50.00%`.

[![Impacted file tree graph](https://codecov.io/gh/knative/pkg/pull/1853/graphs/tree.svg?width=650&height=150&src=pr&token=rlqpDnfxbO)](https://codecov.io/gh/knative/pkg/pull/1853?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1853      +/-   ##
==========================================
- Coverage   68.10%   68.10%   -0.01%     
==========================================
  Files         222      223       +1     
  Lines        9429     9465      +36     
==========================================
+ Hits         6422     6446      +24     
- Misses       2685     2697      +12     
  Partials      322      322              
```


| [Impacted Files](https://codecov.io/gh/knative/pkg/pull/1853?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [depcheck/depcheck.go](https://codecov.io/gh/knative/pkg/pull/1853/diff?src=pr&el=tree#diff-ZGVwY2hlY2svZGVwY2hlY2suZ28=) | `50.00% <50.00%> (ø)` | |
| [test/gcs/mock/mock.go](https://codecov.io/gh/knative/pkg/pull/1853/diff?src=pr&el=tree#diff-dGVzdC9nY3MvbW9jay9tb2NrLmdv) | `93.54% <0.00%> (+3.22%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/knative/pkg/pull/1853?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/knative/pkg/pull/1853?src=pr&el=footer). Last update [273ba59...4b01c56](https://codecov.io/gh/knative/pkg/pull/1853?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

vaikas: Sweet!
/lgtm
/approve
/hold
for further opinions.
knative-prow-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/knative/pkg/pull/1853#" title="Author self-approved">mattmoor</a>*, *<a href="https://github.com/knative/pkg/pull/1853#issuecomment-717335498" title="Approved">vaikas</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=knative%2Fpkg).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/knative/pkg/blob/master/OWNERS)~~ [mattmoor,vaikas]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->

Patch:
diff --git a/RELEASE-LEADS.md b/RELEASE-LEADS.md
index b9479305a..2ac26dc7a 100644
--- a/RELEASE-LEADS.md
+++ b/RELEASE-LEADS.md
@@ -48,13 +48,15 @@ This roster is seeded with all approvers from Eventing workgroups.
 | v0.17   | 2020-08-18   | yanweiguo      | Harwayne        | -           | 2020-08-11 |
 | v0.18   | 2020-09-29   | ZhiminXiang    | n3wscott        | 2020-08-19  | 2020-09-22 |
 | v0.19   | 2020-11-10   | julz           | n3wscott        | 2020-09-30  | 2020-11-03 |
-| v0.20   | 2020-12-22   | nak3           | slinkydeveloper | 2020-11-11  | 2020-12-15 |
-| v0.21   | 2021-02-02   | mattmoor       | lionelvillard   | 2020-12-23  | 2021-01-26 |
-| v0.22   | 2021-03-16   | markusthoemmes | evankanderson   | 2020-02-03  | 2021-03-09 |
-| v0.23   | 2021-04-27   | tcnghia        | vaikas          | 2020-03-17  | 2021-04-20 |
-| v0.24   | 2021-06-08   | dprotaso       | matzew          | 2020-04-28  | 2021-06-01 |
-| v0.25   | 2021-07-20   | vagababov      | grantr          | 2020-06-09  | 2021-07-13 |
-| v0.26   | 2021-08-31   | JRBANCEL       | ...             | 2020-07-21  | 2021-08-24 |
+| v0.20   | 2021-01-12   | nak3           | slinkydeveloper | 2020-11-11  | 2020-01-05 |
+| v0.21   | 2021-02-23   | mattmoor       | lionelvillard   | 2021-01-13  | 2021-02-16 |
+| v0.22   | 2021-04-06   | markusthoemmes | evankanderson   | 2021-02-24  | 2021-03-30 |
+| v0.23   | 2021-05-18   | tcnghia        | vaikas          | 2021-04-07  | 2021-05-11 |
+| v0.24   | 2021-06-29   | dprotaso       | matzew          | 2021-05-19  | 2021-06-22 |
+| v0.25   | 2021-08-10   | vagababov      | grantr          | 2021-06-30  | 2021-08-03 |
+| v0.26   | 2021-09-21   | JRBANCEL       | ...             | 2021-08-11  | 2021-09-14 |
+
+__NOTE:__ v0.20 is moved by 3 weeks for end of year holidays
 
 # Release instruction
 
diff --git a/depcheck/depcheck.go b/depcheck/depcheck.go
new file mode 100644
index 000000000..18a091ad3
--- /dev/null
+++ b/depcheck/depcheck.go
@@ -0,0 +1,111 @@
+/*
+Copyright 2020 The Knative Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Package depcheck defines a test utility for ensuring certain packages don't
+// take on heavy dependencies.
+package depcheck
+
+import (
+	"fmt"
+	"sort"
+	"strings"
+	"testing"
+
+	"golang.org/x/tools/go/packages"
+)
+
+type node struct {
+	importpath string
+	consumers  map[string]struct{}
+}
+
+type graph map[string]node
+
+func (g graph) contains(name string) bool {
+	_, ok := g[name]
+	return ok
+}
+
+// path constructs an examplary path that looks something like:
+//    knative.dev/pkg/apis/duck
+//    knative.dev/pkg/apis  # Also: [knative.dev/pkg/kmeta knative.dev/pkg/tracker]
+//    k8s.io/api/core/v1
+// See the failing example in the test file.
+func (g graph) path(name string) []string {
+	n := g[name]
+	// Base case.
+	if len(n.consumers) == 0 {
+		return []string{name}
+	}
+	// Inductive step.
+	consumers := make(sort.StringSlice, 0, len(n.consumers))
+	for k := range n.consumers {
+		consumers = append(consumers, k)
+	}
+	consumers.Sort()
+	base := g.path(consumers[0])
+	if len(base) > 1 { // Don't decorate the first entry, which is always an entrypoint.
+		if len(consumers) > 1 {
+			// Attach other consumers to the last entry in base.
+			base = append(base[:len(base)-1], fmt.Sprintf("%s  # Also: %v", consumers[0], consumers[1:]))
+		}
+	}
+	return append(base, name)
+}
+
+func buildGraph(importpaths ...string) (graph, error) {
+	g := make(graph, len(importpaths))
+	pkgs, err := packages.Load(&packages.Config{
+		Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedDeps | packages.NeedModule,
+	}, importpaths...)
+	if err != nil {
+		return nil, err
+	}
+	packages.Visit(pkgs, func(pkg *packages.Package) bool {
+		g[pkg.PkgPath] = node{
+			importpath: pkg.PkgPath,
+			consumers:  make(map[string]struct{}),
+		}
+		return pkg.Module != nil
+	}, func(pkg *packages.Package) {
+		for _, imp := range pkg.Imports {
+			if _, ok := g[imp.PkgPath]; ok {
+				g[imp.PkgPath].consumers[pkg.PkgPath] = struct{}{}
+			}
+		}
+	})
+	return g, nil
+}
+
+// AssertNoDependency checks that the given import paths (the keys) do not
+// depend (transitively) on certain banned imports (the values)
+func AssertNoDependency(t *testing.T, banned map[string][]string) {
+	t.Helper()
+	for ip, banned := range banned {
+		t.Run(ip, func(t *testing.T) {
+			g, err := buildGraph(ip)
+			if err != nil {
+				t.Fatal("buildGraph(queue) =", err)
+			}
+			for _, dip := range banned {
+				if g.contains(dip) {
+					t.Errorf("%s depends on banned dependency %s\n%s", ip, dip,
+						strings.Join(g.path(dip), "\n"))
+				}
+			}
+		})
+	}
+}
diff --git a/go.mod b/go.mod
index c7021b1d0..f6535a091 100644
--- a/go.mod
+++ b/go.mod
@@ -41,6 +41,7 @@ require (
 	golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
 	golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
 	golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f // indirect
+	golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3
 	gomodules.xyz/jsonpatch/v2 v2.1.0
 	google.golang.org/api v0.31.0
 	google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d
diff --git a/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go b/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go
new file mode 100644
index 000000000..dc6177c12
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go
@@ -0,0 +1,117 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package packagesdriver fetches type sizes for go/packages and go/analysis.
+package packagesdriver
+
+import (
+	"bytes"
+	"context"
+	"encoding/json"
+	"fmt"
+	"go/types"
+	"os/exec"
+	"strings"
+
+	"golang.org/x/tools/internal/gocommand"
+)
+
+var debug = false
+
+func GetSizes(ctx context.Context, buildFlags, env []string, gocmdRunner *gocommand.Runner, dir string) (types.Sizes, error) {
+	// TODO(matloob): Clean this up. This code is mostly a copy of packages.findExternalDriver.
+	const toolPrefix = "GOPACKAGESDRIVER="
+	tool := ""
+	for _, env := range env {
+		if val := strings.TrimPrefix(env, toolPrefix); val != env {
+			tool = val
+		}
+	}
+
+	if tool == "" {
+		var err error
+		tool, err = exec.LookPath("gopackagesdriver")
+		if err != nil {
+			// We did not find the driver, so use "go list".
+			tool = "off"
+		}
+	}
+
+	if tool == "off" {
+		return GetSizesGolist(ctx, buildFlags, env, gocmdRunner, dir)
+	}
+
+	req, err := json.Marshal(struct {
+		Command    string   `json:"command"`
+		Env        []string `json:"env"`
+		BuildFlags []string `json:"build_flags"`
+	}{
+		Command:    "sizes",
+		Env:        env,
+		BuildFlags: buildFlags,
+	})
+	if err != nil {
+		return nil, fmt.Errorf("failed to encode message to driver tool: %v", err)
+	}
+
+	buf := new(bytes.Buffer)
+	cmd := exec.CommandContext(ctx, tool)
+	cmd.Dir = dir
+	cmd.Env = env
+	cmd.Stdin = bytes.NewReader(req)
+	cmd.Stdout = buf
+	cmd.Stderr = new(bytes.Buffer)
+	if err := cmd.Run(); err != nil {
+		return nil, fmt.Errorf("%v: %v: %s", tool, err, cmd.Stderr)
+	}
+	var response struct {
+		// Sizes, if not nil, is the types.Sizes to use when type checking.
+		Sizes *types.StdSizes
+	}
+	if err := json.Unmarshal(buf.Bytes(), &response); err != nil {
+		return nil, err
+	}
+	return response.Sizes, nil
+}
+
+func GetSizesGolist(ctx context.Context, buildFlags, env []string, gocmdRunner *gocommand.Runner, dir string) (types.Sizes, error) {
+	inv := gocommand.Invocation{
+		Verb:       "list",
+		Args:       []string{"-f", "{{context.GOARCH}} {{context.Compiler}}", "--", "unsafe"},
+		Env:        env,
+		BuildFlags: buildFlags,
+		WorkingDir: dir,
+	}
+	stdout, stderr, friendlyErr, rawErr := gocmdRunner.RunRaw(ctx, inv)
+	var goarch, compiler string
+	if rawErr != nil {
+		if strings.Contains(rawErr.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?
+			inv := gocommand.Invocation{
+				Verb:       "env",
+				Args:       []string{"GOARCH"},
+				Env:        env,
+				WorkingDir: dir,
+			}
+			envout, enverr := gocmdRunner.Run(ctx, inv)
+			if enverr != nil {
+				return nil, enverr
+			}
+			goarch = strings.TrimSpace(envout.String())
+			compiler = "gc"
+		} else {
+			return nil, friendlyErr
+		}
+	} else {
+		fields := strings.Fields(stdout.String())
+		if len(fields) < 2 {
+			return nil, fmt.Errorf("could not parse GOARCH and Go compiler in format \"<GOARCH> <compiler>\":\nstdout: <<%s>>\nstderr: <<%s>>",
+				stdout.String(), stderr.String())
+		}
+		goarch = fields[0]
+		compiler = fields[1]
+	}
+	return types.SizesFor(compiler, goarch), nil
+}
diff --git a/vendor/golang.org/x/tools/go/packages/doc.go b/vendor/golang.org/x/tools/go/packages/doc.go
new file mode 100644
index 000000000..4bfe28a51
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/packages/doc.go
@@ -0,0 +1,221 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package packages loads Go packages for inspection and analysis.
+
+The Load function takes as input a list of patterns and return a list of Package
+structs describing individual packages matched by those patterns.
+The LoadMode controls the amount of detail in the loaded packages.
+
+Load passes most patterns directly to the underlying build tool,
+but all patterns with the prefix "query=", where query is a
+non-empty string of letters from [a-z], are reserved and may be
+interpreted as query operators.
+
+Two query operators are currently supported: "file" and "pattern".
+
+The query "file=path/to/file.go" matches the package or packages enclosing
+the Go source file path/to/file.go.  For example "file=~/go/src/fmt/print.go"
+might return the packages "fmt" and "fmt [fmt.test]".
+
+The query "pattern=string" causes "string" to be passed directly to
+the underlying build tool. In most cases this is unnecessary,
+but an application can use Load("pattern=" + x) as an escaping mechanism
+to ensure that x is not interpreted as a query operator if it contains '='.
+
+All other query operators are reserved for future use and currently
+cause Load to report an error.
+
+The Package struct provides basic information about the package, including
+
+  - ID, a unique identifier for the package in the returned set;
+  - GoFiles, the names of the package's Go source files;
+  - Imports, a map from source import strings to the Packages they name;
+  - Types, the type information for the package's exported symbols;
+  - Syntax, the parsed syntax trees for the package's source code; and
+  - TypeInfo, the result of a complete type-check of the package syntax trees.
+
+(See the documentation for type Package for the complete list of fields
+and more detailed descriptions.)
+
+For example,
+
+	Load(nil, "bytes", "unicode...")
+
+returns four Package structs describing the standard library packages
+bytes, unicode, unicode/utf16, and unicode/utf8. Note that one pattern
+can match multiple packages and that a package might be matched by
+multiple patterns: in general it is not possible to determine which
+packages correspond to which patterns.
+
+Note that the list returned by Load contains only the packages matched
+by the patterns. Their dependencies can be found by walking the import
+graph using the Imports fields.
+
+The Load function can be configured by passing a pointer to a Config as
+the first argument. A nil Config is equivalent to the zero Config, which
+causes Load to run in LoadFiles mode, collecting minimal information.
+See the documentation for type Config for details.
+
+As noted earlier, the Config.Mode controls the amount of detail
+reported about the loaded packages. See the documentation for type LoadMode
+for details.
+
+Most tools should pass their command-line arguments (after any flags)
+uninterpreted to the loader, so that the loader can interpret them
+according to the conventions of the underlying build system.
+See the Example function for typical usage.
+
+*/
+package packages // import "golang.org/x/tools/go/packages"
+
+/*
+
+Motivation and design considerations
+
+The new package's design solves problems addressed by two existing
+packages: go/build, which locates and describes packages, and
+golang.org/x/tools/go/loader, which loads, parses and type-checks them.
+The go/build.Package structure encodes too much of the 'go build' way
+of organizing projects, leaving us in need of a data type that describes a
+package of Go source code independent of the underlying build system.
+We wanted something that works equally well with go build and vgo, and
+also other build systems such as Bazel and Blaze, making it possible to
+construct analysis tools that work in all these environments.
+Tools such as errcheck and staticcheck were essentially unavailable to
+the Go community at Google, and some of Google's internal tools for Go
+are unavailable externally.
+This new package provides a uniform way to obtain package metadata by
+querying each of these build systems, optionally supporting their
+preferred command-line notations for packages, so that tools integrate
+neatly with users' build environments. The Metadata query function
+executes an external query tool appropriate to the current workspace.
+
+Loading packages always returns the complete import graph "all the way down",
+even if all you want is information about a single package, because the query
+mechanisms of all the build systems we currently support ({go,vgo} list, and
+blaze/bazel aspect-based query) cannot provide detailed information
+about one package without visiting all its dependencies too, so there is
+no additional asymptotic cost to providing transitive information.
+(This property might not be true of a hypothetical 5th build system.)
+
+In calls to TypeCheck, all initial packages, and any package that
+transitively depends on one of them, must be loaded from source.
+Consider A->B->C->D->E: if A,C are initial, A,B,C must be loaded from
+source; D may be loaded from export data, and E may not be loaded at all
+(though it's possible that D's export data mentions it, so a
+types.Package may be created for it and exposed.)
+
+The old loader had a feature to suppress type-checking of function
+bodies on a per-package basis, primarily intended to reduce the work of
+obtaining type information for imported packages. Now that imports are
+satisfied by export data, the optimization no longer seems necessary.
+
+Despite some early attempts, the old loader did not exploit export data,
+instead always using the equivalent of WholeProgram mode. This was due
+to the complexity of mixing source and export data packages (now
+resolved by the upward traversal mentioned above), and because export data
+files were nearly always missing or stale. Now that 'go build' supports
+caching, all the underlying build systems can guarantee to produce
+export data in a reasonable (amortized) time.
+
+Test "main" packages synthesized by the build system are now reported as
+first-class packages, avoiding the need for clients (such as go/ssa) to
+reinvent this generation logic.
+
+One way in which go/packages is simpler than the old loader is in its
+treatment of in-package tests. In-package tests are packages that
+consist of all the files of the library under test, plus the test files.
+The old loader constructed in-package tests by a two-phase process of
+mutation called "augmentation": first it would construct and type check
+all the ordinary library packages and type-check the packages that
+depend on them; then it would add more (test) files to the package and
+type-check again. This two-phase approach had four major problems:
+1) in processing the tests, the loader modified the library package,
+   leaving no way for a client application to see both the test
+   package and the library package; one would mutate into the other.
+2) because test files can declare additional methods on types defined in
+   the library portion of the package, the dispatch of method calls in
+   the library portion was affected by the presence of the test files.
+   This should have been a clue that the packages were logically
+   different.
+3) this model of "augmentation" assumed at most one in-package test
+   per library package, which is true of projects using 'go build',
+   but not other build systems.
+4) because of the two-phase nature of test processing, all packages that
+   import the library package had to be processed before augmentation,
+   forcing a "one-shot" API and preventing the client from calling Load
+   in several times in sequence as is now possible in WholeProgram mode.
+   (TypeCheck mode has a similar one-shot restriction for a different reason.)
+
+Early drafts of this package supported "multi-shot" operation.
+Although it allowed clients to make a sequence of calls (or concurrent
+calls) to Load, building up the graph of Packages incrementally,
+it was of marginal value: it complicated the API
+(since it allowed some options to vary across calls but not others),
+it complicated the implementation,
+it cannot be made to work in Types mode, as explained above,
+and it was less efficient than making one combined call (when this is possible).
+Among the clients we have inspected, none made multiple calls to load
+but could not be easily and satisfactorily modified to make only a single call.
+However, applications changes may be required.
+For example, the ssadump command loads the user-specified packages
+and in addition the runtime package.  It is tempting to simply append
+"runtime" to the user-provided list, but that does not work if the user
+specified an ad-hoc package such as [a.go b.go].
+Instead, ssadump no longer requests the runtime package,
+but seeks it among the dependencies of the user-specified packages,
+and emits an error if it is not found.
+
+Overlays: The Overlay field in the Config allows providing alternate contents
+for Go source files, by providing a mapping from file path to contents.
+go/packages will pull in new imports added in overlay files when go/packages
+is run in LoadImports mode or greater.
+Overlay support for the go list driver isn't complete yet: if the file doesn't
+exist on disk, it will only be recognized in an overlay if it is a non-test file
+and the package would be reported even without the overlay.
+
+Questions & Tasks
+
+- Add GOARCH/GOOS?
+  They are not portable concepts, but could be made portable.
+  Our goal has been to allow users to express themselves using the conventions
+  of the underlying build system: if the build system honors GOARCH
+  during a build and during a metadata query, then so should
+  applications built atop that query mechanism.
+  Conversely, if the target architecture of the build is determined by
+  command-line flags, the application can pass the relevant
+  flags through to the build system using a command such as:
+    myapp -query_flag="--cpu=amd64" -query_flag="--os=darwin"
+  However, this approach is low-level, unwieldy, and non-portable.
+  GOOS and GOARCH seem important enough to warrant a dedicated option.
+
+- How should we handle partial failures such as a mixture of good and
+  malformed patterns, existing and non-existent packages, successful and
+  failed builds, import failures, import cycles, and so on, in a call to
+  Load?
+
+- Support bazel, blaze, and go1.10 list, not just go1.11 list.
+
+- Handle (and test) various partial success cases, e.g.
+  a mixture of good packages and:
+  invalid patterns
+  nonexistent packages
+  empty packages
+  packages with malformed package or import declarations
+  unreadable files
+  import cycles
+  other parse errors
+  type errors
+  Make sure we record errors at the correct place in the graph.
+
+- Missing packages among initial arguments are not reported.
+  Return bogus packages for them, like golist does.
+
+- "undeclared name" errors (for example) are reported out of source file
+  order. I suspect this is due to the breadth-first resolution now used
+  by go/types. Is that a bug? Discuss with gri.
+
+*/
diff --git a/vendor/golang.org/x/tools/go/packages/external.go b/vendor/golang.org/x/tools/go/packages/external.go
new file mode 100644
index 000000000..8c8473fd0
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/packages/external.go
@@ -0,0 +1,101 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file enables an external tool to intercept package requests.
+// If the tool is present then its results are used in preference to
+// the go list command.
+
+package packages
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"os"
+	"os/exec"
+	"strings"
+)
+
+// The Driver Protocol
+//
+// The driver, given the inputs to a call to Load, returns metadata about the packages specified.
+// This allows for different build systems to support go/packages by telling go/packages how the
+// packages' source is organized.
+// The driver is a binary, either specified by the GOPACKAGESDRIVER environment variable or in
+// the path as gopackagesdriver. It's given the inputs to load in its argv. See the package
+// documentation in doc.go for the full description of the patterns that need to be supported.
+// A driver receives as a JSON-serialized driverRequest struct in standard input and will
+// produce a JSON-serialized driverResponse (see definition in packages.go) in its standard output.
+
+// driverRequest is used to provide the portion of Load's Config that is needed by a driver.
+type driverRequest struct {
+	Mode LoadMode `json:"mode"`
+	// Env specifies the environment the underlying build system should be run in.
+	Env []string `json:"env"`
+	// BuildFlags are flags that should be passed to the underlying build system.
+	BuildFlags []string `json:"build_flags"`
+	// Tests specifies whether the patterns should also return test packages.
+	Tests bool `json:"tests"`
+	// Overlay maps file paths (relative to the driver's working directory) to the byte contents
+	// of overlay files.
+	Overlay map[string][]byte `json:"overlay"`
+}
+
+// findExternalDriver returns the file path of a tool that supplies
+// the build system package structure, or "" if not found."
+// If GOPACKAGESDRIVER is set in the environment findExternalTool returns its
+// value, otherwise it searches for a binary named gopackagesdriver on the PATH.
+func findExternalDriver(cfg *Config) driver {
+	const toolPrefix = "GOPACKAGESDRIVER="
+	tool := ""
+	for _, env := range cfg.Env {
+		if val := strings.TrimPrefix(env, toolPrefix); val != env {
+			tool = val
+		}
+	}
+	if tool != "" && tool == "off" {
+		return nil
+	}
+	if tool == "" {
+		var err error
+		tool, err = exec.LookPath("gopackagesdriver")
+		if err != nil {
+			return nil
+		}
+	}
+	return func(cfg *Config, words ...string) (*driverResponse, error) {
+		req, err := json.Marshal(driverRequest{
+			Mode:       cfg.Mode,
+			Env:        cfg.Env,
+			BuildFlags: cfg.BuildFlags,
+			Tests:      cfg.Tests,
+			Overlay:    cfg.Overlay,
+		})
+		if err != nil {
+			return nil, fmt.Errorf("failed to encode message to driver tool: %v", err)
+		}
+
+		buf := new(bytes.Buffer)
+		stderr := new(bytes.Buffer)
+		cmd := exec.CommandContext(cfg.Context, tool, words...)
+		cmd.Dir = cfg.Dir
+		cmd.Env = cfg.Env
+		cmd.Stdin = bytes.NewReader(req)
+		cmd.Stdout = buf
+		cmd.Stderr = stderr
+
+		if err := cmd.Run(); err != nil {
+			return nil, fmt.Errorf("%v: %v: %s", tool, err, cmd.Stderr)
+		}
+		if len(stderr.Bytes()) != 0 && os.Getenv("GOPACKAGESPRINTDRIVERERRORS") != "" {
+			fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd, words...), stderr)
+		}
+
+		var response driverResponse
+		if err := json.Unmarshal(buf.Bytes(), &response); err != nil {
+			return nil, err
+		}
+		return &response, nil
+	}
+}
diff --git a/vendor/golang.org/x/tools/go/packages/golist.go b/vendor/golang.org/x/tools/go/packages/golist.go
new file mode 100644
index 000000000..bc04503c1
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/packages/golist.go
@@ -0,0 +1,1012 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packages
+
+import (
+	"bytes"
+	"context"
+	"encoding/json"
+	"fmt"
+	"go/types"
+	"log"
+	"os"
+	"os/exec"
+	"path"
+	"path/filepath"
+	"reflect"
+	"sort"
+	"strconv"
+	"strings"
+	"sync"
+	"unicode"
+
+	"golang.org/x/tools/go/internal/packagesdriver"
+	"golang.org/x/tools/internal/gocommand"
+	"golang.org/x/xerrors"
+)
+
+// debug controls verbose logging.
+var debug, _ = strconv.ParseBool(os.Getenv("GOPACKAGESDEBUG"))
+
+// A goTooOldError reports that the go command
+// found by exec.LookPath is too old to use the new go list behavior.
+type goTooOldError struct {
+	error
+}
+
+// responseDeduper wraps a driverResponse, deduplicating its contents.
+type responseDeduper struct {
+	seenRoots    map[string]bool
+	seenPackages map[string]*Package
+	dr           *driverResponse
+}
+
+func newDeduper() *responseDeduper {
+	return &responseDeduper{
+		dr:           &driverResponse{},
+		seenRoots:    map[string]bool{},
+		seenPackages: map[string]*Package{},
+	}
+}
+
+// addAll fills in r with a driverResponse.
+func (r *responseDeduper) addAll(dr *driverResponse) {
+	for _, pkg := range dr.Packages {
+		r.addPackage(pkg)
+	}
+	for _, root := range dr.Roots {
+		r.addRoot(root)
+	}
+}
+
+func (r *responseDeduper) addPackage(p *Package) {
+	if r.seenPackages[p.ID] != nil {
+		return
+	}
+	r.seenPackages[p.ID] = p
+	r.dr.Packages = append(r.dr.Packages, p)
+}
+
+func (r *responseDeduper) addRoot(id string) {
+	if r.seenRoots[id] {
+		return
+	}
+	r.seenRoots[id] = true
+	r.dr.Roots = append(r.dr.Roots, id)
+}
+
+type golistState struct {
+	cfg *Config
+	ctx context.Context
+
+	envOnce    sync.Once
+	goEnvError error
+	goEnv      map[string]string
+
+	rootsOnce     sync.Once
+	rootDirsError error
+	rootDirs      map[string]string
+
+	goVersionOnce  sync.Once
+	goVersionError error
+	goVersion      string // third field of 'go version'
+
+	// vendorDirs caches the (non)existence of vendor directories.
+	vendorDirs map[string]bool
+}
+
+// getEnv returns Go environment variables. Only specific variables are
+// populated -- computing all of them is slow.
+func (state *golistState) getEnv() (map[string]string, error) {
+	state.envOnce.Do(func() {
+		var b *bytes.Buffer
+		b, state.goEnvError = state.invokeGo("env", "-json", "GOMOD", "GOPATH")
+		if state.goEnvError != nil {
+			return
+		}
+
+		state.goEnv = make(map[string]string)
+		decoder := json.NewDecoder(b)
+		if state.goEnvError = decoder.Decode(&state.goEnv); state.goEnvError != nil {
+			return
+		}
+	})
+	return state.goEnv, state.goEnvError
+}
+
+// mustGetEnv is a convenience function that can be used if getEnv has already succeeded.
+func (state *golistState) mustGetEnv() map[string]string {
+	env, err := state.getEnv()
+	if err != nil {
+		panic(fmt.Sprintf("mustGetEnv: %v", err))
+	}
+	return env
+}
+
+// goListDriver uses the go list command to interpret the patterns and produce
+// the build system package structure.
+// See driver for more details.
+func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
+	// Make sure that any asynchronous go commands are killed when we return.
+	parentCtx := cfg.Context
+	if parentCtx == nil {
+		parentCtx = context.Background()
+	}
+	ctx, cancel := context.WithCancel(parentCtx)
+	defer cancel()
+
+	response := newDeduper()
+
+	// Fill in response.Sizes asynchronously if necessary.
+	var sizeserr error
+	var sizeswg sync.WaitGroup
+	if cfg.Mode&NeedTypesSizes != 0 || cfg.Mode&NeedTypes != 0 {
+		sizeswg.Add(1)
+		go func() {
+			var sizes types.Sizes
+			sizes, sizeserr = packagesdriver.GetSizesGolist(ctx, cfg.BuildFlags, cfg.Env, cfg.gocmdRunner, cfg.Dir)
+			// types.SizesFor always returns nil or a *types.StdSizes.
+			response.dr.Sizes, _ = sizes.(*types.StdSizes)
+			sizeswg.Done()
+		}()
+	}
+
+	state := &golistState{
+		cfg:        cfg,
+		ctx:        ctx,
+		vendorDirs: map[string]bool{},
+	}
+
+	// Determine files requested in contains patterns
+	var containFiles []string
+	restPatterns := make([]string, 0, len(patterns))
+	// Extract file= and other [querytype]= patterns. Report an error if querytype
+	// doesn't exist.
+extractQueries:
+	for _, pattern := range patterns {
+		eqidx := strings.Index(pattern, "=")
+		if eqidx < 0 {
+			restPatterns = append(restPatterns, pattern)
+		} else {
+			query, value := pattern[:eqidx], pattern[eqidx+len("="):]
+			switch query {
+			case "file":
+				containFiles = append(containFiles, value)
+			case "pattern":
+				restPatterns = append(restPatterns, value)
+			case "": // not a reserved query
+				restPatterns = append(restPatterns, pattern)
+			default:
+				for _, rune := range query {
+					if rune < 'a' || rune > 'z' { // not a reserved query
+						restPatterns = append(restPatterns, pattern)
+						continue extractQueries
+					}
+				}
+				// Reject all other patterns containing "="
+				return nil, fmt.Errorf("invalid query type %q in query pattern %q", query, pattern)
+			}
+		}
+	}
+
+	// See if we have any patterns to pass through to go list. Zero initial
+	// patterns also requires a go list call, since it's the equivalent of
+	// ".".
+	if len(restPatterns) > 0 || len(patterns) == 0 {
+		dr, err := state.createDriverResponse(restPatterns...)
+		if err != nil {
+			return nil, err
+		}
+		response.addAll(dr)
+	}
+
+	if len(containFiles) != 0 {
+		if err := state.runContainsQueries(response, containFiles); err != nil {
+			return nil, err
+		}
+	}
+
+	modifiedPkgs, needPkgs, err := state.processGolistOverlay(response)
+	if err != nil {
+		return nil, err
+	}
+
+	var containsCandidates []string
+	if len(containFiles) > 0 {
+		containsCandidates = append(containsCandidates, modifiedPkgs...)
+		containsCandidates = append(containsCandidates, needPkgs...)
+	}
+	if err := state.addNeededOverlayPackages(response, needPkgs); err != nil {
+		return nil, err
+	}
+	// Check candidate packages for containFiles.
+	if len(containFiles) > 0 {
+		for _, id := range containsCandidates {
+			pkg, ok := response.seenPackages[id]
+			if !ok {
+				response.addPackage(&Package{
+					ID: id,
+					Errors: []Error{
+						{
+							Kind: ListError,
+							Msg:  fmt.Sprintf("package %s expected but not seen", id),
+						},
+					},
+				})
+				continue
+			}
+			for _, f := range containFiles {
+				for _, g := range pkg.GoFiles {
+					if sameFile(f, g) {
+						response.addRoot(id)
+					}
+				}
+			}
+		}
+	}
+	// Add root for any package that matches a pattern. This applies only to
+	// packages that are modified by overlays, since they are not added as
+	// roots automatically.
+	for _, pattern := range restPatterns {
+		match := matchPattern(pattern)
+		for _, pkgID := range modifiedPkgs {
+			pkg, ok := response.seenPackages[pkgID]
+			if !ok {
+				continue
+			}
+			if match(pkg.PkgPath) {
+				response.addRoot(pkg.ID)
+			}
+		}
+	}
+
+	sizeswg.Wait()
+	if sizeserr != nil {
+		return nil, sizeserr
+	}
+	return response.dr, nil
+}
+
+func (state *golistState) addNeededOverlayPackages(response *responseDeduper, pkgs []string) error {
+	if len(pkgs) == 0 {
+		return nil
+	}
+	dr, err := state.createDriverResponse(pkgs...)
+	if err != nil {
+		return err
+	}
+	for _, pkg := range dr.Packages {
+		response.addPackage(pkg)
+	}
+	_, needPkgs, err := state.processGolistOverlay(response)
+	if err != nil {
+		return err
+	}
+	return state.addNeededOverlayPackages(response, needPkgs)
+}
+
+func (state *golistState) runContainsQueries(response *responseDeduper, queries []string) error {
+	for _, query := range queries {
+		// TODO(matloob): Do only one query per directory.
+		fdir := filepath.Dir(query)
+		// Pass absolute path of directory to go list so that it knows to treat it as a directory,
+		// not a package path.
+		pattern, err := filepath.Abs(fdir)
+		if err != nil {
+			return fmt.Errorf("could not determine absolute path of file= query path %q: %v", query, err)
+		}
+		dirResponse, err := state.createDriverResponse(pattern)
+
+		// If there was an error loading the package, or the package is returned
+		// with errors, try to load the file as an ad-hoc package.
+		// Usually the error will appear in a returned package, but may not if we're
+		// in module mode and the ad-hoc is located outside a module.
+		if err != nil || len(dirResponse.Packages) == 1 && len(dirResponse.Packages[0].GoFiles) == 0 &&
+			len(dirResponse.Packages[0].Errors) == 1 {
+			var queryErr error
+			if dirResponse, queryErr = state.adhocPackage(pattern, query); queryErr != nil {
+				return err // return the original error
+			}
+		}
+		isRoot := make(map[string]bool, len(dirResponse.Roots))
+		for _, root := range dirResponse.Roots {
+			isRoot[root] = true
+		}
+		for _, pkg := range dirResponse.Packages {
+			// Add any new packages to the main set
+			// We don't bother to filter packages that will be dropped by the changes of roots,
+			// that will happen anyway during graph construction outside this function.
+			// Over-reporting packages is not a problem.
+			response.addPackage(pkg)
+			// if the package was not a root one, it cannot have the file
+			if !isRoot[pkg.ID] {
+				continue
+			}
+			for _, pkgFile := range pkg.GoFiles {
+				if filepath.Base(query) == filepath.Base(pkgFile) {
+					response.addRoot(pkg.ID)
+					break
+				}
+			}
+		}
+	}
+	return nil
+}
+
+// adhocPackage attempts to load or construct an ad-hoc package for a given
+// query, if the original call to the driver produced inadequate results.
+func (state *golistState) adhocPackage(pattern, query string) (*driverResponse, error) {
+	response, err := state.createDriverResponse(query)
+	if err != nil {
+		return nil, err
+	}
+	// If we get nothing back from `go list`,
+	// try to make this file into its own ad-hoc package.
+	// TODO(rstambler): Should this check against the original response?
+	if len(response.Packages) == 0 {
+		response.Packages = append(response.Packages, &Package{
+			ID:              "command-line-arguments",
+			PkgPath:         query,
+			GoFiles:         []string{query},
+			CompiledGoFiles: []string{query},
+			Imports:         make(map[string]*Package),
+		})
+		response.Roots = append(response.Roots, "command-line-arguments")
+	}
+	// Handle special cases.
+	if len(response.Packages) == 1 {
+		// golang/go#33482: If this is a file= query for ad-hoc packages where
+		// the file only exists on an overlay, and exists outside of a module,
+		// add the file to the package and remove the errors.
+		if response.Packages[0].ID == "command-line-arguments" ||
+			filepath.ToSlash(response.Packages[0].PkgPath) == filepath.ToSlash(query) {
+			if len(response.Packages[0].GoFiles) == 0 {
+				filename := filepath.Join(pattern, filepath.Base(query)) // avoid recomputing abspath
+				// TODO(matloob): check if the file is outside of a root dir?
+				for path := range state.cfg.Overlay {
+					if path == filename {
+						response.Packages[0].Errors = nil
+						response.Packages[0].GoFiles = []string{path}
+						response.Packages[0].CompiledGoFiles = []string{path}
+					}
+				}
+			}
+		}
+	}
+	return response, nil
+}
+
+// Fields must match go list;
+// see $GOROOT/src/cmd/go/internal/load/pkg.go.
+type jsonPackage struct {
+	ImportPath      string
+	Dir             string
+	Name            string
+	Export          string
+	GoFiles         []string
+	CompiledGoFiles []string
+	CFiles          []string
+	CgoFiles        []string
+	CXXFiles        []string
+	MFiles          []string
+	HFiles          []string
+	FFiles          []string
+	SFiles          []string
+	SwigFiles       []string
+	SwigCXXFiles    []string
+	SysoFiles       []string
+	Imports         []string
+	ImportMap       map[string]string
+	Deps            []string
+	Module          *Module
+	TestGoFiles     []string
+	TestImports     []string
+	XTestGoFiles    []string
+	XTestImports    []string
+	ForTest         string // q in a "p [q.test]" package, else ""
+	DepOnly         bool
+
+	Error *jsonPackageError
+}
+
+type jsonPackageError struct {
+	ImportStack []string
+	Pos         string
+	Err         string
+}
+
+func otherFiles(p *jsonPackage) [][]string {
+	return [][]string{p.CFiles, p.CXXFiles, p.MFiles, p.HFiles, p.FFiles, p.SFiles, p.SwigFiles, p.SwigCXXFiles, p.SysoFiles}
+}
+
+// createDriverResponse uses the "go list" command to expand the pattern
+// words and return a response for the specified packages.
+func (state *golistState) createDriverResponse(words ...string) (*driverResponse, error) {
+	// go list uses the following identifiers in ImportPath and Imports:
+	//
+	// 	"p"			-- importable package or main (command)
+	// 	"q.test"		-- q's test executable
+	// 	"p [q.test]"		-- variant of p as built for q's test executable
+	// 	"q_test [q.test]"	-- q's external test package
+	//
+	// The packages p that are built differently for a test q.test
+	// are q itself, plus any helpers used by the external test q_test,
+	// typically including "testing" and all its dependencies.
+
+	// Run "go list" for complete
+	// information on the specified packages.
+	buf, err := state.invokeGo("list", golistargs(state.cfg, words)...)
+	if err != nil {
+		return nil, err
+	}
+	seen := make(map[string]*jsonPackage)
+	pkgs := make(map[string]*Package)
+	additionalErrors := make(map[string][]Error)
+	// Decode the JSON and convert it to Package form.
+	var response driverResponse
+	for dec := json.NewDecoder(buf); dec.More(); {
+		p := new(jsonPackage)
+		if err := dec.Decode(p); err != nil {
+			return nil, fmt.Errorf("JSON decoding failed: %v", err)
+		}
+
+		if p.ImportPath == "" {
+			// The documentation for go list says that “[e]rroneous packages will have
+			// a non-empty ImportPath”. If for some reason it comes back empty, we
+			// prefer to error out rather than silently discarding data or handing
+			// back a package without any way to refer to it.
+			if p.Error != nil {
+				return nil, Error{
+					Pos: p.Error.Pos,
+					Msg: p.Error.Err,
+				}
+			}
+			return nil, fmt.Errorf("package missing import path: %+v", p)
+		}
+
+		// Work around https://golang.org/issue/33157:
+		// go list -e, when given an absolute path, will find the package contained at
+		// that directory. But when no package exists there, it will return a fake package
+		// with an error and the ImportPath set to the absolute path provided to go list.
+		// Try to convert that absolute path to what its package path would be if it's
+		// contained in a known module or GOPATH entry. This will allow the package to be
+		// properly "reclaimed" when overlays are processed.
+		if filepath.IsAbs(p.ImportPath) && p.Error != nil {
+			pkgPath, ok, err := state.getPkgPath(p.ImportPath)
+			if err != nil {
+				return nil, err
+			}
+			if ok {
+				p.ImportPath = pkgPath
+			}
+		}
+
+		if old, found := seen[p.ImportPath]; found {
+			// If one version of the package has an error, and the other doesn't, assume
+			// that this is a case where go list is reporting a fake dependency variant
+			// of the imported package: When a package tries to invalidly import another
+			// package, go list emits a variant of the imported package (with the same
+			// import path, but with an error on it, and the package will have a
+			// DepError set on it). An example of when this can happen is for imports of
+			// main packages: main packages can not be imported, but they may be
+			// separately matched and listed by another pattern.
+			// See golang.org/issue/36188 for more details.
+
+			// The plan is that eventually, hopefully in Go 1.15, the error will be
+			// reported on the importing package rather than the duplicate "fake"
+			// version of the imported package. Once all supported versions of Go
+			// have the new behavior this logic can be deleted.
+			// TODO(matloob): delete the workaround logic once all supported versions of
+			// Go return the errors on the proper package.
+
+			// There should be exactly one version of a package that doesn't have an
+			// error.
+			if old.Error == nil && p.Error == nil {
+				if !reflect.DeepEqual(p, old) {
+					return nil, fmt.Errorf("internal error: go list gives conflicting information for package %v", p.ImportPath)
+				}
+				continue
+			}
+
+			// Determine if this package's error needs to be bubbled up.
+			// This is a hack, and we expect for go list to eventually set the error
+			// on the package.
+			if old.Error != nil {
+				var errkind string
+				if strings.Contains(old.Error.Err, "not an importable package") {
+					errkind = "not an importable package"
+				} else if strings.Contains(old.Error.Err, "use of internal package") && strings.Contains(old.Error.Err, "not allowed") {
+					errkind = "use of internal package not allowed"
+				}
+				if errkind != "" {
+					if len(old.Error.ImportStack) < 1 {
+						return nil, fmt.Errorf(`internal error: go list gave a %q error with empty import stack`, errkind)
+					}
+					importingPkg := old.Error.ImportStack[len(old.Error.ImportStack)-1]
+					if importingPkg == old.ImportPath {
+						// Using an older version of Go which put this package itself on top of import
+						// stack, instead of the importer. Look for importer in second from top
+						// position.
+						if len(old.Error.ImportStack) < 2 {
+							return nil, fmt.Errorf(`internal error: go list gave a %q error with an import stack without importing package`, errkind)
+						}
+						importingPkg = old.Error.ImportStack[len(old.Error.ImportStack)-2]
+					}
+					additionalErrors[importingPkg] = append(additionalErrors[importingPkg], Error{
+						Pos:  old.Error.Pos,
+						Msg:  old.Error.Err,
+						Kind: ListError,
+					})
+				}
+			}
+
+			// Make sure that if there's a version of the package without an error,
+			// that's the one reported to the user.
+			if old.Error == nil {
+				continue
+			}
+
+			// This package will replace the old one at the end of the loop.
+		}
+		seen[p.ImportPath] = p
+
+		pkg := &Package{
+			Name:            p.Name,
+			ID:              p.ImportPath,
+			GoFiles:         absJoin(p.Dir, p.GoFiles, p.CgoFiles),
+			CompiledGoFiles: absJoin(p.Dir, p.CompiledGoFiles),
+			OtherFiles:      absJoin(p.Dir, otherFiles(p)...),
+			forTest:         p.ForTest,
+			Module:          p.Module,
+		}
+
+		if (state.cfg.Mode&typecheckCgo) != 0 && len(p.CgoFiles) != 0 {
+			if len(p.CompiledGoFiles) > len(p.GoFiles) {
+				// We need the cgo definitions, which are in the first
+				// CompiledGoFile after the non-cgo ones. This is a hack but there
+				// isn't currently a better way to find it. We also need the pure
+				// Go files and unprocessed cgo files, all of which are already
+				// in pkg.GoFiles.
+				cgoTypes := p.CompiledGoFiles[len(p.GoFiles)]
+				pkg.CompiledGoFiles = append([]string{cgoTypes}, pkg.GoFiles...)
+			} else {
+				// golang/go#38990: go list silently fails to do cgo processing
+				pkg.CompiledGoFiles = nil
+				pkg.Errors = append(pkg.Errors, Error{
+					Msg:  "go list failed to return CompiledGoFiles; https://golang.org/issue/38990?",
+					Kind: ListError,
+				})
+			}
+		}
+
+		// Work around https://golang.org/issue/28749:
+		// cmd/go puts assembly, C, and C++ files in CompiledGoFiles.
+		// Filter out any elements of CompiledGoFiles that are also in OtherFiles.
+		// We have to keep this workaround in place until go1.12 is a distant memory.
+		if len(pkg.OtherFiles) > 0 {
+			other := make(map[string]bool, len(pkg.OtherFiles))
+			for _, f := range pkg.OtherFiles {
+				other[f] = true
+			}
+
+			out := pkg.CompiledGoFiles[:0]
+			for _, f := range pkg.CompiledGoFiles {
+				if other[f] {
+					continue
+				}
+				out = append(out, f)
+			}
+			pkg.CompiledGoFiles = out
+		}
+
+		// Extract the PkgPath from the package's ID.
+		if i := strings.IndexByte(pkg.ID, ' '); i >= 0 {
+			pkg.PkgPath = pkg.ID[:i]
+		} else {
+			pkg.PkgPath = pkg.ID
+		}
+
+		if pkg.PkgPath == "unsafe" {
+			pkg.GoFiles = nil // ignore fake unsafe.go file
+		}
+
+		// Assume go list emits only absolute paths for Dir.
+		if p.Dir != "" && !filepath.IsAbs(p.Dir) {
+			log.Fatalf("internal error: go list returned non-absolute Package.Dir: %s", p.Dir)
+		}
+
+		if p.Export != "" && !filepath.IsAbs(p.Export) {
+			pkg.ExportFile = filepath.Join(p.Dir, p.Export)
+		} else {
+			pkg.ExportFile = p.Export
+		}
+
+		// imports
+		//
+		// Imports contains the IDs of all imported packages.
+		// ImportsMap records (path, ID) only where they differ.
+		ids := make(map[string]bool)
+		for _, id := range p.Imports {
+			ids[id] = true
+		}
+		pkg.Imports = make(map[string]*Package)
+		for path, id := range p.ImportMap {
+			pkg.Imports[path] = &Package{ID: id} // non-identity import
+			delete(ids, id)
+		}
+		for id := range ids {
+			if id == "C" {
+				continue
+			}
+
+			pkg.Imports[id] = &Package{ID: id} // identity import
+		}
+		if !p.DepOnly {
+			response.Roots = append(response.Roots, pkg.ID)
+		}
+
+		// Work around for pre-go.1.11 versions of go list.
+		// TODO(matloob): they should be handled by the fallback.
+		// Can we delete this?
+		if len(pkg.CompiledGoFiles) == 0 {
+			pkg.CompiledGoFiles = pkg.GoFiles
+		}
+
+		// Temporary work-around for golang/go#39986. Parse filenames out of
+		// error messages. This happens if there are unrecoverable syntax
+		// errors in the source, so we can't match on a specific error message.
+		if err := p.Error; err != nil && state.shouldAddFilenameFromError(p) {
+			addFilenameFromPos := func(pos string) bool {
+				split := strings.Split(pos, ":")
+				if len(split) < 1 {
+					return false
+				}
+				filename := strings.TrimSpace(split[0])
+				if filename == "" {
+					return false
+				}
+				if !filepath.IsAbs(filename) {
+					filename = filepath.Join(state.cfg.Dir, filename)
+				}
+				info, _ := os.Stat(filename)
+				if info == nil {
+					return false
+				}
+				pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, filename)
+				pkg.GoFiles = append(pkg.GoFiles, filename)
+				return true
+			}
+			found := addFilenameFromPos(err.Pos)
+			// In some cases, go list only reports the error position in the
+			// error text, not the error position. One such case is when the
+			// file's package name is a keyword (see golang.org/issue/39763).
+			if !found {
+				addFilenameFromPos(err.Err)
+			}
+		}
+
+		if p.Error != nil {
+			msg := strings.TrimSpace(p.Error.Err) // Trim to work around golang.org/issue/32363.
+			// Address golang.org/issue/35964 by appending import stack to error message.
+			if msg == "import cycle not allowed" && len(p.Error.ImportStack) != 0 {
+				msg += fmt.Sprintf(": import stack: %v", p.Error.ImportStack)
+			}
+			pkg.Errors = append(pkg.Errors, Error{
+				Pos:  p.Error.Pos,
+				Msg:  msg,
+				Kind: ListError,
+			})
+		}
+
+		pkgs[pkg.ID] = pkg
+	}
+
+	for id, errs := range additionalErrors {
+		if p, ok := pkgs[id]; ok {
+			p.Errors = append(p.Errors, errs...)
+		}
+	}
+	for _, pkg := range pkgs {
+		response.Packages = append(response.Packages, pkg)
+	}
+	sort.Slice(response.Packages, func(i, j int) bool { return response.Packages[i].ID < response.Packages[j].ID })
+
+	return &response, nil
+}
+
+func (state *golistState) shouldAddFilenameFromError(p *jsonPackage) bool {
+	if len(p.GoFiles) > 0 || len(p.CompiledGoFiles) > 0 {
+		return false
+	}
+
+	goV, err := state.getGoVersion()
+	if err != nil {
+		return false
+	}
+
+	// On Go 1.14 and earlier, only add filenames from errors if the import stack is empty.
+	// The import stack behaves differently for these versions than newer Go versions.
+	if strings.HasPrefix(goV, "go1.13") || strings.HasPrefix(goV, "go1.14") {
+		return len(p.Error.ImportStack) == 0
+	}
+
+	// On Go 1.15 and later, only parse filenames out of error if there's no import stack,
+	// or the current package is at the top of the import stack. This is not guaranteed
+	// to work perfectly, but should avoid some cases where files in errors don't belong to this
+	// package.
+	return len(p.Error.ImportStack) == 0 || p.Error.ImportStack[len(p.Error.ImportStack)-1] == p.ImportPath
+}
+
+func (state *golistState) getGoVersion() (string, error) {
+	state.goVersionOnce.Do(func() {
+		var b *bytes.Buffer
+		// Invoke go version. Don't use invokeGo because it will supply build flags, and
+		// go version doesn't expect build flags.
+		inv := gocommand.Invocation{
+			Verb: "version",
+			Env:  state.cfg.Env,
+			Logf: state.cfg.Logf,
+		}
+		gocmdRunner := state.cfg.gocmdRunner
+		if gocmdRunner == nil {
+			gocmdRunner = &gocommand.Runner{}
+		}
+		b, _, _, state.goVersionError = gocmdRunner.RunRaw(state.cfg.Context, inv)
+		if state.goVersionError != nil {
+			return
+		}
+
+		sp := strings.Split(b.String(), " ")
+		if len(sp) < 3 {
+			state.goVersionError = fmt.Errorf("go version output: expected 'go version <version>', got '%s'", b.String())
+			return
+		}
+		state.goVersion = sp[2]
+	})
+	return state.goVersion, state.goVersionError
+}
+
+// getPkgPath finds the package path of a directory if it's relative to a root
+// directory.
+func (state *golistState) getPkgPath(dir string) (string, bool, error) {
+	absDir, err := filepath.Abs(dir)
+	if err != nil {
+		return "", false, err
+	}
+	roots, err := state.determineRootDirs()
+	if err != nil {
+		return "", false, err
+	}
+
+	for rdir, rpath := range roots {
+		// Make sure that the directory is in the module,
+		// to avoid creating a path relative to another module.
+		if !strings.HasPrefix(absDir, rdir) {
+			continue
+		}
+		// TODO(matloob): This doesn't properly handle symlinks.
+		r, err := filepath.Rel(rdir, dir)
+		if err != nil {
+			continue
+		}
+		if rpath != "" {
+			// We choose only one root even though the directory even it can belong in multiple modules
+			// or GOPATH entries. This is okay because we only need to work with absolute dirs when a
+			// file is missing from disk, for instance when gopls calls go/packages in an overlay.
+			// Once the file is saved, gopls, or the next invocation of the tool will get the correct
+			// result straight from golist.
+			// TODO(matloob): Implement module tiebreaking?
+			return path.Join(rpath, filepath.ToSlash(r)), true, nil
+		}
+		return filepath.ToSlash(r), true, nil
+	}
+	return "", false, nil
+}
+
+// absJoin absolutizes and flattens the lists of files.
+func absJoin(dir string, fileses ...[]string) (res []string) {
+	for _, files := range fileses {
+		for _, file := range files {
+			if !filepath.IsAbs(file) {
+				file = filepath.Join(dir, file)
+			}
+			res = append(res, file)
+		}
+	}
+	return res
+}
+
+func golistargs(cfg *Config, words []string) []string {
+	const findFlags = NeedImports | NeedTypes | NeedSyntax | NeedTypesInfo
+	fullargs := []string{
+		"-e", "-json",
+		fmt.Sprintf("-compiled=%t", cfg.Mode&(NeedCompiledGoFiles|NeedSyntax|NeedTypes|NeedTypesInfo|NeedTypesSizes) != 0),
+		fmt.Sprintf("-test=%t", cfg.Tests),
+		fmt.Sprintf("-export=%t", usesExportData(cfg)),
+		fmt.Sprintf("-deps=%t", cfg.Mode&NeedImports != 0),
+		// go list doesn't let you pass -test and -find together,
+		// probably because you'd just get the TestMain.
+		fmt.Sprintf("-find=%t", !cfg.Tests && cfg.Mode&findFlags == 0),
+	}
+	fullargs = append(fullargs, cfg.BuildFlags...)
+	fullargs = append(fullargs, "--")
+	fullargs = append(fullargs, words...)
+	return fullargs
+}
+
+// invokeGo returns the stdout of a go command invocation.
+func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer, error) {
+	cfg := state.cfg
+
+	inv := gocommand.Invocation{
+		Verb:       verb,
+		Args:       args,
+		BuildFlags: cfg.BuildFlags,
+		Env:        cfg.Env,
+		Logf:       cfg.Logf,
+		WorkingDir: cfg.Dir,
+	}
+	gocmdRunner := cfg.gocmdRunner
+	if gocmdRunner == nil {
+		gocmdRunner = &gocommand.Runner{}
+	}
+	stdout, stderr, _, err := gocmdRunner.RunRaw(cfg.Context, inv)
+	if err != nil {
+		// Check for 'go' executable not being found.
+		if ee, ok := err.(*exec.Error); ok && ee.Err == exec.ErrNotFound {
+			return nil, fmt.Errorf("'go list' driver requires 'go', but %s", exec.ErrNotFound)
+		}
+
+		exitErr, ok := err.(*exec.ExitError)
+		if !ok {
+			// Catastrophic error:
+			// - context cancellation
+			return nil, xerrors.Errorf("couldn't run 'go': %w", err)
+		}
+
+		// Old go version?
+		if strings.Contains(stderr.String(), "flag provided but not defined") {
+			return nil, goTooOldError{fmt.Errorf("unsupported version of go: %s: %s", exitErr, stderr)}
+		}
+
+		// Related to #24854
+		if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "unexpected directory layout") {
+			return nil, fmt.Errorf("%s", stderr.String())
+		}
+
+		// Is there an error running the C compiler in cgo? This will be reported in the "Error" field
+		// and should be suppressed by go list -e.
+		//
+		// This condition is not perfect yet because the error message can include other error messages than runtime/cgo.
+		isPkgPathRune := func(r rune) bool {
+			// From https://golang.org/ref/spec#Import_declarations:
+			//    Implementation restriction: A compiler may restrict ImportPaths to non-empty strings
+			//    using only characters belonging to Unicode's L, M, N, P, and S general categories
+			//    (the Graphic characters without spaces) and may also exclude the
+			//    characters !"#$%&'()*,:;<=>?[\]^`{|} and the Unicode replacement character U+FFFD.
+			return unicode.IsOneOf([]*unicode.RangeTable{unicode.L, unicode.M, unicode.N, unicode.P, unicode.S}, r) &&
+				!strings.ContainsRune("!\"#$%&'()*,:;<=>?[\\]^`{|}\uFFFD", r)
+		}
+		if len(stderr.String()) > 0 && strings.HasPrefix(stderr.String(), "# ") {
+			msg := stderr.String()[len("# "):]
+			if strings.HasPrefix(strings.TrimLeftFunc(msg, isPkgPathRune), "\n") {
+				return stdout, nil
+			}
+			// Treat pkg-config errors as a special case (golang.org/issue/36770).
+			if strings.HasPrefix(msg, "pkg-config") {
+				return stdout, nil
+			}
+		}
+
+		// This error only appears in stderr. See golang.org/cl/166398 for a fix in go list to show
+		// the error in the Err section of stdout in case -e option is provided.
+		// This fix is provided for backwards compatibility.
+		if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "named files must be .go files") {
+			output := fmt.Sprintf(`{"ImportPath": "command-line-arguments","Incomplete": true,"Error": {"Pos": "","Err": %q}}`,
+				strings.Trim(stderr.String(), "\n"))
+			return bytes.NewBufferString(output), nil
+		}
+
+		// Similar to the previous error, but currently lacks a fix in Go.
+		if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "named files must all be in one directory") {
+			output := fmt.Sprintf(`{"ImportPath": "command-line-arguments","Incomplete": true,"Error": {"Pos": "","Err": %q}}`,
+				strings.Trim(stderr.String(), "\n"))
+			return bytes.NewBufferString(output), nil
+		}
+
+		// Backwards compatibility for Go 1.11 because 1.12 and 1.13 put the directory in the ImportPath.
+		// If the package doesn't exist, put the absolute path of the directory into the error message,
+		// as Go 1.13 list does.
+		const noSuchDirectory = "no such directory"
+		if len(stderr.String()) > 0 && strings.Contains(stderr.String(), noSuchDirectory) {
+			errstr := stderr.String()
+			abspath := strings.TrimSpace(errstr[strings.Index(errstr, noSuchDirectory)+len(noSuchDirectory):])
+			output := fmt.Sprintf(`{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q}}`,
+				abspath, strings.Trim(stderr.String(), "\n"))
+			return bytes.NewBufferString(output), nil
+		}
+
+		// Workaround for #29280: go list -e has incorrect behavior when an ad-hoc package doesn't exist.
+		// Note that the error message we look for in this case is different that the one looked for above.
+		if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "no such file or directory") {
+			output := fmt.Sprintf(`{"ImportPath": "command-line-arguments","Incomplete": true,"Error": {"Pos": "","Err": %q}}`,
+				strings.Trim(stderr.String(), "\n"))
+			return bytes.NewBufferString(output), nil
+		}
+
+		// Workaround for #34273. go list -e with GO111MODULE=on has incorrect behavior when listing a
+		// directory outside any module.
+		if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "outside available modules") {
+			output := fmt.Sprintf(`{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q}}`,
+				// TODO(matloob): command-line-arguments isn't correct here.
+				"command-line-arguments", strings.Trim(stderr.String(), "\n"))
+			return bytes.NewBufferString(output), nil
+		}
+
+		// Another variation of the previous error
+		if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "outside module root") {
+			output := fmt.Sprintf(`{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q}}`,
+				// TODO(matloob): command-line-arguments isn't correct here.
+				"command-line-arguments", strings.Trim(stderr.String(), "\n"))
+			return bytes.NewBufferString(output), nil
+		}
+
+		// Workaround for an instance of golang.org/issue/26755: go list -e  will return a non-zero exit
+		// status if there's a dependency on a package that doesn't exist. But it should return
+		// a zero exit status and set an error on that package.
+		if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "no Go files in") {
+			// Don't clobber stdout if `go list` actually returned something.
+			if len(stdout.String()) > 0 {
+				return stdout, nil
+			}
+			// try to extract package name from string
+			stderrStr := stderr.String()
+			var importPath string
+			colon := strings.Index(stderrStr, ":")
+			if colon > 0 && strings.HasPrefix(stderrStr, "go build ") {
+				importPath = stderrStr[len("go build "):colon]
+			}
+			output := fmt.Sprintf(`{"ImportPath": %q,"Incomplete": true,"Error": {"Pos": "","Err": %q}}`,
+				importPath, strings.Trim(stderrStr, "\n"))
+			return bytes.NewBufferString(output), nil
+		}
+
+		// Export mode entails a build.
+		// If that build fails, errors appear on stderr
+		// (despite the -e flag) and the Export field is blank.
+		// Do not fail in that case.
+		// The same is true if an ad-hoc package given to go list doesn't exist.
+		// TODO(matloob): Remove these once we can depend on go list to exit with a zero status with -e even when
+		// packages don't exist or a build fails.
+		if !usesExportData(cfg) && !containsGoFile(args) {
+			return nil, fmt.Errorf("go %v: %s: %s", args, exitErr, stderr)
+		}
+	}
+	return stdout, nil
+}
+
+func containsGoFile(s []string) bool {
+	for _, f := range s {
+		if strings.HasSuffix(f, ".go") {
+			return true
+		}
+	}
+	return false
+}
+
+func cmdDebugStr(cmd *exec.Cmd, args ...string) string {
+	env := make(map[string]string)
+	for _, kv := range cmd.Env {
+		split := strings.Split(kv, "=")
+		k, v := split[0], split[1]
+		env[k] = v
+	}
+	var quotedArgs []string
+	for _, arg := range args {
+		quotedArgs = append(quotedArgs, strconv.Quote(arg))
+	}
+
+	return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v PWD=%v go %s", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["PWD"], strings.Join(quotedArgs, " "))
+}
diff --git a/vendor/golang.org/x/tools/go/packages/golist_overlay.go b/vendor/golang.org/x/tools/go/packages/golist_overlay.go
new file mode 100644
index 000000000..874f90134
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/packages/golist_overlay.go
@@ -0,0 +1,568 @@
+package packages
+
+import (
+	"encoding/json"
+	"fmt"
+	"go/parser"
+	"go/token"
+	"log"
+	"os"
+	"path/filepath"
+	"regexp"
+	"sort"
+	"strconv"
+	"strings"
+
+	"golang.org/x/tools/internal/gocommand"
+)
+
+// processGolistOverlay provides rudimentary support for adding
+// files that don't exist on disk to an overlay. The results can be
+// sometimes incorrect.
+// TODO(matloob): Handle unsupported cases, including the following:
+// - determining the correct package to add given a new import path
+func (state *golistState) processGolistOverlay(response *responseDeduper) (modifiedPkgs, needPkgs []string, err error) {
+	havePkgs := make(map[string]string) // importPath -> non-test package ID
+	needPkgsSet := make(map[string]bool)
+	modifiedPkgsSet := make(map[string]bool)
+
+	pkgOfDir := make(map[string][]*Package)
+	for _, pkg := range response.dr.Packages {
+		// This is an approximation of import path to id. This can be
+		// wrong for tests, vendored packages, and a number of other cases.
+		havePkgs[pkg.PkgPath] = pkg.ID
+		x := commonDir(pkg.GoFiles)
+		if x != "" {
+			pkgOfDir[x] = append(pkgOfDir[x], pkg)
+		}
+	}
+
+	// If no new imports are added, it is safe to avoid loading any needPkgs.
+	// Otherwise, it's hard to tell which package is actually being loaded
+	// (due to vendoring) and whether any modified package will show up
+	// in the transitive set of dependencies (because new imports are added,
+	// potentially modifying the transitive set of dependencies).
+	var overlayAddsImports bool
+
+	// If both a package and its test package are created by the overlay, we
+	// need the real package first. Process all non-test files before test
+	// files, and make the whole process deterministic while we're at it.
+	var overlayFiles []string
+	for opath := range state.cfg.Overlay {
+		overlayFiles = append(overlayFiles, opath)
+	}
+	sort.Slice(overlayFiles, func(i, j int) bool {
+		iTest := strings.HasSuffix(overlayFiles[i], "_test.go")
+		jTest := strings.HasSuffix(overlayFiles[j], "_test.go")
+		if iTest != jTest {
+			return !iTest // non-tests are before tests.
+		}
+		return overlayFiles[i] < overlayFiles[j]
+	})
+	for _, opath := range overlayFiles {
+		contents := state.cfg.Overlay[opath]
+		base := filepath.Base(opath)
+		dir := filepath.Dir(opath)
+		var pkg *Package           // if opath belongs to both a package and its test variant, this will be the test variant
+		var testVariantOf *Package // if opath is a test file, this is the package it is testing
+		var fileExists bool
+		isTestFile := strings.HasSuffix(opath, "_test.go")
+		pkgName, ok := extractPackageName(opath, contents)
+		if !ok {
+			// Don't bother adding a file that doesn't even have a parsable package statement
+			// to the overlay.
+			continue
+		}
+		// If all the overlay files belong to a different package, change the
+		// package name to that package.
+		maybeFixPackageName(pkgName, isTestFile, pkgOfDir[dir])
+	nextPackage:
+		for _, p := range response.dr.Packages {
+			if pkgName != p.Name && p.ID != "command-line-arguments" {
+				continue
+			}
+			for _, f := range p.GoFiles {
+				if !sameFile(filepath.Dir(f), dir) {
+					continue
+				}
+				// Make sure to capture information on the package's test variant, if needed.
+				if isTestFile && !hasTestFiles(p) {
+					// TODO(matloob): Are there packages other than the 'production' variant
+					// of a package that this can match? This shouldn't match the test main package
+					// because the file is generated in another directory.
+					testVariantOf = p
+					continue nextPackage
+				} else if !isTestFile && hasTestFiles(p) {
+					// We're examining a test variant, but the overlaid file is
+					// a non-test file. Because the overlay implementation
+					// (currently) only adds a file to one package, skip this
+					// package, so that we can add the file to the production
+					// variant of the package. (https://golang.org/issue/36857
+					// tracks handling overlays on both the production and test
+					// variant of a package).
+					continue nextPackage
+				}
+				if pkg != nil && p != pkg && pkg.PkgPath == p.PkgPath {
+					// We have already seen the production version of the
+					// for which p is a test variant.
+					if hasTestFiles(p) {
+						testVariantOf = pkg
+					}
+				}
+				pkg = p
+				if filepath.Base(f) == base {
+					fileExists = true
+				}
+			}
+		}
+		// The overlay could have included an entirely new package or an
+		// ad-hoc package. An ad-hoc package is one that we have manually
+		// constructed from inadequate `go list` results for a file= query.
+		// It will have the ID command-line-arguments.
+		if pkg == nil || pkg.ID == "command-line-arguments" {
+			// Try to find the module or gopath dir the file is contained in.
+			// Then for modules, add the module opath to the beginning.
+			pkgPath, ok, err := state.getPkgPath(dir)
+			if err != nil {
+				return nil, nil, err
+			}
+			if !ok {
+				break
+			}
+			var forTest string // only set for x tests
+			isXTest := strings.HasSuffix(pkgName, "_test")
+			if isXTest {
+				forTest = pkgPath
+				pkgPath += "_test"
+			}
+			id := pkgPath
+			if isTestFile {
+				if isXTest {
+					id = fmt.Sprintf("%s [%s.test]", pkgPath, forTest)
+				} else {
+					id = fmt.Sprintf("%s [%s.test]", pkgPath, pkgPath)
+				}
+			}
+			if pkg != nil {
+				// TODO(rstambler): We should change the package's path and ID
+				// here. The only issue is that this messes with the roots.
+			} else {
+				// Try to reclaim a package with the same ID, if it exists in the response.
+				for _, p := range response.dr.Packages {
+					if reclaimPackage(p, id, opath, contents) {
+						pkg = p
+						break
+					}
+				}
+				// Otherwise, create a new package.
+				if pkg == nil {
+					pkg = &Package{
+						PkgPath: pkgPath,
+						ID:      id,
+						Name:    pkgName,
+						Imports: make(map[string]*Package),
+					}
+					response.addPackage(pkg)
+					havePkgs[pkg.PkgPath] = id
+					// Add the production package's sources for a test variant.
+					if isTestFile && !isXTest && testVariantOf != nil {
+						pkg.GoFiles = append(pkg.GoFiles, testVariantOf.GoFiles...)
+						pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, testVariantOf.CompiledGoFiles...)
+						// Add the package under test and its imports to the test variant.
+						pkg.forTest = testVariantOf.PkgPath
+						for k, v := range testVariantOf.Imports {
+							pkg.Imports[k] = &Package{ID: v.ID}
+						}
+					}
+					if isXTest {
+						pkg.forTest = forTest
+					}
+				}
+			}
+		}
+		if !fileExists {
+			pkg.GoFiles = append(pkg.GoFiles, opath)
+			// TODO(matloob): Adding the file to CompiledGoFiles can exhibit the wrong behavior
+			// if the file will be ignored due to its build tags.
+			pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, opath)
+			modifiedPkgsSet[pkg.ID] = true
+		}
+		imports, err := extractImports(opath, contents)
+		if err != nil {
+			// Let the parser or type checker report errors later.
+			continue
+		}
+		for _, imp := range imports {
+			// TODO(rstambler): If the package is an x test and the import has
+			// a test variant, make sure to replace it.
+			if _, found := pkg.Imports[imp]; found {
+				continue
+			}
+			overlayAddsImports = true
+			id, ok := havePkgs[imp]
+			if !ok {
+				var err error
+				id, err = state.resolveImport(dir, imp)
+				if err != nil {
+					return nil, nil, err
+				}
+			}
+			pkg.Imports[imp] = &Package{ID: id}
+			// Add dependencies to the non-test variant version of this package as well.
+			if testVariantOf != nil {
+				testVariantOf.Imports[imp] = &Package{ID: id}
+			}
+		}
+	}
+
+	// toPkgPath guesses the package path given the id.
+	toPkgPath := func(sourceDir, id string) (string, error) {
+		if i := strings.IndexByte(id, ' '); i >= 0 {
+			return state.resolveImport(sourceDir, id[:i])
+		}
+		return state.resolveImport(sourceDir, id)
+	}
+
+	// Now that new packages have been created, do another pass to determine
+	// the new set of missing packages.
+	for _, pkg := range response.dr.Packages {
+		for _, imp := range pkg.Imports {
+			if len(pkg.GoFiles) == 0 {
+				return nil, nil, fmt.Errorf("cannot resolve imports for package %q with no Go files", pkg.PkgPath)
+			}
+			pkgPath, err := toPkgPath(filepath.Dir(pkg.GoFiles[0]), imp.ID)
+			if err != nil {
+				return nil, nil, err
+			}
+			if _, ok := havePkgs[pkgPath]; !ok {
+				needPkgsSet[pkgPath] = true
+			}
+		}
+	}
+
+	if overlayAddsImports {
+		needPkgs = make([]string, 0, len(needPkgsSet))
+		for pkg := range needPkgsSet {
+			needPkgs = append(needPkgs, pkg)
+		}
+	}
+	modifiedPkgs = make([]string, 0, len(modifiedPkgsSet))
+	for pkg := range modifiedPkgsSet {
+		modifiedPkgs = append(modifiedPkgs, pkg)
+	}
+	return modifiedPkgs, needPkgs, err
+}
+
+// resolveImport finds the the ID of a package given its import path.
+// In particular, it will find the right vendored copy when in GOPATH mode.
+func (state *golistState) resolveImport(sourceDir, importPath string) (string, error) {
+	env, err := state.getEnv()
+	if err != nil {
+		return "", err
+	}
+	if env["GOMOD"] != "" {
+		return importPath, nil
+	}
+
+	searchDir := sourceDir
+	for {
+		vendorDir := filepath.Join(searchDir, "vendor")
+		exists, ok := state.vendorDirs[vendorDir]
+		if !ok {
+			info, err := os.Stat(vendorDir)
+			exists = err == nil && info.IsDir()
+			state.vendorDirs[vendorDir] = exists
+		}
+
+		if exists {
+			vendoredPath := filepath.Join(vendorDir, importPath)
+			if info, err := os.Stat(vendoredPath); err == nil && info.IsDir() {
+				// We should probably check for .go files here, but shame on anyone who fools us.
+				path, ok, err := state.getPkgPath(vendoredPath)
+				if err != nil {
+					return "", err
+				}
+				if ok {
+					return path, nil
+				}
+			}
+		}
+
+		// We know we've hit the top of the filesystem when we Dir / and get /,
+		// or C:\ and get C:\, etc.
+		next := filepath.Dir(searchDir)
+		if next == searchDir {
+			break
+		}
+		searchDir = next
+	}
+	return importPath, nil
+}
+
+func hasTestFiles(p *Package) bool {
+	for _, f := range p.GoFiles {
+		if strings.HasSuffix(f, "_test.go") {
+			return true
+		}
+	}
+	return false
+}
+
+// determineRootDirs returns a mapping from absolute directories that could
+// contain code to their corresponding import path prefixes.
+func (state *golistState) determineRootDirs() (map[string]string, error) {
+	env, err := state.getEnv()
+	if err != nil {
+		return nil, err
+	}
+	if env["GOMOD"] != "" {
+		state.rootsOnce.Do(func() {
+			state.rootDirs, state.rootDirsError = state.determineRootDirsModules()
+		})
+	} else {
+		state.rootsOnce.Do(func() {
+			state.rootDirs, state.rootDirsError = state.determineRootDirsGOPATH()
+		})
+	}
+	return state.rootDirs, state.rootDirsError
+}
+
+func (state *golistState) determineRootDirsModules() (map[string]string, error) {
+	// List all of the modules--the first will be the directory for the main
+	// module. Any replaced modules will also need to be treated as roots.
+	// Editing files in the module cache isn't a great idea, so we don't
+	// plan to ever support that.
+	out, err := state.invokeGo("list", "-m", "-json", "all")
+	if err != nil {
+		// 'go list all' will fail if we're outside of a module and
+		// GO111MODULE=on. Try falling back without 'all'.
+		var innerErr error
+		out, innerErr = state.invokeGo("list", "-m", "-json")
+		if innerErr != nil {
+			return nil, err
+		}
+	}
+	roots := map[string]string{}
+	modules := map[string]string{}
+	var i int
+	for dec := json.NewDecoder(out); dec.More(); {
+		mod := new(gocommand.ModuleJSON)
+		if err := dec.Decode(mod); err != nil {
+			return nil, err
+		}
+		if mod.Dir != "" && mod.Path != "" {
+			// This is a valid module; add it to the map.
+			absDir, err := filepath.Abs(mod.Dir)
+			if err != nil {
+				return nil, err
+			}
+			modules[absDir] = mod.Path
+			// The first result is the main module.
+			if i == 0 || mod.Replace != nil && mod.Replace.Path != "" {
+				roots[absDir] = mod.Path
+			}
+		}
+		i++
+	}
+	return roots, nil
+}
+
+func (state *golistState) determineRootDirsGOPATH() (map[string]string, error) {
+	m := map[string]string{}
+	for _, dir := range filepath.SplitList(state.mustGetEnv()["GOPATH"]) {
+		absDir, err := filepath.Abs(dir)
+		if err != nil {
+			return nil, err
+		}
+		m[filepath.Join(absDir, "src")] = ""
+	}
+	return m, nil
+}
+
+func extractImports(filename string, contents []byte) ([]string, error) {
+	f, err := parser.ParseFile(token.NewFileSet(), filename, contents, parser.ImportsOnly) // TODO(matloob): reuse fileset?
+	if err != nil {
+		return nil, err
+	}
+	var res []string
+	for _, imp := range f.Imports {
+		quotedPath := imp.Path.Value
+		path, err := strconv.Unquote(quotedPath)
+		if err != nil {
+			return nil, err
+		}
+		res = append(res, path)
+	}
+	return res, nil
+}
+
+// reclaimPackage attempts to reuse a package that failed to load in an overlay.
+//
+// If the package has errors and has no Name, GoFiles, or Imports,
+// then it's possible that it doesn't yet exist on disk.
+func reclaimPackage(pkg *Package, id string, filename string, contents []byte) bool {
+	// TODO(rstambler): Check the message of the actual error?
+	// It differs between $GOPATH and module mode.
+	if pkg.ID != id {
+		return false
+	}
+	if len(pkg.Errors) != 1 {
+		return false
+	}
+	if pkg.Name != "" || pkg.ExportFile != "" {
+		return false
+	}
+	if len(pkg.GoFiles) > 0 || len(pkg.CompiledGoFiles) > 0 || len(pkg.OtherFiles) > 0 {
+		return false
+	}
+	if len(pkg.Imports) > 0 {
+		return false
+	}
+	pkgName, ok := extractPackageName(filename, contents)
+	if !ok {
+		return false
+	}
+	pkg.Name = pkgName
+	pkg.Errors = nil
+	return true
+}
+
+func extractPackageName(filename string, contents []byte) (string, bool) {
+	// TODO(rstambler): Check the message of the actual error?
+	// It differs between $GOPATH and module mode.
+	f, err := parser.ParseFile(token.NewFileSet(), filename, contents, parser.PackageClauseOnly) // TODO(matloob): reuse fileset?
+	if err != nil {
+		return "", false
+	}
+	return f.Name.Name, true
+}
+
+func commonDir(a []string) string {
+	seen := make(map[string]bool)
+	x := append([]string{}, a...)
+	for _, f := range x {
+		seen[filepath.Dir(f)] = true
+	}
+	if len(seen) > 1 {
+		log.Fatalf("commonDir saw %v for %v", seen, x)
+	}
+	for k := range seen {
+		// len(seen) == 1
+		return k
+	}
+	return "" // no files
+}
+
+// It is possible that the files in the disk directory dir have a different package
+// name from newName, which is deduced from the overlays. If they all have a different
+// package name, and they all have the same package name, then that name becomes
+// the package name.
+// It returns true if it changes the package name, false otherwise.
+func maybeFixPackageName(newName string, isTestFile bool, pkgsOfDir []*Package) {
+	names := make(map[string]int)
+	for _, p := range pkgsOfDir {
+		names[p.Name]++
+	}
+	if len(names) != 1 {
+		// some files are in different packages
+		return
+	}
+	var oldName string
+	for k := range names {
+		oldName = k
+	}
+	if newName == oldName {
+		return
+	}
+	// We might have a case where all of the package names in the directory are
+	// the same, but the overlay file is for an x test, which belongs to its
+	// own package. If the x test does not yet exist on disk, we may not yet
+	// have its package name on disk, but we should not rename the packages.
+	//
+	// We use a heuristic to determine if this file belongs to an x test:
+	// The test file should have a package name whose package name has a _test
+	// suffix or looks like "newName_test".
+	maybeXTest := strings.HasPrefix(oldName+"_test", newName) || strings.HasSuffix(newName, "_test")
+	if isTestFile && maybeXTest {
+		return
+	}
+	for _, p := range pkgsOfDir {
+		p.Name = newName
+	}
+}
+
+// This function is copy-pasted from
+// https://github.com/golang/go/blob/9706f510a5e2754595d716bd64be8375997311fb/src/cmd/go/internal/search/search.go#L360.
+// It should be deleted when we remove support for overlays from go/packages.
+//
+// NOTE: This does not handle any ./... or ./ style queries, as this function
+// doesn't know the working directory.
+//
+// matchPattern(pattern)(name) reports whether
+// name matches pattern. Pattern is a limited glob
+// pattern in which '...' means 'any string' and there
+// is no other special syntax.
+// Unfortunately, there are two special cases. Quoting "go help packages":
+//
+// First, /... at the end of the pattern can match an empty string,
+// so that net/... matches both net and packages in its subdirectories, like net/http.
+// Second, any slash-separated pattern element containing a wildcard never
+// participates in a match of the "vendor" element in the path of a vendored
+// package, so that ./... does not match packages in subdirectories of
+// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do.
+// Note, however, that a directory named vendor that itself contains code
+// is not a vendored package: cmd/vendor would be a command named vendor,
+// and the pattern cmd/... matches it.
+func matchPattern(pattern string) func(name string) bool {
+	// Convert pattern to regular expression.
+	// The strategy for the trailing /... is to nest it in an explicit ? expression.
+	// The strategy for the vendor exclusion is to change the unmatchable
+	// vendor strings to a disallowed code point (vendorChar) and to use
+	// "(anything but that codepoint)*" as the implementation of the ... wildcard.
+	// This is a bit complicated but the obvious alternative,
+	// namely a hand-written search like in most shell glob matchers,
+	// is too easy to make accidentally exponential.
+	// Using package regexp guarantees linear-time matching.
+
+	const vendorChar = "\x00"
+
+	if strings.Contains(pattern, vendorChar) {
+		return func(name string) bool { return false }
+	}
+
+	re := regexp.QuoteMeta(pattern)
+	re = replaceVendor(re, vendorChar)
+	switch {
+	case strings.HasSuffix(re, `/`+vendorChar+`/\.\.\.`):
+		re = strings.TrimSuffix(re, `/`+vendorChar+`/\.\.\.`) + `(/vendor|/` + vendorChar + `/\.\.\.)`
+	case re == vendorChar+`/\.\.\.`:
+		re = `(/vendor|/` + vendorChar + `/\.\.\.)`
+	case strings.HasSuffix(re, `/\.\.\.`):
+		re = strings.TrimSuffix(re, `/\.\.\.`) + `(/\.\.\.)?`
+	}
+	re = strings.ReplaceAll(re, `\.\.\.`, `[^`+vendorChar+`]*`)
+
+	reg := regexp.MustCompile(`^` + re + `$`)
+
+	return func(name string) bool {
+		if strings.Contains(name, vendorChar) {
+			return false
+		}
+		return reg.MatchString(replaceVendor(name, vendorChar))
+	}
+}
+
+// replaceVendor returns the result of replacing
+// non-trailing vendor path elements in x with repl.
+func replaceVendor(x, repl string) string {
+	if !strings.Contains(x, "vendor") {
+		return x
+	}
+	elem := strings.Split(x, "/")
+	for i := 0; i < len(elem)-1; i++ {
+		if elem[i] == "vendor" {
+			elem[i] = repl
+		}
+	}
+	return strings.Join(elem, "/")
+}
diff --git a/vendor/golang.org/x/tools/go/packages/loadmode_string.go b/vendor/golang.org/x/tools/go/packages/loadmode_string.go
new file mode 100644
index 000000000..7ea37e7ee
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/packages/loadmode_string.go
@@ -0,0 +1,57 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packages
+
+import (
+	"fmt"
+	"strings"
+)
+
+var allModes = []LoadMode{
+	NeedName,
+	NeedFiles,
+	NeedCompiledGoFiles,
+	NeedImports,
+	NeedDeps,
+	NeedExportsFile,
+	NeedTypes,
+	NeedSyntax,
+	NeedTypesInfo,
+	NeedTypesSizes,
+}
+
+var modeStrings = []string{
+	"NeedName",
+	"NeedFiles",
+	"NeedCompiledGoFiles",
+	"NeedImports",
+	"NeedDeps",
+	"NeedExportsFile",
+	"NeedTypes",
+	"NeedSyntax",
+	"NeedTypesInfo",
+	"NeedTypesSizes",
+}
+
+func (mod LoadMode) String() string {
+	m := mod
+	if m == 0 {
+		return "LoadMode(0)"
+	}
+	var out []string
+	for i, x := range allModes {
+		if x > m {
+			break
+		}
+		if (m & x) != 0 {
+			out = append(out, modeStrings[i])
+			m = m ^ x
+		}
+	}
+	if m != 0 {
+		out = append(out, "Unknown")
+	}
+	return fmt.Sprintf("LoadMode(%s)", strings.Join(out, "|"))
+}
diff --git a/vendor/golang.org/x/tools/go/packages/packages.go b/vendor/golang.org/x/tools/go/packages/packages.go
new file mode 100644
index 000000000..04053f1e7
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/packages/packages.go
@@ -0,0 +1,1212 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package packages
+
+// See doc.go for package documentation and implementation notes.
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/scanner"
+	"go/token"
+	"go/types"
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"strings"
+	"sync"
+	"time"
+
+	"golang.org/x/tools/go/gcexportdata"
+	"golang.org/x/tools/internal/gocommand"
+	"golang.org/x/tools/internal/packagesinternal"
+	"golang.org/x/tools/internal/typesinternal"
+)
+
+// A LoadMode controls the amount of detail to return when loading.
+// The bits below can be combined to specify which fields should be
+// filled in the result packages.
+// The zero value is a special case, equivalent to combining
+// the NeedName, NeedFiles, and NeedCompiledGoFiles bits.
+// ID and Errors (if present) will always be filled.
+// Load may return more information than requested.
+type LoadMode int
+
+// TODO(matloob): When a V2 of go/packages is released, rename NeedExportsFile to
+// NeedExportFile to make it consistent with the Package field it's adding.
+
+const (
+	// NeedName adds Name and PkgPath.
+	NeedName LoadMode = 1 << iota
+
+	// NeedFiles adds GoFiles and OtherFiles.
+	NeedFiles
+
+	// NeedCompiledGoFiles adds CompiledGoFiles.
+	NeedCompiledGoFiles
+
+	// NeedImports adds Imports. If NeedDeps is not set, the Imports field will contain
+	// "placeholder" Packages with only the ID set.
+	NeedImports
+
+	// NeedDeps adds the fields requested by the LoadMode in the packages in Imports.
+	NeedDeps
+
+	// NeedExportsFile adds ExportFile.
+	NeedExportsFile
+
+	// NeedTypes adds Types, Fset, and IllTyped.
+	NeedTypes
+
+	// NeedSyntax adds Syntax.
+	NeedSyntax
+
+	// NeedTypesInfo adds TypesInfo.
+	NeedTypesInfo
+
+	// NeedTypesSizes adds TypesSizes.
+	NeedTypesSizes
+
+	// typecheckCgo enables full support for type checking cgo. Requires Go 1.15+.
+	// Modifies CompiledGoFiles and Types, and has no effect on its own.
+	typecheckCgo
+
+	// NeedModule adds Module.
+	NeedModule
+)
+
+const (
+	// Deprecated: LoadFiles exists for historical compatibility
+	// and should not be used. Please directly specify the needed fields using the Need values.
+	LoadFiles = NeedName | NeedFiles | NeedCompiledGoFiles
+
+	// Deprecated: LoadImports exists for historical compatibility
+	// and should not be used. Please directly specify the needed fields using the Need values.
+	LoadImports = LoadFiles | NeedImports
+
+	// Deprecated: LoadTypes exists for historical compatibility
+	// and should not be used. Please directly specify the needed fields using the Need values.
+	LoadTypes = LoadImports | NeedTypes | NeedTypesSizes
+
+	// Deprecated: LoadSyntax exists for historical compatibility
+	// and should not be used. Please directly specify the needed fields using the Need values.
+	LoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo
+
+	// Deprecated: LoadAllSyntax exists for historical compatibility
+	// and should not be used. Please directly specify the needed fields using the Need values.
+	LoadAllSyntax = LoadSyntax | NeedDeps
+)
+
+// A Config specifies details about how packages should be loaded.
+// The zero value is a valid configuration.
+// Calls to Load do not modify this struct.
+type Config struct {
+	// Mode controls the level of information returned for each package.
+	Mode LoadMode
+
+	// Context specifies the context for the load operation.
+	// If the context is cancelled, the loader may stop early
+	// and return an ErrCancelled error.
+	// If Context is nil, the load cannot be cancelled.
+	Context context.Context
+
+	// Logf is the logger for the config.
+	// If the user provides a logger, debug logging is enabled.
+	// If the GOPACKAGESDEBUG environment variable is set to true,
+	// but the logger is nil, default to log.Printf.
+	Logf func(format string, args ...interface{})
+
+	// Dir is the directory in which to run the build system's query tool
+	// that provides information about the packages.
+	// If Dir is empty, the tool is run in the current directory.
+	Dir string
+
+	// Env is the environment to use when invoking the build system's query tool.
+	// If Env is nil, the current environment is used.
+	// As in os/exec's Cmd, only the last value in the slice for
+	// each environment key is used. To specify the setting of only
+	// a few variables, append to the current environment, as in:
+	//
+	//	opt.Env = append(os.Environ(), "GOOS=plan9", "GOARCH=386")
+	//
+	Env []string
+
+	// gocmdRunner guards go command calls from concurrency errors.
+	gocmdRunner *gocommand.Runner
+
+	// BuildFlags is a list of command-line flags to be passed through to
+	// the build system's query tool.
+	BuildFlags []string
+
+	// Fset provides source position information for syntax trees and types.
+	// If Fset is nil, Load will use a new fileset, but preserve Fset's value.
+	Fset *token.FileSet
+
+	// ParseFile is called to read and parse each file
+	// when preparing a package's type-checked syntax tree.
+	// It must be safe to call ParseFile simultaneously from multiple goroutines.
+	// If ParseFile is nil, the loader will uses parser.ParseFile.
+	//
+	// ParseFile should parse the source from src and use filename only for
+	// recording position information.
+	//
+	// An application may supply a custom implementation of ParseFile
+	// to change the effective file contents or the behavior of the parser,
+	// or to modify the syntax tree. For example, selectively eliminating
+	// unwanted function bodies can significantly accelerate type checking.
+	ParseFile func(fset *token.FileSet, filename string, src []byte) (*ast.File, error)
+
+	// If Tests is set, the loader includes not just the packages
+	// matching a particular pattern but also any related test packages,
+	// including test-only variants of the package and the test executable.
+	//
+	// For example, when using the go command, loading "fmt" with Tests=true
+	// returns four packages, with IDs "fmt" (the standard package),
+	// "fmt [fmt.test]" (the package as compiled for the test),
+	// "fmt_test" (the test functions from source files in package fmt_test),
+	// and "fmt.test" (the test binary).
+	//
+	// In build systems with explicit names for tests,
+	// setting Tests may have no effect.
+	Tests bool
+
+	// Overlay provides a mapping of absolute file paths to file contents.
+	// If the file with the given path already exists, the parser will use the
+	// alternative file contents provided by the map.
+	//
+	// Overlays provide incomplete support for when a given file doesn't
+	// already exist on disk. See the package doc above for more details.
+	Overlay map[string][]byte
+}
+
+// driver is the type for functions that query the build system for the
+// packages named by the patterns.
+type driver func(cfg *Config, patterns ...string) (*driverResponse, error)
+
+// driverResponse contains the results for a driver query.
+type driverResponse struct {
+	// NotHandled is returned if the request can't be handled by the current
+	// driver. If an external driver returns a response with NotHandled, the
+	// rest of the driverResponse is ignored, and go/packages will fallback
+	// to the next driver. If go/packages is extended in the future to support
+	// lists of multiple drivers, go/packages will fall back to the next driver.
+	NotHandled bool
+
+	// Sizes, if not nil, is the types.Sizes to use when type checking.
+	Sizes *types.StdSizes
+
+	// Roots is the set of package IDs that make up the root packages.
+	// We have to encode this separately because when we encode a single package
+	// we cannot know if it is one of the roots as that requires knowledge of the
+	// graph it is part of.
+	Roots []string `json:",omitempty"`
+
+	// Packages is the full set of packages in the graph.
+	// The packages are not connected into a graph.
+	// The Imports if populated will be stubs that only have their ID set.
+	// Imports will be connected and then type and syntax information added in a
+	// later pass (see refine).
+	Packages []*Package
+}
+
+// Load loads and returns the Go packages named by the given patterns.
+//
+// Config specifies loading options;
+// nil behaves the same as an empty Config.
+//
+// Load returns an error if any of the patterns was invalid
+// as defined by the underlying build system.
+// It may return an empty list of packages without an error,
+// for instance for an empty expansion of a valid wildcard.
+// Errors associated with a particular package are recorded in the
+// corresponding Package's Errors list, and do not cause Load to
+// return an error. Clients may need to handle such errors before
+// proceeding with further analysis. The PrintErrors function is
+// provided for convenient display of all errors.
+func Load(cfg *Config, patterns ...string) ([]*Package, error) {
+	l := newLoader(cfg)
+	response, err := defaultDriver(&l.Config, patterns...)
+	if err != nil {
+		return nil, err
+	}
+	l.sizes = response.Sizes
+	return l.refine(response.Roots, response.Packages...)
+}
+
+// defaultDriver is a driver that implements go/packages' fallback behavior.
+// It will try to request to an external driver, if one exists. If there's
+// no external driver, or the driver returns a response with NotHandled set,
+// defaultDriver will fall back to the go list driver.
+func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
+	driver := findExternalDriver(cfg)
+	if driver == nil {
+		driver = goListDriver
+	}
+	response, err := driver(cfg, patterns...)
+	if err != nil {
+		return response, err
+	} else if response.NotHandled {
+		return goListDriver(cfg, patterns...)
+	}
+	return response, nil
+}
+
+// A Package describes a loaded Go package.
+type Package struct {
+	// ID is a unique identifier for a package,
+	// in a syntax provided by the underlying build system.
+	//
+	// Because the syntax varies based on the build system,
+	// clients should treat IDs as opaque and not attempt to
+	// interpret them.
+	ID string
+
+	// Name is the package name as it appears in the package source code.
+	Name string
+
+	// PkgPath is the package path as used by the go/types package.
+	PkgPath string
+
+	// Errors contains any errors encountered querying the metadata
+	// of the package, or while parsing or type-checking its files.
+	Errors []Error
+
+	// GoFiles lists the absolute file paths of the package's Go source files.
+	GoFiles []string
+
+	// CompiledGoFiles lists the absolute file paths of the package's source
+	// files that are suitable for type checking.
+	// This may differ from GoFiles if files are processed before compilation.
+	CompiledGoFiles []string
+
+	// OtherFiles lists the absolute file paths of the package's non-Go source files,
+	// including assembly, C, C++, Fortran, Objective-C, SWIG, and so on.
+	OtherFiles []string
+
+	// ExportFile is the absolute path to a file containing type
+	// information for the package as provided by the build system.
+	ExportFile string
+
+	// Imports maps import paths appearing in the package's Go source files
+	// to corresponding loaded Packages.
+	Imports map[string]*Package
+
+	// Types provides type information for the package.
+	// The NeedTypes LoadMode bit sets this field for packages matching the
+	// patterns; type information for dependencies may be missing or incomplete,
+	// unless NeedDeps and NeedImports are also set.
+	Types *types.Package
+
+	// Fset provides position information for Types, TypesInfo, and Syntax.
+	// It is set only when Types is set.
+	Fset *token.FileSet
+
+	// IllTyped indicates whether the package or any dependency contains errors.
+	// It is set only when Types is set.
+	IllTyped bool
+
+	// Syntax is the package's syntax trees, for the files listed in CompiledGoFiles.
+	//
+	// The NeedSyntax LoadMode bit populates this field for packages matching the patterns.
+	// If NeedDeps and NeedImports are also set, this field will also be populated
+	// for dependencies.
+	Syntax []*ast.File
+
+	// TypesInfo provides type information about the package's syntax trees.
+	// It is set only when Syntax is set.
+	TypesInfo *types.Info
+
+	// TypesSizes provides the effective size function for types in TypesInfo.
+	TypesSizes types.Sizes
+
+	// forTest is the package under test, if any.
+	forTest string
+
+	// module is the module information for the package if it exists.
+	Module *Module
+}
+
+// Module provides module information for a package.
+type Module struct {
+	Path      string       // module path
+	Version   string       // module version
+	Replace   *Module      // replaced by this module
+	Time      *time.Time   // time version was created
+	Main      bool         // is this the main module?
+	Indirect  bool         // is this module only an indirect dependency of main module?
+	Dir       string       // directory holding files for this module, if any
+	GoMod     string       // path to go.mod file used when loading this module, if any
+	GoVersion string       // go version used in module
+	Error     *ModuleError // error loading module
+}
+
+// ModuleError holds errors loading a module.
+type ModuleError struct {
+	Err string // the error itself
+}
+
+func init() {
+	packagesinternal.GetForTest = func(p interface{}) string {
+		return p.(*Package).forTest
+	}
+	packagesinternal.GetGoCmdRunner = func(config interface{}) *gocommand.Runner {
+		return config.(*Config).gocmdRunner
+	}
+	packagesinternal.SetGoCmdRunner = func(config interface{}, runner *gocommand.Runner) {
+		config.(*Config).gocmdRunner = runner
+	}
+	packagesinternal.TypecheckCgo = int(typecheckCgo)
+}
+
+// An Error describes a problem with a package's metadata, syntax, or types.
+type Error struct {
+	Pos  string // "file:line:col" or "file:line" or "" or "-"
+	Msg  string
+	Kind ErrorKind
+}
+
+// ErrorKind describes the source of the error, allowing the user to
+// differentiate between errors generated by the driver, the parser, or the
+// type-checker.
+type ErrorKind int
+
+const (
+	UnknownError ErrorKind = iota
+	ListError
+	ParseError
+	TypeError
+)
+
+func (err Error) Error() string {
+	pos := err.Pos
+	if pos == "" {
+		pos = "-" // like token.Position{}.String()
+	}
+	return pos + ": " + err.Msg
+}
+
+// flatPackage is the JSON form of Package
+// It drops all the type and syntax fields, and transforms the Imports
+//
+// TODO(adonovan): identify this struct with Package, effectively
+// publishing the JSON protocol.
+type flatPackage struct {
+	ID              string
+	Name            string            `json:",omitempty"`
+	PkgPath         string            `json:",omitempty"`
+	Errors          []Error           `json:",omitempty"`
+	GoFiles         []string          `json:",omitempty"`
+	CompiledGoFiles []string          `json:",omitempty"`
+	OtherFiles      []string          `json:",omitempty"`
+	ExportFile      string            `json:",omitempty"`
+	Imports         map[string]string `json:",omitempty"`
+}
+
+// MarshalJSON returns the Package in its JSON form.
+// For the most part, the structure fields are written out unmodified, and
+// the type and syntax fields are skipped.
+// The imports are written out as just a map of path to package id.
+// The errors are written using a custom type that tries to preserve the
+// structure of error types we know about.
+//
+// This method exists to enable support for additional build systems.  It is
+// not intended for use by clients of the API and we may change the format.
+func (p *Package) MarshalJSON() ([]byte, error) {
+	flat := &flatPackage{
+		ID:              p.ID,
+		Name:            p.Name,
+		PkgPath:         p.PkgPath,
+		Errors:          p.Errors,
+		GoFiles:         p.GoFiles,
+		CompiledGoFiles: p.CompiledGoFiles,
+		OtherFiles:      p.OtherFiles,
+		ExportFile:      p.ExportFile,
+	}
+	if len(p.Imports) > 0 {
+		flat.Imports = make(map[string]string, len(p.Imports))
+		for path, ipkg := range p.Imports {
+			flat.Imports[path] = ipkg.ID
+		}
+	}
+	return json.Marshal(flat)
+}
+
+// UnmarshalJSON reads in a Package from its JSON format.
+// See MarshalJSON for details about the format accepted.
+func (p *Package) UnmarshalJSON(b []byte) error {
+	flat := &flatPackage{}
+	if err := json.Unmarshal(b, &flat); err != nil {
+		return err
+	}
+	*p = Package{
+		ID:              flat.ID,
+		Name:            flat.Name,
+		PkgPath:         flat.PkgPath,
+		Errors:          flat.Errors,
+		GoFiles:         flat.GoFiles,
+		CompiledGoFiles: flat.CompiledGoFiles,
+		OtherFiles:      flat.OtherFiles,
+		ExportFile:      flat.ExportFile,
+	}
+	if len(flat.Imports) > 0 {
+		p.Imports = make(map[string]*Package, len(flat.Imports))
+		for path, id := range flat.Imports {
+			p.Imports[path] = &Package{ID: id}
+		}
+	}
+	return nil
+}
+
+func (p *Package) String() string { return p.ID }
+
+// loaderPackage augments Package with state used during the loading phase
+type loaderPackage struct {
+	*Package
+	importErrors map[string]error // maps each bad import to its error
+	loadOnce     sync.Once
+	color        uint8 // for cycle detection
+	needsrc      bool  // load from source (Mode >= LoadTypes)
+	needtypes    bool  // type information is either requested or depended on
+	initial      bool  // package was matched by a pattern
+}
+
+// loader holds the working state of a single call to load.
+type loader struct {
+	pkgs map[string]*loaderPackage
+	Config
+	sizes        types.Sizes
+	parseCache   map[string]*parseValue
+	parseCacheMu sync.Mutex
+	exportMu     sync.Mutex // enforces mutual exclusion of exportdata operations
+
+	// Config.Mode contains the implied mode (see impliedLoadMode).
+	// Implied mode contains all the fields we need the data for.
+	// In requestedMode there are the actually requested fields.
+	// We'll zero them out before returning packages to the user.
+	// This makes it easier for us to get the conditions where
+	// we need certain modes right.
+	requestedMode LoadMode
+}
+
+type parseValue struct {
+	f     *ast.File
+	err   error
+	ready chan struct{}
+}
+
+func newLoader(cfg *Config) *loader {
+	ld := &loader{
+		parseCache: map[string]*parseValue{},
+	}
+	if cfg != nil {
+		ld.Config = *cfg
+		// If the user has provided a logger, use it.
+		ld.Config.Logf = cfg.Logf
+	}
+	if ld.Config.Logf == nil {
+		// If the GOPACKAGESDEBUG environment variable is set to true,
+		// but the user has not provided a logger, default to log.Printf.
+		if debug {
+			ld.Config.Logf = log.Printf
+		} else {
+			ld.Config.Logf = func(format string, args ...interface{}) {}
+		}
+	}
+	if ld.Config.Mode == 0 {
+		ld.Config.Mode = NeedName | NeedFiles | NeedCompiledGoFiles // Preserve zero behavior of Mode for backwards compatibility.
+	}
+	if ld.Config.Env == nil {
+		ld.Config.Env = os.Environ()
+	}
+	if ld.Config.gocmdRunner == nil {
+		ld.Config.gocmdRunner = &gocommand.Runner{}
+	}
+	if ld.Context == nil {
+		ld.Context = context.Background()
+	}
+	if ld.Dir == "" {
+		if dir, err := os.Getwd(); err == nil {
+			ld.Dir = dir
+		}
+	}
+
+	// Save the actually requested fields. We'll zero them out before returning packages to the user.
+	ld.requestedMode = ld.Mode
+	ld.Mode = impliedLoadMode(ld.Mode)
+
+	if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 {
+		if ld.Fset == nil {
+			ld.Fset = token.NewFileSet()
+		}
+
+		// ParseFile is required even in LoadTypes mode
+		// because we load source if export data is missing.
+		if ld.ParseFile == nil {
+			ld.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
+				const mode = parser.AllErrors | parser.ParseComments
+				return parser.ParseFile(fset, filename, src, mode)
+			}
+		}
+	}
+
+	return ld
+}
+
+// refine connects the supplied packages into a graph and then adds type and
+// and syntax information as requested by the LoadMode.
+func (ld *loader) refine(roots []string, list ...*Package) ([]*Package, error) {
+	rootMap := make(map[string]int, len(roots))
+	for i, root := range roots {
+		rootMap[root] = i
+	}
+	ld.pkgs = make(map[string]*loaderPackage)
+	// first pass, fixup and build the map and roots
+	var initial = make([]*loaderPackage, len(roots))
+	for _, pkg := range list {
+		rootIndex := -1
+		if i, found := rootMap[pkg.ID]; found {
+			rootIndex = i
+		}
+
+		// Overlays can invalidate export data.
+		// TODO(matloob): make this check fine-grained based on dependencies on overlaid files
+		exportDataInvalid := len(ld.Overlay) > 0 || pkg.ExportFile == "" && pkg.PkgPath != "unsafe"
+		// This package needs type information if the caller requested types and the package is
+		// either a root, or it's a non-root and the user requested dependencies ...
+		needtypes := (ld.Mode&NeedTypes|NeedTypesInfo != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0))
+		// This package needs source if the call requested source (or types info, which implies source)
+		// and the package is either a root, or itas a non- root and the user requested dependencies...
+		needsrc := ((ld.Mode&(NeedSyntax|NeedTypesInfo) != 0 && (rootIndex >= 0 || ld.Mode&NeedDeps != 0)) ||
+			// ... or if we need types and the exportData is invalid. We fall back to (incompletely)
+			// typechecking packages from source if they fail to compile.
+			(ld.Mode&NeedTypes|NeedTypesInfo != 0 && exportDataInvalid)) && pkg.PkgPath != "unsafe"
+		lpkg := &loaderPackage{
+			Package:   pkg,
+			needtypes: needtypes,
+			needsrc:   needsrc,
+		}
+		ld.pkgs[lpkg.ID] = lpkg
+		if rootIndex >= 0 {
+			initial[rootIndex] = lpkg
+			lpkg.initial = true
+		}
+	}
+	for i, root := range roots {
+		if initial[i] == nil {
+			return nil, fmt.Errorf("root package %v is missing", root)
+		}
+	}
+
+	// Materialize the import graph.
+
+	const (
+		white = 0 // new
+		grey  = 1 // in progress
+		black = 2 // complete
+	)
+
+	// visit traverses the import graph, depth-first,
+	// and materializes the graph as Packages.Imports.
+	//
+	// Valid imports are saved in the Packages.Import map.
+	// Invalid imports (cycles and missing nodes) are saved in the importErrors map.
+	// Thus, even in the presence of both kinds of errors, the Import graph remains a DAG.
+	//
+	// visit returns whether the package needs src or has a transitive
+	// dependency on a package that does. These are the only packages
+	// for which we load source code.
+	var stack []*loaderPackage
+	var visit func(lpkg *loaderPackage) bool
+	var srcPkgs []*loaderPackage
+	visit = func(lpkg *loaderPackage) bool {
+		switch lpkg.color {
+		case black:
+			return lpkg.needsrc
+		case grey:
+			panic("internal error: grey node")
+		}
+		lpkg.color = grey
+		stack = append(stack, lpkg) // push
+		stubs := lpkg.Imports       // the structure form has only stubs with the ID in the Imports
+		// If NeedImports isn't set, the imports fields will all be zeroed out.
+		if ld.Mode&NeedImports != 0 {
+			lpkg.Imports = make(map[string]*Package, len(stubs))
+			for importPath, ipkg := range stubs {
+				var importErr error
+				imp := ld.pkgs[ipkg.ID]
+				if imp == nil {
+					// (includes package "C" when DisableCgo)
+					importErr = fmt.Errorf("missing package: %q", ipkg.ID)
+				} else if imp.color == grey {
+					importErr = fmt.Errorf("import cycle: %s", stack)
+				}
+				if importErr != nil {
+					if lpkg.importErrors == nil {
+						lpkg.importErrors = make(map[string]error)
+					}
+					lpkg.importErrors[importPath] = importErr
+					continue
+				}
+
+				if visit(imp) {
+					lpkg.needsrc = true
+				}
+				lpkg.Imports[importPath] = imp.Package
+			}
+		}
+		if lpkg.needsrc {
+			srcPkgs = append(srcPkgs, lpkg)
+		}
+		if ld.Mode&NeedTypesSizes != 0 {
+			lpkg.TypesSizes = ld.sizes
+		}
+		stack = stack[:len(stack)-1] // pop
+		lpkg.color = black
+
+		return lpkg.needsrc
+	}
+
+	if ld.Mode&NeedImports == 0 {
+		// We do this to drop the stub import packages that we are not even going to try to resolve.
+		for _, lpkg := range initial {
+			lpkg.Imports = nil
+		}
+	} else {
+		// For each initial package, create its import DAG.
+		for _, lpkg := range initial {
+			visit(lpkg)
+		}
+	}
+	if ld.Mode&NeedImports != 0 && ld.Mode&NeedTypes != 0 {
+		for _, lpkg := range srcPkgs {
+			// Complete type information is required for the
+			// immediate dependencies of each source package.
+			for _, ipkg := range lpkg.Imports {
+				imp := ld.pkgs[ipkg.ID]
+				imp.needtypes = true
+			}
+		}
+	}
+	// Load type data and syntax if needed, starting at
+	// the initial packages (roots of the import DAG).
+	if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 {
+		var wg sync.WaitGroup
+		for _, lpkg := range initial {
+			wg.Add(1)
+			go func(lpkg *loaderPackage) {
+				ld.loadRecursive(lpkg)
+				wg.Done()
+			}(lpkg)
+		}
+		wg.Wait()
+	}
+
+	result := make([]*Package, len(initial))
+	for i, lpkg := range initial {
+		result[i] = lpkg.Package
+	}
+	for i := range ld.pkgs {
+		// Clear all unrequested fields, for extra de-Hyrum-ization.
+		if ld.requestedMode&NeedName == 0 {
+			ld.pkgs[i].Name = ""
+			ld.pkgs[i].PkgPath = ""
+		}
+		if ld.requestedMode&NeedFiles == 0 {
+			ld.pkgs[i].GoFiles = nil
+			ld.pkgs[i].OtherFiles = nil
+		}
+		if ld.requestedMode&NeedCompiledGoFiles == 0 {
+			ld.pkgs[i].CompiledGoFiles = nil
+		}
+		if ld.requestedMode&NeedImports == 0 {
+			ld.pkgs[i].Imports = nil
+		}
+		if ld.requestedMode&NeedExportsFile == 0 {
+			ld.pkgs[i].ExportFile = ""
+		}
+		if ld.requestedMode&NeedTypes == 0 {
+			ld.pkgs[i].Types = nil
+			ld.pkgs[i].Fset = nil
+			ld.pkgs[i].IllTyped = false
+		}
+		if ld.requestedMode&NeedSyntax == 0 {
+			ld.pkgs[i].Syntax = nil
+		}
+		if ld.requestedMode&NeedTypesInfo == 0 {
+			ld.pkgs[i].TypesInfo = nil
+		}
+		if ld.requestedMode&NeedTypesSizes == 0 {
+			ld.pkgs[i].TypesSizes = nil
+		}
+		if ld.requestedMode&NeedModule == 0 {
+			ld.pkgs[i].Module = nil
+		}
+	}
+
+	return result, nil
+}
+
+// loadRecursive loads the specified package and its dependencies,
+// recursively, in parallel, in topological order.
+// It is atomic and idempotent.
+// Precondition: ld.Mode&NeedTypes.
+func (ld *loader) loadRecursive(lpkg *loaderPackage) {
+	lpkg.loadOnce.Do(func() {
+		// Load the direct dependencies, in parallel.
+		var wg sync.WaitGroup
+		for _, ipkg := range lpkg.Imports {
+			imp := ld.pkgs[ipkg.ID]
+			wg.Add(1)
+			go func(imp *loaderPackage) {
+				ld.loadRecursive(imp)
+				wg.Done()
+			}(imp)
+		}
+		wg.Wait()
+		ld.loadPackage(lpkg)
+	})
+}
+
+// loadPackage loads the specified package.
+// It must be called only once per Package,
+// after immediate dependencies are loaded.
+// Precondition: ld.Mode & NeedTypes.
+func (ld *loader) loadPackage(lpkg *loaderPackage) {
+	if lpkg.PkgPath == "unsafe" {
+		// Fill in the blanks to avoid surprises.
+		lpkg.Types = types.Unsafe
+		lpkg.Fset = ld.Fset
+		lpkg.Syntax = []*ast.File{}
+		lpkg.TypesInfo = new(types.Info)
+		lpkg.TypesSizes = ld.sizes
+		return
+	}
+
+	// Call NewPackage directly with explicit name.
+	// This avoids skew between golist and go/types when the files'
+	// package declarations are inconsistent.
+	lpkg.Types = types.NewPackage(lpkg.PkgPath, lpkg.Name)
+	lpkg.Fset = ld.Fset
+
+	// Subtle: we populate all Types fields with an empty Package
+	// before loading export data so that export data processing
+	// never has to create a types.Package for an indirect dependency,
+	// which would then require that such created packages be explicitly
+	// inserted back into the Import graph as a final step after export data loading.
+	// The Diamond test exercises this case.
+	if !lpkg.needtypes && !lpkg.needsrc {
+		return
+	}
+	if !lpkg.needsrc {
+		ld.loadFromExportData(lpkg)
+		return // not a source package, don't get syntax trees
+	}
+
+	appendError := func(err error) {
+		// Convert various error types into the one true Error.
+		var errs []Error
+		switch err := err.(type) {
+		case Error:
+			// from driver
+			errs = append(errs, err)
+
+		case *os.PathError:
+			// from parser
+			errs = append(errs, Error{
+				Pos:  err.Path + ":1",
+				Msg:  err.Err.Error(),
+				Kind: ParseError,
+			})
+
+		case scanner.ErrorList:
+			// from parser
+			for _, err := range err {
+				errs = append(errs, Error{
+					Pos:  err.Pos.String(),
+					Msg:  err.Msg,
+					Kind: ParseError,
+				})
+			}
+
+		case types.Error:
+			// from type checker
+			errs = append(errs, Error{
+				Pos:  err.Fset.Position(err.Pos).String(),
+				Msg:  err.Msg,
+				Kind: TypeError,
+			})
+
+		default:
+			// unexpected impoverished error from parser?
+			errs = append(errs, Error{
+				Pos:  "-",
+				Msg:  err.Error(),
+				Kind: UnknownError,
+			})
+
+			// If you see this error message, please file a bug.
+			log.Printf("internal error: error %q (%T) without position", err, err)
+		}
+
+		lpkg.Errors = append(lpkg.Errors, errs...)
+	}
+
+	if ld.Config.Mode&NeedTypes != 0 && len(lpkg.CompiledGoFiles) == 0 && lpkg.ExportFile != "" {
+		// The config requested loading sources and types, but sources are missing.
+		// Add an error to the package and fall back to loading from export data.
+		appendError(Error{"-", fmt.Sprintf("sources missing for package %s", lpkg.ID), ParseError})
+		ld.loadFromExportData(lpkg)
+		return // can't get syntax trees for this package
+	}
+
+	files, errs := ld.parseFiles(lpkg.CompiledGoFiles)
+	for _, err := range errs {
+		appendError(err)
+	}
+
+	lpkg.Syntax = files
+	if ld.Config.Mode&NeedTypes == 0 {
+		return
+	}
+
+	lpkg.TypesInfo = &types.Info{
+		Types:      make(map[ast.Expr]types.TypeAndValue),
+		Defs:       make(map[*ast.Ident]types.Object),
+		Uses:       make(map[*ast.Ident]types.Object),
+		Implicits:  make(map[ast.Node]types.Object),
+		Scopes:     make(map[ast.Node]*types.Scope),
+		Selections: make(map[*ast.SelectorExpr]*types.Selection),
+	}
+	lpkg.TypesSizes = ld.sizes
+
+	importer := importerFunc(func(path string) (*types.Package, error) {
+		if path == "unsafe" {
+			return types.Unsafe, nil
+		}
+
+		// The imports map is keyed by import path.
+		ipkg := lpkg.Imports[path]
+		if ipkg == nil {
+			if err := lpkg.importErrors[path]; err != nil {
+				return nil, err
+			}
+			// There was skew between the metadata and the
+			// import declarations, likely due to an edit
+			// race, or because the ParseFile feature was
+			// used to supply alternative file contents.
+			return nil, fmt.Errorf("no metadata for %s", path)
+		}
+
+		if ipkg.Types != nil && ipkg.Types.Complete() {
+			return ipkg.Types, nil
+		}
+		log.Fatalf("internal error: package %q without types was imported from %q", path, lpkg)
+		panic("unreachable")
+	})
+
+	// type-check
+	tc := &types.Config{
+		Importer: importer,
+
+		// Type-check bodies of functions only in non-initial packages.
+		// Example: for import graph A->B->C and initial packages {A,C},
+		// we can ignore function bodies in B.
+		IgnoreFuncBodies: ld.Mode&NeedDeps == 0 && !lpkg.initial,
+
+		Error: appendError,
+		Sizes: ld.sizes,
+	}
+	if (ld.Mode & typecheckCgo) != 0 {
+		if !typesinternal.SetUsesCgo(tc) {
+			appendError(Error{
+				Msg:  "typecheckCgo requires Go 1.15+",
+				Kind: ListError,
+			})
+			return
+		}
+	}
+	types.NewChecker(tc, ld.Fset, lpkg.Types, lpkg.TypesInfo).Files(lpkg.Syntax)
+
+	lpkg.importErrors = nil // no longer needed
+
+	// If !Cgo, the type-checker uses FakeImportC mode, so
+	// it doesn't invoke the importer for import "C",
+	// nor report an error for the import,
+	// or for any undefined C.f reference.
+	// We must detect this explicitly and correctly
+	// mark the package as IllTyped (by reporting an error).
+	// TODO(adonovan): if these errors are annoying,
+	// we could just set IllTyped quietly.
+	if tc.FakeImportC {
+	outer:
+		for _, f := range lpkg.Syntax {
+			for _, imp := range f.Imports {
+				if imp.Path.Value == `"C"` {
+					err := types.Error{Fset: ld.Fset, Pos: imp.Pos(), Msg: `import "C" ignored`}
+					appendError(err)
+					break outer
+				}
+			}
+		}
+	}
+
+	// Record accumulated errors.
+	illTyped := len(lpkg.Errors) > 0
+	if !illTyped {
+		for _, imp := range lpkg.Imports {
+			if imp.IllTyped {
+				illTyped = true
+				break
+			}
+		}
+	}
+	lpkg.IllTyped = illTyped
+}
+
+// An importFunc is an implementation of the single-method
+// types.Importer interface based on a function value.
+type importerFunc func(path string) (*types.Package, error)
+
+func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }
+
+// We use a counting semaphore to limit
+// the number of parallel I/O calls per process.
+var ioLimit = make(chan bool, 20)
+
+func (ld *loader) parseFile(filename string) (*ast.File, error) {
+	ld.parseCacheMu.Lock()
+	v, ok := ld.parseCache[filename]
+	if ok {
+		// cache hit
+		ld.parseCacheMu.Unlock()
+		<-v.ready
+	} else {
+		// cache miss
+		v = &parseValue{ready: make(chan struct{})}
+		ld.parseCache[filename] = v
+		ld.parseCacheMu.Unlock()
+
+		var src []byte
+		for f, contents := range ld.Config.Overlay {
+			if sameFile(f, filename) {
+				src = contents
+			}
+		}
+		var err error
+		if src == nil {
+			ioLimit <- true // wait
+			src, err = ioutil.ReadFile(filename)
+			<-ioLimit // signal
+		}
+		if err != nil {
+			v.err = err
+		} else {
+			v.f, v.err = ld.ParseFile(ld.Fset, filename, src)
+		}
+
+		close(v.ready)
+	}
+	return v.f, v.err
+}
+
+// parseFiles reads and parses the Go source files and returns the ASTs
+// of the ones that could be at least partially parsed, along with a
+// list of I/O and parse errors encountered.
+//
+// Because files are scanned in parallel, the token.Pos
+// positions of the resulting ast.Files are not ordered.
+//
+func (ld *loader) parseFiles(filenames []string) ([]*ast.File, []error) {
+	var wg sync.WaitGroup
+	n := len(filenames)
+	parsed := make([]*ast.File, n)
+	errors := make([]error, n)
+	for i, file := range filenames {
+		if ld.Config.Context.Err() != nil {
+			parsed[i] = nil
+			errors[i] = ld.Config.Context.Err()
+			continue
+		}
+		wg.Add(1)
+		go func(i int, filename string) {
+			parsed[i], errors[i] = ld.parseFile(filename)
+			wg.Done()
+		}(i, file)
+	}
+	wg.Wait()
+
+	// Eliminate nils, preserving order.
+	var o int
+	for _, f := range parsed {
+		if f != nil {
+			parsed[o] = f
+			o++
+		}
+	}
+	parsed = parsed[:o]
+
+	o = 0
+	for _, err := range errors {
+		if err != nil {
+			errors[o] = err
+			o++
+		}
+	}
+	errors = errors[:o]
+
+	return parsed, errors
+}
+
+// sameFile returns true if x and y have the same basename and denote
+// the same file.
+//
+func sameFile(x, y string) bool {
+	if x == y {
+		// It could be the case that y doesn't exist.
+		// For instance, it may be an overlay file that
+		// hasn't been written to disk. To handle that case
+		// let x == y through. (We added the exact absolute path
+		// string to the CompiledGoFiles list, so the unwritten
+		// overlay case implies x==y.)
+		return true
+	}
+	if strings.EqualFold(filepath.Base(x), filepath.Base(y)) { // (optimisation)
+		if xi, err := os.Stat(x); err == nil {
+			if yi, err := os.Stat(y); err == nil {
+				return os.SameFile(xi, yi)
+			}
+		}
+	}
+	return false
+}
+
+// loadFromExportData returns type information for the specified
+// package, loading it from an export data file on the first request.
+func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error) {
+	if lpkg.PkgPath == "" {
+		log.Fatalf("internal error: Package %s has no PkgPath", lpkg)
+	}
+
+	// Because gcexportdata.Read has the potential to create or
+	// modify the types.Package for each node in the transitive
+	// closure of dependencies of lpkg, all exportdata operations
+	// must be sequential. (Finer-grained locking would require
+	// changes to the gcexportdata API.)
+	//
+	// The exportMu lock guards the Package.Pkg field and the
+	// types.Package it points to, for each Package in the graph.
+	//
+	// Not all accesses to Package.Pkg need to be protected by exportMu:
+	// graph ordering ensures that direct dependencies of source
+	// packages are fully loaded before the importer reads their Pkg field.
+	ld.exportMu.Lock()
+	defer ld.exportMu.Unlock()
+
+	if tpkg := lpkg.Types; tpkg != nil && tpkg.Complete() {
+		return tpkg, nil // cache hit
+	}
+
+	lpkg.IllTyped = true // fail safe
+
+	if lpkg.ExportFile == "" {
+		// Errors while building export data will have been printed to stderr.
+		return nil, fmt.Errorf("no export data file")
+	}
+	f, err := os.Open(lpkg.ExportFile)
+	if err != nil {
+		return nil, err
+	}
+	defer f.Close()
+
+	// Read gc export data.
+	//
+	// We don't currently support gccgo export data because all
+	// underlying workspaces use the gc toolchain. (Even build
+	// systems that support gccgo don't use it for workspace
+	// queries.)
+	r, err := gcexportdata.NewReader(f)
+	if err != nil {
+		return nil, fmt.Errorf("reading %s: %v", lpkg.ExportFile, err)
+	}
+
+	// Build the view.
+	//
+	// The gcexportdata machinery has no concept of package ID.
+	// It identifies packages by their PkgPath, which although not
+	// globally unique is unique within the scope of one invocation
+	// of the linker, type-checker, or gcexportdata.
+	//
+	// So, we must build a PkgPath-keyed view of the global
+	// (conceptually ID-keyed) cache of packages and pass it to
+	// gcexportdata. The view must contain every existing
+	// package that might possibly be mentioned by the
+	// current package---its transitive closure.
+	//
+	// In loadPackage, we unconditionally create a types.Package for
+	// each dependency so that export data loading does not
+	// create new ones.
+	//
+	// TODO(adonovan): it would be simpler and more efficient
+	// if the export data machinery invoked a callback to
+	// get-or-create a package instead of a map.
+	//
+	view := make(map[string]*types.Package) // view seen by gcexportdata
+	seen := make(map[*loaderPackage]bool)   // all visited packages
+	var visit func(pkgs map[string]*Package)
+	visit = func(pkgs map[string]*Package) {
+		for _, p := range pkgs {
+			lpkg := ld.pkgs[p.ID]
+			if !seen[lpkg] {
+				seen[lpkg] = true
+				view[lpkg.PkgPath] = lpkg.Types
+				visit(lpkg.Imports)
+			}
+		}
+	}
+	visit(lpkg.Imports)
+
+	viewLen := len(view) + 1 // adding the self package
+	// Parse the export data.
+	// (May modify incomplete packages in view but not create new ones.)
+	tpkg, err := gcexportdata.Read(r, ld.Fset, view, lpkg.PkgPath)
+	if err != nil {
+		return nil, fmt.Errorf("reading %s: %v", lpkg.ExportFile, err)
+	}
+	if viewLen != len(view) {
+		log.Fatalf("Unexpected package creation during export data loading")
+	}
+
+	lpkg.Types = tpkg
+	lpkg.IllTyped = false
+
+	return tpkg, nil
+}
+
+// impliedLoadMode returns loadMode with its dependencies.
+func impliedLoadMode(loadMode LoadMode) LoadMode {
+	if loadMode&NeedTypesInfo != 0 && loadMode&NeedImports == 0 {
+		// If NeedTypesInfo, go/packages needs to do typechecking itself so it can
+		// associate type info with the AST. To do so, we need the export data
+		// for dependencies, which means we need to ask for the direct dependencies.
+		// NeedImports is used to ask for the direct dependencies.
+		loadMode |= NeedImports
+	}
+
+	if loadMode&NeedDeps != 0 && loadMode&NeedImports == 0 {
+		// With NeedDeps we need to load at least direct dependencies.
+		// NeedImports is used to ask for the direct dependencies.
+		loadMode |= NeedImports
+	}
+
+	return loadMode
+}
+
+func usesExportData(cfg *Config) bool {
+	return cfg.Mode&NeedExportsFile != 0 || cfg.Mode&NeedTypes != 0 && cfg.Mode&NeedDeps == 0
+}
diff --git a/vendor/golang.org/x/tools/go/packages/visit.go b/vendor/golang.org/x/tools/go/packages/visit.go
new file mode 100644
index 000000000..b13cb081f
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/packages/visit.go
@@ -0,0 +1,55 @@
+package packages
+
+import (
+	"fmt"
+	"os"
+	"sort"
+)
+
+// Visit visits all the packages in the import graph whose roots are
+// pkgs, calling the optional pre function the first time each package
+// is encountered (preorder), and the optional post function after a
+// package's dependencies have been visited (postorder).
+// The boolean result of pre(pkg) determines whether
+// the imports of package pkg are visited.
+func Visit(pkgs []*Package, pre func(*Package) bool, post func(*Package)) {
+	seen := make(map[*Package]bool)
+	var visit func(*Package)
+	visit = func(pkg *Package) {
+		if !seen[pkg] {
+			seen[pkg] = true
+
+			if pre == nil || pre(pkg) {
+				paths := make([]string, 0, len(pkg.Imports))
+				for path := range pkg.Imports {
+					paths = append(paths, path)
+				}
+				sort.Strings(paths) // Imports is a map, this makes visit stable
+				for _, path := range paths {
+					visit(pkg.Imports[path])
+				}
+			}
+
+			if post != nil {
+				post(pkg)
+			}
+		}
+	}
+	for _, pkg := range pkgs {
+		visit(pkg)
+	}
+}
+
+// PrintErrors prints to os.Stderr the accumulated errors of all
+// packages in the import graph rooted at pkgs, dependencies first.
+// PrintErrors returns the number of errors printed.
+func PrintErrors(pkgs []*Package) int {
+	var n int
+	Visit(pkgs, nil, func(pkg *Package) {
+		for _, err := range pkg.Errors {
+			fmt.Fprintln(os.Stderr, err)
+			n++
+		}
+	})
+	return n
+}
diff --git a/vendor/golang.org/x/tools/internal/packagesinternal/packages.go b/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
new file mode 100644
index 000000000..2c4527f24
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
@@ -0,0 +1,14 @@
+// Package packagesinternal exposes internal-only fields from go/packages.
+package packagesinternal
+
+import (
+	"golang.org/x/tools/internal/gocommand"
+)
+
+var GetForTest = func(p interface{}) string { return "" }
+
+var GetGoCmdRunner = func(config interface{}) *gocommand.Runner { return nil }
+
+var SetGoCmdRunner = func(config interface{}, runner *gocommand.Runner) {}
+
+var TypecheckCgo int
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/types.go b/vendor/golang.org/x/tools/internal/typesinternal/types.go
new file mode 100644
index 000000000..a5bb408e2
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typesinternal/types.go
@@ -0,0 +1,28 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typesinternal
+
+import (
+	"go/types"
+	"reflect"
+	"unsafe"
+)
+
+func SetUsesCgo(conf *types.Config) bool {
+	v := reflect.ValueOf(conf).Elem()
+
+	f := v.FieldByName("go115UsesCgo")
+	if !f.IsValid() {
+		f = v.FieldByName("UsesCgo")
+		if !f.IsValid() {
+			return false
+		}
+	}
+
+	addr := unsafe.Pointer(f.UnsafeAddr())
+	*(*bool)(addr) = true
+
+	return true
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index c24682f93..be57e3817 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -362,10 +362,13 @@ golang.org/x/text/width
 # golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
 golang.org/x/time/rate
 # golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3
+## explicit
 golang.org/x/tools/cmd/goimports
 golang.org/x/tools/go/ast/astutil
 golang.org/x/tools/go/gcexportdata
 golang.org/x/tools/go/internal/gcimporter
+golang.org/x/tools/go/internal/packagesdriver
+golang.org/x/tools/go/packages
 golang.org/x/tools/imports
 golang.org/x/tools/internal/event
 golang.org/x/tools/internal/event/core
@@ -375,6 +378,8 @@ golang.org/x/tools/internal/fastwalk
 golang.org/x/tools/internal/gocommand
 golang.org/x/tools/internal/gopathwalk
 golang.org/x/tools/internal/imports
+golang.org/x/tools/internal/packagesinternal
+golang.org/x/tools/internal/typesinternal
 # golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
 golang.org/x/xerrors
 golang.org/x/xerrors/internal


Test patch:
diff --git a/depcheck/depcheck_test.go b/depcheck/depcheck_test.go
new file mode 100644
index 000000000..7f11bf67c
--- /dev/null
+++ b/depcheck/depcheck_test.go
@@ -0,0 +1,50 @@
+/*
+Copyright 2020 The Knative Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Package depcheck_test demonstrates the usage of depcheck.
+// Tests should be put into the special `_test` package to avoid
+// polluting the dependencies of the package they are testing.
+package depcheck_test
+
+import (
+	"testing"
+
+	"knative.dev/pkg/depcheck"
+)
+
+// TestExample doesn't follow the Go Example style because it isn't well
+// suited for libraries needing *testing.T
+func TestExample(t *testing.T) {
+	depcheck.AssertNoDependency(t, map[string][]string{
+		// Our duck types shouldn't depend on fuzzers.
+		"knative.dev/pkg/apis/duck/v1": {
+			"k8s.io/apimachinery/pkg/api/apitesting/fuzzer",
+		},
+		"knative.dev/pkg/apis/duck/v1beta1": {
+			"k8s.io/apimachinery/pkg/api/apitesting/fuzzer",
+		},
+
+		// We intentionally avoid using the Kubernetes "sets" package.
+		"knative.dev/pkg/depcheck": {
+			"k8s.io/apimachinery/pkg/util/sets",
+		},
+
+		// BAD Example used to illustrate path error message.
+		// "knative.dev/pkg/apis/duck": {
+		// 	"k8s.io/api/core/v1",
+		// },
+	})
+}