all: merge master (abc106c) into gopls-release-branch.0.8

Also add a replace directive to gopls/go.mod.

Updates golang/go#51074

Conflicts:

- gopls/go.mod (due to gofumpt update)

Merge List:

+ 2022-02-28 abc106cd gopls/integration/govim: build gopls using go1.18rc1
+ 2022-02-28 c2ddf3dd internal/lsp: add quick fix for unsupported feature
+ 2022-02-28 0e44f7a8 gopls/doc/advanced.md: correct commands for unstable version build
+ 2022-02-25 acdddf67 go/ssa: allows right operand of a shift to be signed.
+ 2022-02-25 9ffa3ad3 internal/lsp: Provide completions for test function definitions
+ 2022-02-24 b7525f43 internal/lsp: hash go version into package key
+ 2022-02-24 5210e0ca gopls: wire in LangVersion and ModulePath for gofumpt formatting
+ 2022-02-24 e6ef7709 go/types/typeutil: don't recurse into constraints when hashing tparams
+ 2022-02-23 258e4730 internal/lsp/source: disable the useany analyzer by default
+ 2022-02-23 b7d29496 internal/lsp: don't store diagnostics for builtin.go
+ 2022-02-23 4f21f7a5 gopls: update gofumpt to v0.3.0
+ 2022-02-22 3e31058c internal/imports: update to permit multiple main modules
+ 2022-02-22 43f084e5 internal/typesinternal: update typesinternal for 1.18
+ 2022-02-18 897bd77c internal/gocommand: remove support for -workfile
+ 2022-02-17 e6a7e133 go/analysis/tools/internal/checker: add support for RunDespiteError

Change-Id: I4ca5a581cb276b904f4a9d73d686aaa7cb0c6093
diff --git a/cmd/godoc/main.go b/cmd/godoc/main.go
index 9d6ac86..352bb4b 100644
--- a/cmd/godoc/main.go
+++ b/cmd/godoc/main.go
@@ -207,21 +207,21 @@
 		fmt.Printf("using module mode; GOMOD=%s\n", goModFile)
 
 		// Detect whether to use vendor mode or not.
-		mainMod, vendorEnabled, err := gocommand.VendorEnabled(context.Background(), gocommand.Invocation{}, &gocommand.Runner{})
+		vendorEnabled, mainModVendor, err := gocommand.VendorEnabled(context.Background(), gocommand.Invocation{}, &gocommand.Runner{})
 		if err != nil {
 			fmt.Fprintf(os.Stderr, "failed to determine if vendoring is enabled: %v", err)
 			os.Exit(1)
 		}
 		if vendorEnabled {
 			// Bind the root directory of the main module.
-			fs.Bind(path.Join("/src", mainMod.Path), gatefs.New(vfs.OS(mainMod.Dir), fsGate), "/", vfs.BindAfter)
+			fs.Bind(path.Join("/src", mainModVendor.Path), gatefs.New(vfs.OS(mainModVendor.Dir), fsGate), "/", vfs.BindAfter)
 
 			// Bind the vendor directory.
 			//
 			// Note that in module mode, vendor directories in locations
 			// other than the main module's root directory are ignored.
 			// See https://golang.org/ref/mod#vendoring.
-			vendorDir := filepath.Join(mainMod.Dir, "vendor")
+			vendorDir := filepath.Join(mainModVendor.Dir, "vendor")
 			fs.Bind("/src", gatefs.New(vfs.OS(vendorDir), fsGate), "/", vfs.BindAfter)
 
 		} else {
diff --git a/go/analysis/internal/checker/checker.go b/go/analysis/internal/checker/checker.go
index 8861393..e405a2a 100644
--- a/go/analysis/internal/checker/checker.go
+++ b/go/analysis/internal/checker/checker.go
@@ -11,6 +11,7 @@
 import (
 	"bytes"
 	"encoding/gob"
+	"errors"
 	"flag"
 	"fmt"
 	"go/format"
@@ -129,8 +130,13 @@
 	allSyntax := needFacts(analyzers)
 	initial, err := load(args, allSyntax)
 	if err != nil {
-		log.Print(err)
-		return 1 // load errors
+		if _, ok := err.(typeParseError); !ok {
+			// Fail when some of the errors are not
+			// related to parsing nor typing.
+			log.Print(err)
+			return 1
+		}
+		// TODO: filter analyzers based on RunDespiteError?
 	}
 
 	// Print the results.
@@ -139,11 +145,17 @@
 	if Fix {
 		applyFixes(roots)
 	}
-
 	return printDiagnostics(roots)
 }
 
-// load loads the initial packages.
+// typeParseError represents a package load error
+// that is related to typing and parsing.
+type typeParseError struct {
+	error
+}
+
+// load loads the initial packages. If all loading issues are related to
+// typing and parsing, the returned error is of type typeParseError.
 func load(patterns []string, allSyntax bool) ([]*packages.Package, error) {
 	mode := packages.LoadSyntax
 	if allSyntax {
@@ -155,18 +167,43 @@
 	}
 	initial, err := packages.Load(&conf, patterns...)
 	if err == nil {
-		if n := packages.PrintErrors(initial); n > 1 {
-			err = fmt.Errorf("%d errors during loading", n)
-		} else if n == 1 {
-			err = fmt.Errorf("error during loading")
-		} else if len(initial) == 0 {
+		if len(initial) == 0 {
 			err = fmt.Errorf("%s matched no packages", strings.Join(patterns, " "))
+		} else {
+			err = loadingError(initial)
 		}
 	}
-
 	return initial, err
 }
 
+// loadingError checks for issues during the loading of initial
+// packages. Returns nil if there are no issues. Returns error
+// of type typeParseError if all errors, including those in
+// dependencies, are related to typing or parsing. Otherwise,
+// a plain error is returned with an appropriate message.
+func loadingError(initial []*packages.Package) error {
+	var err error
+	if n := packages.PrintErrors(initial); n > 1 {
+		err = fmt.Errorf("%d errors during loading", n)
+	} else if n == 1 {
+		err = errors.New("error during loading")
+	} else {
+		// no errors
+		return nil
+	}
+	all := true
+	packages.Visit(initial, nil, func(pkg *packages.Package) {
+		for _, err := range pkg.Errors {
+			typeOrParse := err.Kind == packages.TypeError || err.Kind == packages.ParseError
+			all = all && typeOrParse
+		}
+	})
+	if all {
+		return typeParseError{err}
+	}
+	return err
+}
+
 // TestAnalyzer applies an analysis to a set of packages (and their
 // dependencies if necessary) and returns the results.
 //
diff --git a/go/analysis/internal/checker/checker_test.go b/go/analysis/internal/checker/checker_test.go
index 50c51a1..eee211c 100644
--- a/go/analysis/internal/checker/checker_test.go
+++ b/go/analysis/internal/checker/checker_test.go
@@ -99,3 +99,62 @@
 
 	return nil, nil
 }
+
+func TestRunDespiteErrors(t *testing.T) {
+	testenv.NeedsGoPackages(t)
+
+	files := map[string]string{
+		"rderr/test.go": `package rderr
+
+// Foo deliberately has a type error
+func Foo(s string) int {
+	return s + 1
+}
+`}
+
+	testdata, cleanup, err := analysistest.WriteFiles(files)
+	if err != nil {
+		t.Fatal(err)
+	}
+	path := filepath.Join(testdata, "src/rderr/test.go")
+
+	// A no-op analyzer that should finish regardless of
+	// parse or type errors in the code.
+	noop := &analysis.Analyzer{
+		Name:     "noop",
+		Requires: []*analysis.Analyzer{inspect.Analyzer},
+		Run: func(pass *analysis.Pass) (interface{}, error) {
+			return nil, nil
+		},
+		RunDespiteErrors: true,
+	}
+
+	for _, test := range []struct {
+		name      string
+		pattern   []string
+		analyzers []*analysis.Analyzer
+		code      int
+	}{
+		// parse/type errors
+		{name: "skip-error", pattern: []string{"file=" + path}, analyzers: []*analysis.Analyzer{analyzer}, code: 1},
+		{name: "despite-error", pattern: []string{"file=" + path}, analyzers: []*analysis.Analyzer{noop}, code: 0},
+		// combination of parse/type errors and no errors
+		{name: "despite-error-and-no-error", pattern: []string{"file=" + path, "sort"}, analyzers: []*analysis.Analyzer{analyzer, noop}, code: 1},
+		// non-existing package error
+		{name: "no-package", pattern: []string{"xyz"}, analyzers: []*analysis.Analyzer{analyzer}, code: 1},
+		{name: "no-package-despite-error", pattern: []string{"abc"}, analyzers: []*analysis.Analyzer{noop}, code: 1},
+		{name: "no-multi-package-despite-error", pattern: []string{"xyz", "abc"}, analyzers: []*analysis.Analyzer{noop}, code: 1},
+		// combination of type/parsing and different errors
+		{name: "different-errors", pattern: []string{"file=" + path, "xyz"}, analyzers: []*analysis.Analyzer{analyzer, noop}, code: 1},
+		// non existing dir error
+		{name: "no-match-dir", pattern: []string{"file=non/existing/dir"}, analyzers: []*analysis.Analyzer{analyzer, noop}, code: 1},
+		// no errors
+		{name: "no-errors", pattern: []string{"sort"}, analyzers: []*analysis.Analyzer{analyzer, noop}, code: 0},
+	} {
+		if got := checker.Run(test.pattern, test.analyzers); got != test.code {
+			t.Errorf("got incorrect exit code %d for test %s; want %d", got, test.name, test.code)
+		}
+	}
+
+	defer cleanup()
+}
diff --git a/go/ssa/emit.go b/go/ssa/emit.go
index 7c8cfdc..ff53705 100644
--- a/go/ssa/emit.go
+++ b/go/ssa/emit.go
@@ -74,9 +74,16 @@
 	case token.SHL, token.SHR:
 		x = emitConv(f, x, t)
 		// y may be signed or an 'untyped' constant.
-		// TODO(adonovan): whence signed values?
-		if b, ok := y.Type().Underlying().(*types.Basic); ok && b.Info()&types.IsUnsigned == 0 {
-			y = emitConv(f, y, types.Typ[types.Uint64])
+
+		// There is a runtime panic if y is signed and <0. Instead of inserting a check for y<0
+		// and converting to an unsigned value (like the compiler) leave y as is.
+
+		if b, ok := y.Type().Underlying().(*types.Basic); ok && b.Info()&types.IsUntyped != 0 {
+			// Untyped conversion:
+			// Spec https://go.dev/ref/spec#Operators:
+			// The right operand in a shift expression must have integer type or be an untyped constant
+			// representable by a value of type uint.
+			y = emitConv(f, y, types.Typ[types.Uint])
 		}
 
 	case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
diff --git a/go/ssa/interp/interp_test.go b/go/ssa/interp/interp_test.go
index 28ebf5f..1b43742 100644
--- a/go/ssa/interp/interp_test.go
+++ b/go/ssa/interp/interp_test.go
@@ -109,6 +109,7 @@
 var testdataTests = []string{
 	"boundmeth.go",
 	"complit.go",
+	"convert.go",
 	"coverage.go",
 	"defer.go",
 	"fieldprom.go",
diff --git a/go/ssa/interp/ops.go b/go/ssa/interp/ops.go
index 6af7847..3bc6a4e 100644
--- a/go/ssa/interp/ops.go
+++ b/go/ssa/interp/ops.go
@@ -137,6 +137,26 @@
 	panic(fmt.Sprintf("cannot convert %T to uint64", x))
 }
 
+// asUnsigned returns the value of x, which must be an integer type, as its equivalent unsigned type,
+// and returns true if x is non-negative.
+func asUnsigned(x value) (value, bool) {
+	switch x := x.(type) {
+	case int:
+		return uint(x), x >= 0
+	case int8:
+		return uint8(x), x >= 0
+	case int16:
+		return uint16(x), x >= 0
+	case int32:
+		return uint32(x), x >= 0
+	case int64:
+		return uint64(x), x >= 0
+	case uint, uint8, uint32, uint64, uintptr:
+		return x, true
+	}
+	panic(fmt.Sprintf("cannot convert %T to unsigned", x))
+}
+
 // zero returns a new "zero" value of the specified type.
 func zero(t types.Type) value {
 	switch t := t.(type) {
@@ -576,7 +596,11 @@
 		}
 
 	case token.SHL:
-		y := asUint64(y)
+		u, ok := asUnsigned(y)
+		if !ok {
+			panic("negative shift amount")
+		}
+		y := asUint64(u)
 		switch x.(type) {
 		case int:
 			return x.(int) << y
@@ -603,7 +627,11 @@
 		}
 
 	case token.SHR:
-		y := asUint64(y)
+		u, ok := asUnsigned(y)
+		if !ok {
+			panic("negative shift amount")
+		}
+		y := asUint64(u)
 		switch x.(type) {
 		case int:
 			return x.(int) >> y
diff --git a/go/ssa/interp/testdata/convert.go b/go/ssa/interp/testdata/convert.go
new file mode 100644
index 0000000..0dcf13b
--- /dev/null
+++ b/go/ssa/interp/testdata/convert.go
@@ -0,0 +1,38 @@
+// Copyright 2022 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.
+
+// Test conversion operations.
+
+package main
+
+func left(x int)  { _ = 1 << x }
+func right(x int) { _ = 1 >> x }
+
+func main() {
+	wantPanic(
+		func() {
+			left(-1)
+		},
+		"runtime error: negative shift amount",
+	)
+	wantPanic(
+		func() {
+			right(-1)
+		},
+		"runtime error: negative shift amount",
+	)
+}
+
+func wantPanic(fn func(), s string) {
+	defer func() {
+		err := recover()
+		if err == nil {
+			panic("expected panic")
+		}
+		if got := err.(error).Error(); got != s {
+			panic("expected panic " + s + " got " + got)
+		}
+	}()
+	fn()
+}
diff --git a/go/types/typeutil/map.go b/go/types/typeutil/map.go
index 490ee90..c9f8f25 100644
--- a/go/types/typeutil/map.go
+++ b/go/types/typeutil/map.go
@@ -379,7 +379,7 @@
 func (h Hasher) hashTuple(tuple *types.Tuple) uint32 {
 	// See go/types.identicalTypes for rationale.
 	n := tuple.Len()
-	var hash uint32 = 9137 + 2*uint32(n)
+	hash := 9137 + 2*uint32(n)
 	for i := 0; i < n; i++ {
 		hash += 3 * h.Hash(tuple.At(i).Type())
 	}
@@ -398,7 +398,7 @@
 }
 
 func (h Hasher) hashTermSet(terms []*typeparams.Term) uint32 {
-	var hash uint32 = 9157 + 2*uint32(len(terms))
+	hash := 9157 + 2*uint32(len(terms))
 	for _, term := range terms {
 		// term order is not significant.
 		termHash := h.Hash(term.Type())
@@ -416,14 +416,16 @@
 // If h.sigTParams is set and contains t, then we are in the process of hashing
 // a signature, and the hash value of t must depend only on t's index and
 // constraint: signatures are considered identical modulo type parameter
-// renaming.
+// renaming. To avoid infinite recursion, we only hash the type parameter
+// index, and rely on types.Identical to handle signatures where constraints
+// are not identical.
 //
 // Otherwise the hash of t depends only on t's pointer identity.
 func (h Hasher) hashTypeParam(t *typeparams.TypeParam) uint32 {
 	if h.sigTParams != nil {
 		i := t.Index()
 		if i >= 0 && i < h.sigTParams.Len() && t == h.sigTParams.At(i) {
-			return 9173 + 2*h.Hash(t.Constraint()) + 3*uint32(i)
+			return 9173 + 3*uint32(i)
 		}
 	}
 	return h.hashPtr(t.Obj())
diff --git a/go/types/typeutil/map_test.go b/go/types/typeutil/map_test.go
index 17f87ed..8cd643e 100644
--- a/go/types/typeutil/map_test.go
+++ b/go/types/typeutil/map_test.go
@@ -233,6 +233,17 @@
 
 // ME1Type should have identical type as ME1.
 var ME1Type func(G1[int], G1[int], G2[int])
+
+// Examples from issue #51314
+type Constraint[T any] interface{}
+func Foo[T Constraint[T]]() {}
+func Fn[T1 ~*T2, T2 ~*T1](t1 T1, t2 T2) {}
+
+// Bar and Baz are identical to Foo.
+func Bar[P Constraint[P]]() {}
+func Baz[Q any]() {} // The underlying type of Constraint[P] is any.
+// But Quux is not.
+func Quux[Q interface{ quux() }]() {}
 `
 
 	fset := token.NewFileSet()
@@ -284,6 +295,13 @@
 		ME1     = scope.Lookup("ME1").Type()
 		ME1Type = scope.Lookup("ME1Type").Type()
 		ME2     = scope.Lookup("ME2").Type()
+
+		Constraint = scope.Lookup("Constraint").Type()
+		Foo        = scope.Lookup("Foo").Type()
+		Fn         = scope.Lookup("Fn").Type()
+		Bar        = scope.Lookup("Foo").Type()
+		Baz        = scope.Lookup("Foo").Type()
+		Quux       = scope.Lookup("Quux").Type()
 	)
 
 	tmap := new(typeutil.Map)
@@ -345,6 +363,14 @@
 		{ME1, "ME1", true},
 		{ME1Type, "ME1Type", false},
 		{ME2, "ME2", true},
+
+		// See golang/go#51314: avoid infinite recursion on cyclic type constraints.
+		{Constraint, "Constraint", true},
+		{Foo, "Foo", true},
+		{Fn, "Fn", true},
+		{Bar, "Bar", false},
+		{Baz, "Baz", false},
+		{Quux, "Quux", true},
 	}
 
 	for _, step := range steps {
diff --git a/gopls/doc/advanced.md b/gopls/doc/advanced.md
index dfea673..c4e9eab 100644
--- a/gopls/doc/advanced.md
+++ b/gopls/doc/advanced.md
@@ -16,7 +16,8 @@
 
 ### Unstable versions
 
-To update `gopls` to the latest **unstable** version, use:
+To update `gopls` to the latest **unstable** version, use the following
+commands.
 
 ```sh
 # Create an empty go.mod file, only for tracking requirements.
@@ -24,11 +25,8 @@
 go mod init gopls-unstable
 
 # Use 'go get' to add requirements and to ensure they work together.
-go get golang.org/x/tools/gopls@master golang.org/x/tools@master
+go get -d golang.org/x/tools/gopls@master golang.org/x/tools@master
 
-# For go1.17 or older, the above `go get` command will build and
-# install `gopls`. For go1.18+ or tip, run the following command to install
-# using selected versions in go.mod.
 go install golang.org/x/tools/gopls
 ```
 
diff --git a/gopls/doc/analyzers.md b/gopls/doc/analyzers.md
index 121fa49..07f846d 100644
--- a/gopls/doc/analyzers.md
+++ b/gopls/doc/analyzers.md
@@ -574,7 +574,7 @@
 
 check for constraints that could be simplified to "any"
 
-**Enabled by default.**
+**Disabled by default. Enable it by setting `"analyses": {"useany": true}`.**
 
 ## **fillreturns**
 
diff --git a/gopls/doc/commands.md b/gopls/doc/commands.md
index b70b0af..37a4ca4 100644
--- a/gopls/doc/commands.md
+++ b/gopls/doc/commands.md
@@ -84,6 +84,22 @@
 }
 ```
 
+### **Run go mod edit -go=version**
+Identifier: `gopls.edit_go_directive`
+
+Runs `go mod edit -go=version` for a module.
+
+Args:
+
+```
+{
+	// Any document URI within the relevant module.
+	"URI": string,
+	// The version to pass to `go mod edit -go`.
+	"Version": string,
+}
+```
+
 ### **Toggle gc_details**
 Identifier: `gopls.gc_details`
 
diff --git a/gopls/go.mod b/gopls/go.mod
index 8d28eb1..f31b95a 100644
--- a/gopls/go.mod
+++ b/gopls/go.mod
@@ -8,10 +8,10 @@
 	github.com/jba/templatecheck v0.6.0
 	github.com/sergi/go-diff v1.1.0
 	golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3
-	golang.org/x/sys v0.0.0-20220114195835-da31bd327af9
+	golang.org/x/sys v0.0.0-20220209214540-3681064d5158
 	golang.org/x/tools v0.1.10-0.20220218151557-0d40b49f18b2
 	honnef.co/go/tools v0.2.2
-	mvdan.cc/gofumpt v0.2.1
+	mvdan.cc/gofumpt v0.3.0
 	mvdan.cc/xurls/v2 v2.3.0
 )
 
@@ -22,3 +22,5 @@
 	golang.org/x/text v0.3.7 // indirect
 	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
 )
+
+replace golang.org/x/tools => ../
diff --git a/gopls/go.sum b/gopls/go.sum
index 19c76d9..74e0e84 100644
--- a/gopls/go.sum
+++ b/gopls/go.sum
@@ -5,9 +5,8 @@
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss=
-github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns=
+github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
 github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
 github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
 github.com/google/safehtml v0.0.2 h1:ZOt2VXg4x24bW0m2jtzAOkhoXV0iM8vNKc0paByCZqM=
@@ -62,9 +61,8 @@
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
-golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
+golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -91,7 +89,7 @@
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 honnef.co/go/tools v0.2.2 h1:MNh1AVMyVX23VUHE2O27jm6lNj3vjO5DexS4A1xvnzk=
 honnef.co/go/tools v0.2.2/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY=
-mvdan.cc/gofumpt v0.2.1 h1:7jakRGkQcLAJdT+C8Bwc9d0BANkVPSkHZkzNv07pJAs=
-mvdan.cc/gofumpt v0.2.1/go.mod h1:a/rvZPhsNaedOJBzqRD9omnwVwHZsBdJirXHa9Gh9Ig=
+mvdan.cc/gofumpt v0.3.0 h1:kTojdZo9AcEYbQYhGuLf/zszYthRdhDNDUi2JKTxas4=
+mvdan.cc/gofumpt v0.3.0/go.mod h1:0+VyGZWleeIj5oostkOex+nDBA0eyavuDnDusAJ8ylo=
 mvdan.cc/xurls/v2 v2.3.0 h1:59Olnbt67UKpxF1EwVBopJvkSUBmgtb468E4GVWIZ1I=
 mvdan.cc/xurls/v2 v2.3.0/go.mod h1:AjuTy7gEiUArFMjgBBDU4SMxlfUYsRokpJQgNWOt3e4=
diff --git a/gopls/integration/govim/run_local.sh b/gopls/integration/govim/run_local.sh
index b7aba5e..b5c284f 100755
--- a/gopls/integration/govim/run_local.sh
+++ b/gopls/integration/govim/run_local.sh
@@ -13,7 +13,7 @@
 Args:
   --sudo     run docker with sudo
   --short    run `go test` with `-short`
-  --version  run on the specific tagged Go version (or latest) rather
+  --version  run on the specific tagged govim version (or latest) rather
              than the default branch
 
 Run govim tests against HEAD using local docker.
@@ -71,7 +71,7 @@
 ${SUDO_IF_NEEDED}docker run --rm -t \
   -v "${tools_dir}:/src/tools" \
   -w "/src/tools/gopls" \
-  golang:latest \
+  golang:rc \
   go build -o $(basename ${temp_gopls})
 
 # Build the test harness. Here we are careful to pass in a very limited build
diff --git a/gopls/internal/hooks/hooks.go b/gopls/internal/hooks/hooks.go
index 390967d..487fb60 100644
--- a/gopls/internal/hooks/hooks.go
+++ b/gopls/internal/hooks/hooks.go
@@ -22,8 +22,11 @@
 		options.ComputeEdits = ComputeEdits
 	}
 	options.URLRegexp = relaxedFullWord
-	options.GofumptFormat = func(ctx context.Context, src []byte) ([]byte, error) {
-		return format.Source(src, format.Options{})
+	options.GofumptFormat = func(ctx context.Context, langVersion, modulePath string, src []byte) ([]byte, error) {
+		return format.Source(src, format.Options{
+			LangVersion: langVersion,
+			ModulePath:  modulePath,
+		})
 	}
 	updateAnalyzers(options)
 }
diff --git a/gopls/internal/regtest/completion/completion_test.go b/gopls/internal/regtest/completion/completion_test.go
index 988d5c3..6abcd60 100644
--- a/gopls/internal/regtest/completion/completion_test.go
+++ b/gopls/internal/regtest/completion/completion_test.go
@@ -256,7 +256,7 @@
 
 	for i, v := range got {
 		if v != want[i] {
-			return fmt.Sprintf("completion results are not the same: got %v, want %v", got, want)
+			return fmt.Sprintf("%d completion result not the same: got %q, want %q", i, v, want[i])
 		}
 	}
 
@@ -546,3 +546,56 @@
 		}
 	})
 }
+
+func TestDefinition(t *testing.T) {
+	stuff := `
+-- go.mod --
+module mod.com
+
+go 1.18
+-- a_test.go --
+package foo
+func T()
+func TestG()
+func TestM()
+func TestMi()
+func Ben()
+func Fuz()
+func Testx()
+func TestMe(t *testing.T)
+func BenchmarkFoo()
+`
+	// All those parentheses are needed for the completion code to see
+	// later lines as being definitions
+	tests := []struct {
+		pat  string
+		want []string
+	}{
+		{"T", []string{"TestXxx(t *testing.T)", "TestMain(m *testing.M)"}},
+		{"TestM", []string{"TestMain(m *testing.M)", "TestM(t *testing.T)"}},
+		{"TestMi", []string{"TestMi(t *testing.T)"}},
+		{"TestG", []string{"TestG(t *testing.T)"}},
+		{"B", []string{"BenchmarkXxx(b *testing.B)"}},
+		{"BenchmarkFoo", []string{"BenchmarkFoo(b *testing.B)"}},
+		{"F", []string{"FuzzXxx(f *testing.F)"}},
+		{"Testx", nil},
+		{"TestMe", []string{"TestMe"}},
+	}
+	fname := "a_test.go"
+	Run(t, stuff, func(t *testing.T, env *Env) {
+		env.OpenFile(fname)
+		env.Await(env.DoneWithOpen())
+		for _, tst := range tests {
+			pos := env.RegexpSearch(fname, tst.pat)
+			pos.Column += len(tst.pat)
+			completions := env.Completion(fname, pos)
+			result := compareCompletionResults(tst.want, completions.Items)
+			if result != "" {
+				t.Errorf("%s failed: %s:%q", tst.pat, result, tst.want)
+				for i, it := range completions.Items {
+					t.Errorf("%d got %q %q", i, it.Label, it.Detail)
+				}
+			}
+		}
+	})
+}
diff --git a/gopls/internal/regtest/misc/formatting_test.go b/gopls/internal/regtest/misc/formatting_test.go
index 67e7939..75d8f62 100644
--- a/gopls/internal/regtest/misc/formatting_test.go
+++ b/gopls/internal/regtest/misc/formatting_test.go
@@ -301,3 +301,69 @@
 		}
 	})
 }
+
+func TestGofumptFormatting(t *testing.T) {
+
+	// Exercise some gofumpt formatting rules:
+	//  - No empty lines following an assignment operator
+	//  - Octal integer literals should use the 0o prefix on modules using Go
+	//    1.13 and later. Requires LangVersion to be correctly resolved.
+	//  - std imports must be in a separate group at the top. Requires ModulePath
+	//    to be correctly resolved.
+	const input = `
+-- go.mod --
+module foo
+
+go 1.17
+-- foo.go --
+package foo
+
+import (
+	"foo/bar"
+	"fmt"
+)
+
+const perm = 0755
+
+func foo() {
+	foo :=
+		"bar"
+	fmt.Println(foo, bar.Bar)
+}
+-- foo.go.formatted --
+package foo
+
+import (
+	"fmt"
+
+	"foo/bar"
+)
+
+const perm = 0o755
+
+func foo() {
+	foo := "bar"
+	fmt.Println(foo, bar.Bar)
+}
+-- bar/bar.go --
+package bar
+
+const Bar = 42
+`
+
+	WithOptions(
+		EditorConfig{
+			Settings: map[string]interface{}{
+				"gofumpt": true,
+			},
+		},
+	).Run(t, input, func(t *testing.T, env *Env) {
+		env.OpenFile("foo.go")
+		env.FormatBuffer("foo.go")
+		got := env.Editor.BufferText("foo.go")
+		want := env.ReadWorkspaceFile("foo.go.formatted")
+		if got != want {
+			t.Errorf("unexpected formatting result:\n%s", tests.Diff(t, want, got))
+		}
+	})
+}
diff --git a/internal/gocommand/vendor.go b/internal/gocommand/vendor.go
index 5e75bd6..2d3d408 100644
--- a/internal/gocommand/vendor.go
+++ b/internal/gocommand/vendor.go
@@ -38,10 +38,10 @@
 // with the supplied context.Context and Invocation. The Invocation can contain pre-defined fields,
 // of which only Verb and Args are modified to run the appropriate Go command.
 // Inspired by setDefaultBuildMod in modload/init.go
-func VendorEnabled(ctx context.Context, inv Invocation, r *Runner) (*ModuleJSON, bool, error) {
+func VendorEnabled(ctx context.Context, inv Invocation, r *Runner) (bool, *ModuleJSON, error) {
 	mainMod, go114, err := getMainModuleAnd114(ctx, inv, r)
 	if err != nil {
-		return nil, false, err
+		return false, nil, err
 	}
 
 	// We check the GOFLAGS to see if there is anything overridden or not.
@@ -49,7 +49,7 @@
 	inv.Args = []string{"GOFLAGS"}
 	stdout, err := r.Run(ctx, inv)
 	if err != nil {
-		return nil, false, err
+		return false, nil, err
 	}
 	goflags := string(bytes.TrimSpace(stdout.Bytes()))
 	matches := modFlagRegexp.FindStringSubmatch(goflags)
@@ -57,25 +57,27 @@
 	if len(matches) != 0 {
 		modFlag = matches[1]
 	}
-	if modFlag != "" {
-		// Don't override an explicit '-mod=' argument.
-		return mainMod, modFlag == "vendor", nil
+	// Don't override an explicit '-mod=' argument.
+	if modFlag == "vendor" {
+		return true, mainMod, nil
+	} else if modFlag != "" {
+		return false, nil, nil
 	}
 	if mainMod == nil || !go114 {
-		return mainMod, false, nil
+		return false, nil, nil
 	}
 	// Check 1.14's automatic vendor mode.
 	if fi, err := os.Stat(filepath.Join(mainMod.Dir, "vendor")); err == nil && fi.IsDir() {
 		if mainMod.GoVersion != "" && semver.Compare("v"+mainMod.GoVersion, "v1.14") >= 0 {
 			// The Go version is at least 1.14, and a vendor directory exists.
 			// Set -mod=vendor by default.
-			return mainMod, true, nil
+			return true, mainMod, nil
 		}
 	}
-	return mainMod, false, nil
+	return false, nil, nil
 }
 
-// getMainModuleAnd114 gets the main module's information and whether the
+// getMainModuleAnd114 gets one of the main modules' information and whether the
 // go command in use is 1.14+. This is the information needed to figure out
 // if vendoring should be enabled.
 func getMainModuleAnd114(ctx context.Context, inv Invocation, r *Runner) (*ModuleJSON, bool, error) {
diff --git a/internal/imports/mod.go b/internal/imports/mod.go
index dff6d55..2bcf41f 100644
--- a/internal/imports/mod.go
+++ b/internal/imports/mod.go
@@ -34,7 +34,8 @@
 	scannedRoots   map[gopathwalk.Root]bool
 
 	initialized   bool
-	main          *gocommand.ModuleJSON
+	mains         []*gocommand.ModuleJSON
+	mainByDir     map[string]*gocommand.ModuleJSON
 	modsByModPath []*gocommand.ModuleJSON // All modules, ordered by # of path components in module Path...
 	modsByDir     []*gocommand.ModuleJSON // ...or Dir.
 
@@ -69,21 +70,21 @@
 		Logf:       r.env.Logf,
 		WorkingDir: r.env.WorkingDir,
 	}
-	mainMod, vendorEnabled, err := gocommand.VendorEnabled(context.TODO(), inv, r.env.GocmdRunner)
+	vendorEnabled, mainModVendor, err := gocommand.VendorEnabled(context.TODO(), inv, r.env.GocmdRunner)
 	if err != nil {
 		return err
 	}
 
-	if mainMod != nil && vendorEnabled {
+	if mainModVendor != nil && vendorEnabled {
 		// Vendor mode is on, so all the non-Main modules are irrelevant,
 		// and we need to search /vendor for everything.
-		r.main = mainMod
+		r.mains = []*gocommand.ModuleJSON{mainModVendor}
 		r.dummyVendorMod = &gocommand.ModuleJSON{
 			Path: "",
-			Dir:  filepath.Join(mainMod.Dir, "vendor"),
+			Dir:  filepath.Join(mainModVendor.Dir, "vendor"),
 		}
-		r.modsByModPath = []*gocommand.ModuleJSON{mainMod, r.dummyVendorMod}
-		r.modsByDir = []*gocommand.ModuleJSON{mainMod, r.dummyVendorMod}
+		r.modsByModPath = []*gocommand.ModuleJSON{mainModVendor, r.dummyVendorMod}
+		r.modsByDir = []*gocommand.ModuleJSON{mainModVendor, r.dummyVendorMod}
 	} else {
 		// Vendor mode is off, so run go list -m ... to find everything.
 		err := r.initAllMods()
@@ -122,8 +123,10 @@
 	r.roots = []gopathwalk.Root{
 		{filepath.Join(goenv["GOROOT"], "/src"), gopathwalk.RootGOROOT},
 	}
-	if r.main != nil {
-		r.roots = append(r.roots, gopathwalk.Root{r.main.Dir, gopathwalk.RootCurrentModule})
+	r.mainByDir = make(map[string]*gocommand.ModuleJSON)
+	for _, main := range r.mains {
+		r.roots = append(r.roots, gopathwalk.Root{main.Dir, gopathwalk.RootCurrentModule})
+		r.mainByDir[main.Dir] = main
 	}
 	if vendorEnabled {
 		r.roots = append(r.roots, gopathwalk.Root{r.dummyVendorMod.Dir, gopathwalk.RootOther})
@@ -189,7 +192,7 @@
 		r.modsByModPath = append(r.modsByModPath, mod)
 		r.modsByDir = append(r.modsByDir, mod)
 		if mod.Main {
-			r.main = mod
+			r.mains = append(r.mains, mod)
 		}
 	}
 	return nil
@@ -609,7 +612,7 @@
 	}
 	switch root.Type {
 	case gopathwalk.RootCurrentModule:
-		importPath = path.Join(r.main.Path, filepath.ToSlash(subdir))
+		importPath = path.Join(r.mainByDir[root.Path].Path, filepath.ToSlash(subdir))
 	case gopathwalk.RootModuleCache:
 		matches := modCacheRegexp.FindStringSubmatch(subdir)
 		if len(matches) == 0 {
diff --git a/internal/imports/mod_test.go b/internal/imports/mod_test.go
index 51bc967..5f71805 100644
--- a/internal/imports/mod_test.go
+++ b/internal/imports/mod_test.go
@@ -552,6 +552,336 @@
 	mt.assertModuleFoundInDir("example.com/vv", "v", `main/v12$`)
 }
 
+// Tests that go.work files are respected.
+func TestModWorkspace(t *testing.T) {
+	testenv.NeedsGo1Point(t, 18)
+
+	mt := setup(t, `
+-- go.work --
+go 1.18
+
+use (
+	./a
+	./b
+)
+-- a/go.mod --
+module example.com/a
+
+go 1.18
+-- a/a.go --
+package a
+-- b/go.mod --
+module example.com/b
+
+go 1.18
+-- b/b.go --
+package b
+`, "")
+	defer mt.cleanup()
+
+	mt.assertModuleFoundInDir("example.com/a", "a", `main/a$`)
+	mt.assertModuleFoundInDir("example.com/b", "b", `main/b$`)
+	mt.assertScanFinds("example.com/a", "a")
+	mt.assertScanFinds("example.com/b", "b")
+}
+
+// Tests replaces in workspaces. Uses the directory layout in the cmd/go
+// work_replace test. It tests both that replaces in go.work files are
+// respected and that a wildcard replace in go.work overrides a versioned replace
+// in go.mod.
+func TestModWorkspaceReplace(t *testing.T) {
+	testenv.NeedsGo1Point(t, 18)
+
+	mt := setup(t, `
+-- go.work --
+use m
+
+replace example.com/dep => ./dep
+replace example.com/other => ./other2
+
+-- m/go.mod --
+module example.com/m
+
+require example.com/dep v1.0.0
+require example.com/other v1.0.0
+
+replace example.com/other v1.0.0 => ./other
+-- m/m.go --
+package m
+
+import "example.com/dep"
+import "example.com/other"
+
+func F() {
+	dep.G()
+	other.H()
+}
+-- dep/go.mod --
+module example.com/dep
+-- dep/dep.go --
+package dep
+
+func G() {
+}
+-- other/go.mod --
+module example.com/other
+-- other/dep.go --
+package other
+
+func G() {
+}
+-- other2/go.mod --
+module example.com/other
+-- other2/dep.go --
+package other2
+
+func G() {
+}
+`, "")
+	defer mt.cleanup()
+
+	mt.assertScanFinds("example.com/m", "m")
+	mt.assertScanFinds("example.com/dep", "dep")
+	mt.assertModuleFoundInDir("example.com/other", "other2", "main/other2$")
+	mt.assertScanFinds("example.com/other", "other2")
+}
+
+// Tests a case where conflicting replaces are overridden by a replace
+// in the go.work file.
+func TestModWorkspaceReplaceOverride(t *testing.T) {
+	testenv.NeedsGo1Point(t, 18)
+
+	mt := setup(t, `-- go.work --
+use m
+use n
+replace example.com/dep => ./dep3
+-- m/go.mod --
+module example.com/m
+
+require example.com/dep v1.0.0
+replace example.com/dep => ./dep1
+-- m/m.go --
+package m
+
+import "example.com/dep"
+
+func F() {
+	dep.G()
+}
+-- n/go.mod --
+module example.com/n
+
+require example.com/dep v1.0.0
+replace example.com/dep => ./dep2
+-- n/n.go --
+package n
+
+import "example.com/dep"
+
+func F() {
+	dep.G()
+}
+-- dep1/go.mod --
+module example.com/dep
+-- dep1/dep.go --
+package dep
+
+func G() {
+}
+-- dep2/go.mod --
+module example.com/dep
+-- dep2/dep.go --
+package dep
+
+func G() {
+}
+-- dep3/go.mod --
+module example.com/dep
+-- dep3/dep.go --
+package dep
+
+func G() {
+}
+`, "")
+
+	mt.assertScanFinds("example.com/m", "m")
+	mt.assertScanFinds("example.com/n", "n")
+	mt.assertScanFinds("example.com/dep", "dep")
+	mt.assertModuleFoundInDir("example.com/dep", "dep", "main/dep3$")
+}
+
+// Tests that the correct versions of modules are found in
+// workspaces with module pruning. This is based on the
+// cmd/go mod_prune_all script test.
+func TestModWorkspacePrune(t *testing.T) {
+	testenv.NeedsGo1Point(t, 18)
+
+	mt := setup(t, `
+-- go.work --
+go 1.18
+
+use (
+	./a
+	./p
+)
+
+replace example.com/b v1.0.0 => ./b
+replace example.com/q v1.0.0 => ./q1_0_0
+replace example.com/q v1.0.5 => ./q1_0_5
+replace example.com/q v1.1.0 => ./q1_1_0
+replace example.com/r v1.0.0 => ./r
+replace example.com/w v1.0.0 => ./w
+replace example.com/x v1.0.0 => ./x
+replace example.com/y v1.0.0 => ./y
+replace example.com/z v1.0.0 => ./z1_0_0
+replace example.com/z v1.1.0 => ./z1_1_0
+
+-- a/go.mod --
+module example.com/a
+
+go 1.18
+
+require example.com/b v1.0.0
+require example.com/z v1.0.0
+-- a/foo.go --
+package main
+
+import "example.com/b"
+
+func main() {
+	b.B()
+}
+-- b/go.mod --
+module example.com/b
+
+go 1.18
+
+require example.com/q v1.1.0
+-- b/b.go --
+package b
+
+func B() {
+}
+-- p/go.mod --
+module example.com/p
+
+go 1.18
+
+require example.com/q v1.0.0
+
+replace example.com/q v1.0.0 => ../q1_0_0
+replace example.com/q v1.1.0 => ../q1_1_0
+-- p/main.go --
+package main
+
+import "example.com/q"
+
+func main() {
+	q.PrintVersion()
+}
+-- q1_0_0/go.mod --
+module example.com/q
+
+go 1.18
+-- q1_0_0/q.go --
+package q
+
+import "fmt"
+
+func PrintVersion() {
+	fmt.Println("version 1.0.0")
+}
+-- q1_0_5/go.mod --
+module example.com/q
+
+go 1.18
+
+require example.com/r v1.0.0
+-- q1_0_5/q.go --
+package q
+
+import _ "example.com/r"
+-- q1_1_0/go.mod --
+module example.com/q
+
+require example.com/w v1.0.0
+require example.com/z v1.1.0
+
+go 1.18
+-- q1_1_0/q.go --
+package q
+
+import _ "example.com/w"
+import _ "example.com/z"
+
+import "fmt"
+
+func PrintVersion() {
+	fmt.Println("version 1.1.0")
+}
+-- r/go.mod --
+module example.com/r
+
+go 1.18
+
+require example.com/r v1.0.0
+-- r/r.go --
+package r
+-- w/go.mod --
+module example.com/w
+
+go 1.18
+
+require example.com/x v1.0.0
+-- w/w.go --
+package w
+-- w/w_test.go --
+package w
+
+import _ "example.com/x"
+-- x/go.mod --
+module example.com/x
+
+go 1.18
+-- x/x.go --
+package x
+-- x/x_test.go --
+package x
+import _ "example.com/y"
+-- y/go.mod --
+module example.com/y
+
+go 1.18
+-- y/y.go --
+package y
+-- z1_0_0/go.mod --
+module example.com/z
+
+go 1.18
+
+require example.com/q v1.0.5
+-- z1_0_0/z.go --
+package z
+
+import _ "example.com/q"
+-- z1_1_0/go.mod --
+module example.com/z
+
+go 1.18
+-- z1_1_0/z.go --
+package z
+`, "")
+
+	mt.assertScanFinds("example.com/w", "w")
+	mt.assertScanFinds("example.com/q", "q")
+	mt.assertScanFinds("example.com/x", "x")
+	mt.assertScanFinds("example.com/z", "z")
+	mt.assertModuleFoundInDir("example.com/w", "w", "main/w$")
+	mt.assertModuleFoundInDir("example.com/q", "q", "main/q1_1_0$")
+	mt.assertModuleFoundInDir("example.com/x", "x", "main/x$")
+	mt.assertModuleFoundInDir("example.com/z", "z", "main/z1_1_0$")
+}
+
 // Tests that we handle GO111MODULE=on with no go.mod file. See #30855.
 func TestNoMainModule(t *testing.T) {
 	testenv.NeedsGo1Point(t, 12)
diff --git a/internal/lsp/cache/check.go b/internal/lsp/cache/check.go
index 6163816..f166863 100644
--- a/internal/lsp/cache/check.go
+++ b/internal/lsp/cache/check.go
@@ -194,7 +194,7 @@
 		depKeys = append(depKeys, depHandle.key)
 	}
 	experimentalKey := s.View().Options().ExperimentalPackageCacheKey
-	ph.key = checkPackageKey(ph.m.ID, compiledGoFiles, m.Config, depKeys, mode, experimentalKey)
+	ph.key = checkPackageKey(ph.m.ID, compiledGoFiles, m, depKeys, mode, experimentalKey)
 	return ph, deps, nil
 }
 
@@ -214,15 +214,18 @@
 	return source.ParseExported
 }
 
-func checkPackageKey(id PackageID, pghs []*parseGoHandle, cfg *packages.Config, deps []packageHandleKey, mode source.ParseMode, experimentalKey bool) packageHandleKey {
+func checkPackageKey(id PackageID, pghs []*parseGoHandle, m *KnownMetadata, deps []packageHandleKey, mode source.ParseMode, experimentalKey bool) packageHandleKey {
 	b := bytes.NewBuffer(nil)
 	b.WriteString(string(id))
+	if m.Module != nil {
+		b.WriteString(m.Module.GoVersion) // go version affects type check errors.
+	}
 	if !experimentalKey {
 		// cfg was used to produce the other hashed inputs (package ID, parsed Go
 		// files, and deps). It should not otherwise affect the inputs to the type
 		// checker, so this experiment omits it. This should increase cache hits on
 		// the daemon as cfg contains the environment and working directory.
-		b.WriteString(hashConfig(cfg))
+		b.WriteString(hashConfig(m.Config))
 	}
 	b.WriteByte(byte(mode))
 	for _, dep := range deps {
diff --git a/internal/lsp/cache/errors.go b/internal/lsp/cache/errors.go
index 6790938..155b7a4 100644
--- a/internal/lsp/cache/errors.go
+++ b/internal/lsp/cache/errors.go
@@ -101,6 +101,7 @@
 }
 
 var importErrorRe = regexp.MustCompile(`could not import ([^\s]+)`)
+var unsupportedFeatureRe = regexp.MustCompile(`.*require go(\d+\.\d+) or later`)
 
 func typeErrorDiagnostics(snapshot *snapshot, pkg *pkg, e extendedError) ([]*source.Diagnostic, error) {
 	code, spn, err := typeErrorData(snapshot.FileSet(), pkg, e.primary)
@@ -145,6 +146,14 @@
 			return nil, err
 		}
 	}
+	if code == typesinternal.UnsupportedFeature {
+		if match := unsupportedFeatureRe.FindStringSubmatch(e.primary.Msg); match != nil {
+			diag.SuggestedFixes, err = editGoDirectiveQuickFix(snapshot, spn.URI(), match[1])
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
 	return []*source.Diagnostic{diag}, nil
 }
 
@@ -165,6 +174,22 @@
 	return []source.SuggestedFix{source.SuggestedFixFromCommand(cmd, protocol.QuickFix)}, nil
 }
 
+func editGoDirectiveQuickFix(snapshot *snapshot, uri span.URI, version string) ([]source.SuggestedFix, error) {
+	// Go mod edit only supports module mode.
+	if snapshot.workspaceMode()&moduleMode == 0 {
+		return nil, nil
+	}
+	title := fmt.Sprintf("go mod edit -go=%s", version)
+	cmd, err := command.NewEditGoDirectiveCommand(title, command.EditGoDirectiveArgs{
+		URI:     protocol.URIFromSpanURI(uri),
+		Version: version,
+	})
+	if err != nil {
+		return nil, err
+	}
+	return []source.SuggestedFix{source.SuggestedFixFromCommand(cmd, protocol.QuickFix)}, nil
+}
+
 func analysisDiagnosticDiagnostics(snapshot *snapshot, pkg *pkg, a *analysis.Analyzer, e *analysis.Diagnostic) ([]*source.Diagnostic, error) {
 	var srcAnalyzer *source.Analyzer
 	// Find the analyzer that generated this diagnostic.
diff --git a/internal/lsp/cache/metadata.go b/internal/lsp/cache/metadata.go
index bef7bf8..618578d 100644
--- a/internal/lsp/cache/metadata.go
+++ b/internal/lsp/cache/metadata.go
@@ -56,6 +56,11 @@
 	return string(m.PkgPath)
 }
 
+// ModuleInfo implements the source.Metadata interface.
+func (m *Metadata) ModuleInfo() *packages.Module {
+	return m.Module
+}
+
 // KnownMetadata is a wrapper around metadata that tracks its validity.
 type KnownMetadata struct {
 	*Metadata
diff --git a/internal/lsp/cache/snapshot.go b/internal/lsp/cache/snapshot.go
index b9cd36c..e786c02 100644
--- a/internal/lsp/cache/snapshot.go
+++ b/internal/lsp/cache/snapshot.go
@@ -1025,7 +1025,11 @@
 	var mds []source.Metadata
 	for _, id := range knownIDs {
 		md := s.getMetadata(id)
-		mds = append(mds, md)
+		// TODO(rfindley): knownIDs and metadata should be in sync, but existing
+		// code is defensive of nil metadata.
+		if md != nil {
+			mds = append(mds, md)
+		}
 	}
 	return mds, nil
 }
diff --git a/internal/lsp/command.go b/internal/lsp/command.go
index d8f9d2c..e9d61d5 100644
--- a/internal/lsp/command.go
+++ b/internal/lsp/command.go
@@ -261,6 +261,20 @@
 	})
 }
 
+func (c *commandHandler) EditGoDirective(ctx context.Context, args command.EditGoDirectiveArgs) error {
+	return c.run(ctx, commandConfig{
+		requireSave: true, // if go.mod isn't saved it could cause a problem
+		forURI:      args.URI,
+	}, func(ctx context.Context, deps commandDeps) error {
+		_, err := deps.snapshot.RunGoCommandDirect(ctx, source.Normal, &gocommand.Invocation{
+			Verb:       "mod",
+			Args:       []string{"edit", "-go", args.Version},
+			WorkingDir: filepath.Dir(args.URI.SpanURI().Filename()),
+		})
+		return err
+	})
+}
+
 func (c *commandHandler) RemoveDependency(ctx context.Context, args command.RemoveDependencyArgs) error {
 	return c.run(ctx, commandConfig{
 		progress: "Removing dependency",
diff --git a/internal/lsp/command/command_gen.go b/internal/lsp/command/command_gen.go
index c814bfe..5569693 100644
--- a/internal/lsp/command/command_gen.go
+++ b/internal/lsp/command/command_gen.go
@@ -23,6 +23,7 @@
 	AddImport         Command = "add_import"
 	ApplyFix          Command = "apply_fix"
 	CheckUpgrades     Command = "check_upgrades"
+	EditGoDirective   Command = "edit_go_directive"
 	GCDetails         Command = "gc_details"
 	Generate          Command = "generate"
 	GenerateGoplsMod  Command = "generate_gopls_mod"
@@ -46,6 +47,7 @@
 	AddImport,
 	ApplyFix,
 	CheckUpgrades,
+	EditGoDirective,
 	GCDetails,
 	Generate,
 	GenerateGoplsMod,
@@ -90,6 +92,12 @@
 			return nil, err
 		}
 		return nil, s.CheckUpgrades(ctx, a0)
+	case "gopls.edit_go_directive":
+		var a0 EditGoDirectiveArgs
+		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
+			return nil, err
+		}
+		return nil, s.EditGoDirective(ctx, a0)
 	case "gopls.gc_details":
 		var a0 protocol.DocumentURI
 		if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
@@ -240,6 +248,18 @@
 	}, nil
 }
 
+func NewEditGoDirectiveCommand(title string, a0 EditGoDirectiveArgs) (protocol.Command, error) {
+	args, err := MarshalArgs(a0)
+	if err != nil {
+		return protocol.Command{}, err
+	}
+	return protocol.Command{
+		Title:     title,
+		Command:   "gopls.edit_go_directive",
+		Arguments: args,
+	}, nil
+}
+
 func NewGCDetailsCommand(title string, a0 protocol.DocumentURI) (protocol.Command, error) {
 	args, err := MarshalArgs(a0)
 	if err != nil {
diff --git a/internal/lsp/command/interface.go b/internal/lsp/command/interface.go
index d5f520d..6058c72 100644
--- a/internal/lsp/command/interface.go
+++ b/internal/lsp/command/interface.go
@@ -68,6 +68,11 @@
 	// Runs `go mod vendor` for a module.
 	Vendor(context.Context, URIArg) error
 
+	// EditGoDirective: Run go mod edit -go=version
+	//
+	// Runs `go mod edit -go=version` for a module.
+	EditGoDirective(context.Context, EditGoDirectiveArgs) error
+
 	// UpdateGoSum: Update go.sum
 	//
 	// Updates the go.sum file for a module.
@@ -204,6 +209,13 @@
 	OnlyDiagnostic bool
 }
 
+type EditGoDirectiveArgs struct {
+	// Any document URI within the relevant module.
+	URI protocol.DocumentURI
+	// The version to pass to `go mod edit -go`.
+	Version string
+}
+
 type GoGetPackageArgs struct {
 	// Any document URI within the relevant module.
 	URI protocol.DocumentURI
diff --git a/internal/lsp/diagnostics.go b/internal/lsp/diagnostics.go
index f4b0064..e352e4b 100644
--- a/internal/lsp/diagnostics.go
+++ b/internal/lsp/diagnostics.go
@@ -288,7 +288,11 @@
 		return
 	}
 	for _, cgf := range pkg.CompiledGoFiles() {
-		s.storeDiagnostics(snapshot, cgf.URI, typeCheckSource, pkgDiagnostics[cgf.URI])
+		// builtin.go exists only for documentation purposes, and is not valid Go code.
+		// Don't report distracting errors
+		if !snapshot.IsBuiltin(ctx, cgf.URI) {
+			s.storeDiagnostics(snapshot, cgf.URI, typeCheckSource, pkgDiagnostics[cgf.URI])
+		}
 	}
 	if includeAnalysis && !pkg.HasListOrParseErrors() {
 		reports, err := source.Analyze(ctx, snapshot, pkg, false)
diff --git a/internal/lsp/source/api_json.go b/internal/lsp/source/api_json.go
index 4742fb1..f37cc80 100755
--- a/internal/lsp/source/api_json.go
+++ b/internal/lsp/source/api_json.go
@@ -406,7 +406,7 @@
 						{
 							Name:    "\"useany\"",
 							Doc:     "check for constraints that could be simplified to \"any\"",
-							Default: "true",
+							Default: "false",
 						},
 						{
 							Name:    "\"fillreturns\"",
@@ -604,6 +604,12 @@
 			ArgDoc:  "{\n\t// The go.mod file URI.\n\t\"URI\": string,\n\t// The modules to check.\n\t\"Modules\": []string,\n}",
 		},
 		{
+			Command: "gopls.edit_go_directive",
+			Title:   "Run go mod edit -go=version",
+			Doc:     "Runs `go mod edit -go=version` for a module.",
+			ArgDoc:  "{\n\t// Any document URI within the relevant module.\n\t\"URI\": string,\n\t// The version to pass to `go mod edit -go`.\n\t\"Version\": string,\n}",
+		},
+		{
 			Command: "gopls.gc_details",
 			Title:   "Toggle gc_details",
 			Doc:     "Toggle the calculation of gc annotations.",
@@ -922,9 +928,8 @@
 			Doc:  "checks for unused writes\n\nThe analyzer reports instances of writes to struct fields and\narrays that are never read. Specifically, when a struct object\nor an array is copied, its elements are copied implicitly by\nthe compiler, and any element write to this copy does nothing\nwith the original object.\n\nFor example:\n\n\ttype T struct { x int }\n\tfunc f(input []T) {\n\t\tfor i, v := range input {  // v is a copy\n\t\t\tv.x = i  // unused write to field x\n\t\t}\n\t}\n\nAnother example is about non-pointer receiver:\n\n\ttype T struct { x int }\n\tfunc (t T) f() {  // t is a copy\n\t\tt.x = i  // unused write to field x\n\t}\n",
 		},
 		{
-			Name:    "useany",
-			Doc:     "check for constraints that could be simplified to \"any\"",
-			Default: true,
+			Name: "useany",
+			Doc:  "check for constraints that could be simplified to \"any\"",
 		},
 		{
 			Name:    "fillreturns",
diff --git a/internal/lsp/source/completion/completion.go b/internal/lsp/source/completion/completion.go
index 94389c7..30d277f 100644
--- a/internal/lsp/source/completion/completion.go
+++ b/internal/lsp/source/completion/completion.go
@@ -485,6 +485,13 @@
 					qual := types.RelativeTo(pkg.GetTypes())
 					objStr = types.ObjectString(obj, qual)
 				}
+				ans, sel := definition(path, obj, snapshot.FileSet(), pgf.Mapper, fh)
+				if ans != nil {
+					sort.Slice(ans, func(i, j int) bool {
+						return ans[i].Score > ans[j].Score
+					})
+					return ans, sel, nil
+				}
 				return nil, nil, ErrIsDefinition{objStr: objStr}
 			}
 		}
diff --git a/internal/lsp/source/completion/definition.go b/internal/lsp/source/completion/definition.go
new file mode 100644
index 0000000..17b251c
--- /dev/null
+++ b/internal/lsp/source/completion/definition.go
@@ -0,0 +1,127 @@
+// Copyright 2022 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 completion
+
+import (
+	"go/ast"
+	"go/token"
+	"go/types"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+
+	"golang.org/x/tools/internal/lsp/protocol"
+	"golang.org/x/tools/internal/lsp/snippet"
+	"golang.org/x/tools/internal/lsp/source"
+)
+
+// some definitions can be completed
+// So far, TestFoo(t *testing.T), TestMain(m *testing.M)
+// BenchmarkFoo(b *testing.B), FuzzFoo(f *testing.F)
+
+// path[0] is known to be *ast.Ident
+func definition(path []ast.Node, obj types.Object, fset *token.FileSet, mapper *protocol.ColumnMapper, fh source.FileHandle) ([]CompletionItem, *Selection) {
+	if _, ok := obj.(*types.Func); !ok {
+		return nil, nil // not a function at all
+	}
+	if !strings.HasSuffix(fh.URI().Filename(), "_test.go") {
+		return nil, nil
+	}
+
+	name := path[0].(*ast.Ident).Name
+	if len(name) == 0 {
+		// can't happen
+		return nil, nil
+	}
+	pos := path[0].Pos()
+	sel := &Selection{
+		content:     "",
+		cursor:      pos,
+		MappedRange: source.NewMappedRange(fset, mapper, pos, pos),
+	}
+	var ans []CompletionItem
+
+	// Always suggest TestMain, if possible
+	if strings.HasPrefix("TestMain", name) {
+		ans = []CompletionItem{defItem("TestMain(m *testing.M)", obj)}
+	}
+
+	// If a snippet is possible, suggest it
+	if strings.HasPrefix("Test", name) {
+		ans = append(ans, defSnippet("Test", "Xxx", "(t *testing.T)", obj))
+		return ans, sel
+	} else if strings.HasPrefix("Benchmark", name) {
+		ans = append(ans, defSnippet("Benchmark", "Xxx", "(b *testing.B)", obj))
+		return ans, sel
+	} else if strings.HasPrefix("Fuzz", name) {
+		ans = append(ans, defSnippet("Fuzz", "Xxx", "(f *testing.F)", obj))
+		return ans, sel
+	}
+
+	// Fill in the argument for what the user has already typed
+	if got := defMatches(name, "Test", path, "(t *testing.T)"); got != "" {
+		ans = append(ans, defItem(got, obj))
+	} else if got := defMatches(name, "Benchmark", path, "(b *testing.B)"); got != "" {
+		ans = append(ans, defItem(got, obj))
+	} else if got := defMatches(name, "Fuzz", path, "(f *testing.F)"); got != "" {
+		ans = append(ans, defItem(got, obj))
+	}
+	return ans, sel
+}
+
+func defMatches(name, pat string, path []ast.Node, arg string) string {
+	idx := strings.Index(name, pat)
+	if idx < 0 {
+		return ""
+	}
+	c, _ := utf8.DecodeRuneInString(name[len(pat):])
+	if unicode.IsLower(c) {
+		return ""
+	}
+	fd, ok := path[1].(*ast.FuncDecl)
+	if !ok {
+		// we don't know what's going on
+		return ""
+	}
+	fp := fd.Type.Params
+	if fp != nil && len(fp.List) > 0 {
+		// signature already there, minimal suggestion
+		return name
+	}
+	// suggesting signature too
+	return name + arg
+}
+
+func defSnippet(prefix, placeholder, suffix string, obj types.Object) CompletionItem {
+	var sn snippet.Builder
+	sn.WriteText(prefix)
+	if placeholder != "" {
+		sn.WritePlaceholder(func(b *snippet.Builder) { b.WriteText(placeholder) })
+	}
+	sn.WriteText(suffix + " {\n")
+	sn.WriteFinalTabstop()
+	sn.WriteText("\n}")
+	return CompletionItem{
+		Label:         prefix + placeholder + suffix,
+		Detail:        "tab, type the rest of the name, then tab",
+		Kind:          protocol.FunctionCompletion,
+		Depth:         0,
+		Score:         10,
+		snippet:       &sn,
+		Documentation: prefix + " test function",
+		obj:           obj,
+	}
+}
+func defItem(val string, obj types.Object) CompletionItem {
+	return CompletionItem{
+		Label:         val,
+		InsertText:    val,
+		Kind:          protocol.FunctionCompletion,
+		Depth:         0,
+		Score:         9, // prefer the snippets when available
+		Documentation: "complete the parameter",
+		obj:           obj,
+	}
+}
diff --git a/internal/lsp/source/format.go b/internal/lsp/source/format.go
index 4f02e4f..79da0b3 100644
--- a/internal/lsp/source/format.go
+++ b/internal/lsp/source/format.go
@@ -63,8 +63,24 @@
 
 	// Apply additional formatting, if any is supported. Currently, the only
 	// supported additional formatter is gofumpt.
-	if format := snapshot.View().Options().Hooks.GofumptFormat; snapshot.View().Options().Gofumpt && format != nil {
-		b, err := format(ctx, buf.Bytes())
+	if format := snapshot.View().Options().GofumptFormat; snapshot.View().Options().Gofumpt && format != nil {
+		// gofumpt can customize formatting based on language version and module
+		// path, if available.
+		//
+		// Try to derive this information, but fall-back on the default behavior.
+		//
+		// TODO: under which circumstances can we fail to find module information?
+		// Can this, for example, result in inconsistent formatting across saves,
+		// due to pending calls to packages.Load?
+		var langVersion, modulePath string
+		mds, err := snapshot.MetadataForFile(ctx, fh.URI())
+		if err == nil && len(mds) > 0 {
+			if mi := mds[0].ModuleInfo(); mi != nil {
+				langVersion = mi.GoVersion
+				modulePath = mi.Path
+			}
+		}
+		b, err := format(ctx, langVersion, modulePath, buf.Bytes())
 		if err != nil {
 			return nil, err
 		}
diff --git a/internal/lsp/source/options.go b/internal/lsp/source/options.go
index 139ae70..b1df290 100644
--- a/internal/lsp/source/options.go
+++ b/internal/lsp/source/options.go
@@ -462,11 +462,16 @@
 // Hooks contains configuration that is provided to the Gopls command by the
 // main package.
 type Hooks struct {
-	LicensesText         string
-	GoDiff               bool
-	ComputeEdits         diff.ComputeEdits
-	URLRegexp            *regexp.Regexp
-	GofumptFormat        func(ctx context.Context, src []byte) ([]byte, error)
+	LicensesText string
+	GoDiff       bool
+	ComputeEdits diff.ComputeEdits
+	URLRegexp    *regexp.Regexp
+
+	// GofumptFormat allows the gopls module to wire-in a call to
+	// gofumpt/format.Source. langVersion and modulePath are used for some
+	// Gofumpt formatting rules -- see the Gofumpt documentation for details.
+	GofumptFormat func(ctx context.Context, langVersion, modulePath string, src []byte) ([]byte, error)
+
 	DefaultAnalyzers     map[string]*Analyzer
 	TypeErrorAnalyzers   map[string]*Analyzer
 	ConvenienceAnalyzers map[string]*Analyzer
@@ -694,8 +699,8 @@
 		ClientOptions:   o.ClientOptions,
 		InternalOptions: o.InternalOptions,
 		Hooks: Hooks{
-			GoDiff:        o.Hooks.GoDiff,
-			ComputeEdits:  o.Hooks.ComputeEdits,
+			GoDiff:        o.GoDiff,
+			ComputeEdits:  o.ComputeEdits,
 			GofumptFormat: o.GofumptFormat,
 			URLRegexp:     o.URLRegexp,
 		},
@@ -1265,7 +1270,7 @@
 		testinggoroutine.Analyzer.Name: {Analyzer: testinggoroutine.Analyzer, Enabled: true},
 		unusedparams.Analyzer.Name:     {Analyzer: unusedparams.Analyzer, Enabled: false},
 		unusedwrite.Analyzer.Name:      {Analyzer: unusedwrite.Analyzer, Enabled: false},
-		useany.Analyzer.Name:           {Analyzer: useany.Analyzer, Enabled: true},
+		useany.Analyzer.Name:           {Analyzer: useany.Analyzer, Enabled: false},
 		infertypeargs.Analyzer.Name:    {Analyzer: infertypeargs.Analyzer, Enabled: true},
 
 		// gofmt -s suite:
diff --git a/internal/lsp/source/view.go b/internal/lsp/source/view.go
index dba45f7..9e9b035 100644
--- a/internal/lsp/source/view.go
+++ b/internal/lsp/source/view.go
@@ -18,6 +18,7 @@
 	"golang.org/x/mod/modfile"
 	"golang.org/x/mod/module"
 	"golang.org/x/tools/go/analysis"
+	"golang.org/x/tools/go/packages"
 	"golang.org/x/tools/internal/gocommand"
 	"golang.org/x/tools/internal/imports"
 	"golang.org/x/tools/internal/lsp/progress"
@@ -319,6 +320,9 @@
 
 	// PackagePath is the package path.
 	PackagePath() string
+
+	// ModuleInfo returns the go/packages module information for the given package.
+	ModuleInfo() *packages.Module
 }
 
 // Session represents a single connection from a client.
diff --git a/internal/typesinternal/errorcode.go b/internal/typesinternal/errorcode.go
index fa2834e..d38ee3c 100644
--- a/internal/typesinternal/errorcode.go
+++ b/internal/typesinternal/errorcode.go
@@ -1365,4 +1365,162 @@
 	//  	return i
 	//  }
 	InvalidGo
+
+	// All codes below were added in Go 1.17.
+
+	/* decl */
+
+	// BadDecl occurs when a declaration has invalid syntax.
+	BadDecl
+
+	// RepeatedDecl occurs when an identifier occurs more than once on the left
+	// hand side of a short variable declaration.
+	//
+	// Example:
+	//  func _() {
+	//  	x, y, y := 1, 2, 3
+	//  }
+	RepeatedDecl
+
+	/* unsafe */
+
+	// InvalidUnsafeAdd occurs when unsafe.Add is called with a
+	// length argument that is not of integer type.
+	//
+	// Example:
+	//  import "unsafe"
+	//
+	//  var p unsafe.Pointer
+	//  var _ = unsafe.Add(p, float64(1))
+	InvalidUnsafeAdd
+
+	// InvalidUnsafeSlice occurs when unsafe.Slice is called with a
+	// pointer argument that is not of pointer type or a length argument
+	// that is not of integer type, negative, or out of bounds.
+	//
+	// Example:
+	//  import "unsafe"
+	//
+	//  var x int
+	//  var _ = unsafe.Slice(x, 1)
+	//
+	// Example:
+	//  import "unsafe"
+	//
+	//  var x int
+	//  var _ = unsafe.Slice(&x, float64(1))
+	//
+	// Example:
+	//  import "unsafe"
+	//
+	//  var x int
+	//  var _ = unsafe.Slice(&x, -1)
+	//
+	// Example:
+	//  import "unsafe"
+	//
+	//  var x int
+	//  var _ = unsafe.Slice(&x, uint64(1) << 63)
+	InvalidUnsafeSlice
+
+	// All codes below were added in Go 1.18.
+
+	/* features */
+
+	// UnsupportedFeature occurs when a language feature is used that is not
+	// supported at this Go version.
+	UnsupportedFeature
+
+	/* type params */
+
+	// NotAGenericType occurs when a non-generic type is used where a generic
+	// type is expected: in type or function instantiation.
+	//
+	// Example:
+	//  type T int
+	//
+	//  var _ T[int]
+	NotAGenericType
+
+	// WrongTypeArgCount occurs when a type or function is instantiated with an
+	// incorrent number of type arguments, including when a generic type or
+	// function is used without instantiation.
+	//
+	// Errors inolving failed type inference are assigned other error codes.
+	//
+	// Example:
+	//  type T[p any] int
+	//
+	//  var _ T[int, string]
+	//
+	// Example:
+	//  func f[T any]() {}
+	//
+	//  var x = f
+	WrongTypeArgCount
+
+	// CannotInferTypeArgs occurs when type or function type argument inference
+	// fails to infer all type arguments.
+	//
+	// Example:
+	//  func f[T any]() {}
+	//
+	//  func _() {
+	//  	f()
+	//  }
+	//
+	// Example:
+	//   type N[P, Q any] struct{}
+	//
+	//   var _ N[int]
+	CannotInferTypeArgs
+
+	// InvalidTypeArg occurs when a type argument does not satisfy its
+	// corresponding type parameter constraints.
+	//
+	// Example:
+	//  type T[P ~int] struct{}
+	//
+	//  var _ T[string]
+	InvalidTypeArg // arguments? InferenceFailed
+
+	// InvalidInstanceCycle occurs when an invalid cycle is detected
+	// within the instantiation graph.
+	//
+	// Example:
+	//  func f[T any]() { f[*T]() }
+	InvalidInstanceCycle
+
+	// InvalidUnion occurs when an embedded union or approximation element is
+	// not valid.
+	//
+	// Example:
+	//  type _ interface {
+	//   	~int | interface{ m() }
+	//  }
+	InvalidUnion
+
+	// MisplacedConstraintIface occurs when a constraint-type interface is used
+	// outside of constraint position.
+	//
+	// Example:
+	//   type I interface { ~int }
+	//
+	//   var _ I
+	MisplacedConstraintIface
+
+	// InvalidMethodTypeParams occurs when methods have type parameters.
+	//
+	// It cannot be encountered with an AST parsed using go/parser.
+	InvalidMethodTypeParams
+
+	// MisplacedTypeParam occurs when a type parameter is used in a place where
+	// it is not permitted.
+	//
+	// Example:
+	//  type T[P any] P
+	//
+	// Example:
+	//  type T[P any] struct{ *P }
+	MisplacedTypeParam
 )
diff --git a/internal/typesinternal/errorcode_string.go b/internal/typesinternal/errorcode_string.go
index 3e5842a..de90e95 100644
--- a/internal/typesinternal/errorcode_string.go
+++ b/internal/typesinternal/errorcode_string.go
@@ -138,11 +138,25 @@
 	_ = x[UnusedResults-128]
 	_ = x[InvalidDefer-129]
 	_ = x[InvalidGo-130]
+	_ = x[BadDecl-131]
+	_ = x[RepeatedDecl-132]
+	_ = x[InvalidUnsafeAdd-133]
+	_ = x[InvalidUnsafeSlice-134]
+	_ = x[UnsupportedFeature-135]
+	_ = x[NotAGenericType-136]
+	_ = x[WrongTypeArgCount-137]
+	_ = x[CannotInferTypeArgs-138]
+	_ = x[InvalidTypeArg-139]
+	_ = x[InvalidInstanceCycle-140]
+	_ = x[InvalidUnion-141]
+	_ = x[MisplacedConstraintIface-142]
+	_ = x[InvalidMethodTypeParams-143]
+	_ = x[MisplacedTypeParam-144]
 }
 
-const _ErrorCode_name = "TestBlankPkgNameMismatchedPkgNameInvalidPkgUseBadImportPathBrokenImportImportCRenamedUnusedImportInvalidInitCycleDuplicateDeclInvalidDeclCycleInvalidTypeCycleInvalidConstInitInvalidConstValInvalidConstTypeUntypedNilWrongAssignCountUnassignableOperandNoNewVarMultiValAssignOpInvalidIfaceAssignInvalidChanAssignIncompatibleAssignUnaddressableFieldAssignNotATypeInvalidArrayLenBlankIfaceMethodIncomparableMapKeyInvalidIfaceEmbedInvalidPtrEmbedBadRecvInvalidRecvDuplicateFieldAndMethodDuplicateMethodInvalidBlankInvalidIotaMissingInitBodyInvalidInitSigInvalidInitDeclInvalidMainDeclTooManyValuesNotAnExprTruncatedFloatNumericOverflowUndefinedOpMismatchedTypesDivByZeroNonNumericIncDecUnaddressableOperandInvalidIndirectionNonIndexableOperandInvalidIndexSwappedSliceIndicesNonSliceableOperandInvalidSliceExprInvalidShiftCountInvalidShiftOperandInvalidReceiveInvalidSendDuplicateLitKeyMissingLitKeyInvalidLitIndexOversizeArrayLitMixedStructLitInvalidStructLitMissingLitFieldDuplicateLitFieldUnexportedLitFieldInvalidLitFieldUntypedLitInvalidLitAmbiguousSelectorUndeclaredImportedNameUnexportedNameUndeclaredNameMissingFieldOrMethodBadDotDotDotSyntaxNonVariadicDotDotDotMisplacedDotDotDotInvalidDotDotDotOperandInvalidDotDotDotUncalledBuiltinInvalidAppendInvalidCapInvalidCloseInvalidCopyInvalidComplexInvalidDeleteInvalidImagInvalidLenSwappedMakeArgsInvalidMakeInvalidRealInvalidAssertImpossibleAssertInvalidConversionInvalidUntypedConversionBadOffsetofSyntaxInvalidOffsetofUnusedExprUnusedVarMissingReturnWrongResultCountOutOfScopeResultInvalidCondInvalidPostDeclInvalidChanRangeInvalidIterVarInvalidRangeExprMisplacedBreakMisplacedContinueMisplacedFallthroughDuplicateCaseDuplicateDefaultBadTypeKeywordInvalidTypeSwitchInvalidExprSwitchInvalidSelectCaseUndeclaredLabelDuplicateLabelMisplacedLabelUnusedLabelJumpOverDeclJumpIntoBlockInvalidMethodExprWrongArgCountInvalidCallUnusedResultsInvalidDeferInvalidGo"
+const _ErrorCode_name = "TestBlankPkgNameMismatchedPkgNameInvalidPkgUseBadImportPathBrokenImportImportCRenamedUnusedImportInvalidInitCycleDuplicateDeclInvalidDeclCycleInvalidTypeCycleInvalidConstInitInvalidConstValInvalidConstTypeUntypedNilWrongAssignCountUnassignableOperandNoNewVarMultiValAssignOpInvalidIfaceAssignInvalidChanAssignIncompatibleAssignUnaddressableFieldAssignNotATypeInvalidArrayLenBlankIfaceMethodIncomparableMapKeyInvalidIfaceEmbedInvalidPtrEmbedBadRecvInvalidRecvDuplicateFieldAndMethodDuplicateMethodInvalidBlankInvalidIotaMissingInitBodyInvalidInitSigInvalidInitDeclInvalidMainDeclTooManyValuesNotAnExprTruncatedFloatNumericOverflowUndefinedOpMismatchedTypesDivByZeroNonNumericIncDecUnaddressableOperandInvalidIndirectionNonIndexableOperandInvalidIndexSwappedSliceIndicesNonSliceableOperandInvalidSliceExprInvalidShiftCountInvalidShiftOperandInvalidReceiveInvalidSendDuplicateLitKeyMissingLitKeyInvalidLitIndexOversizeArrayLitMixedStructLitInvalidStructLitMissingLitFieldDuplicateLitFieldUnexportedLitFieldInvalidLitFieldUntypedLitInvalidLitAmbiguousSelectorUndeclaredImportedNameUnexportedNameUndeclaredNameMissingFieldOrMethodBadDotDotDotSyntaxNonVariadicDotDotDotMisplacedDotDotDotInvalidDotDotDotOperandInvalidDotDotDotUncalledBuiltinInvalidAppendInvalidCapInvalidCloseInvalidCopyInvalidComplexInvalidDeleteInvalidImagInvalidLenSwappedMakeArgsInvalidMakeInvalidRealInvalidAssertImpossibleAssertInvalidConversionInvalidUntypedConversionBadOffsetofSyntaxInvalidOffsetofUnusedExprUnusedVarMissingReturnWrongResultCountOutOfScopeResultInvalidCondInvalidPostDeclInvalidChanRangeInvalidIterVarInvalidRangeExprMisplacedBreakMisplacedContinueMisplacedFallthroughDuplicateCaseDuplicateDefaultBadTypeKeywordInvalidTypeSwitchInvalidExprSwitchInvalidSelectCaseUndeclaredLabelDuplicateLabelMisplacedLabelUnusedLabelJumpOverDeclJumpIntoBlockInvalidMethodExprWrongArgCountInvalidCallUnusedResultsInvalidDeferInvalidGoBadDeclRepeatedDeclInvalidUnsafeAddInvalidUnsafeSliceUnsupportedFeatureNotAGenericTypeWrongTypeArgCountCannotInferTypeArgsInvalidTypeArgInvalidInstanceCycleInvalidUnionMisplacedConstraintIfaceInvalidMethodTypeParamsMisplacedTypeParam"
 
-var _ErrorCode_index = [...]uint16{0, 4, 16, 33, 46, 59, 71, 85, 97, 113, 126, 142, 158, 174, 189, 205, 215, 231, 250, 258, 274, 292, 309, 327, 351, 359, 374, 390, 408, 425, 440, 447, 458, 481, 496, 508, 519, 534, 548, 563, 578, 591, 600, 614, 629, 640, 655, 664, 680, 700, 718, 737, 749, 768, 787, 803, 820, 839, 853, 864, 879, 892, 907, 923, 937, 953, 968, 985, 1003, 1018, 1028, 1038, 1055, 1077, 1091, 1105, 1125, 1143, 1163, 1181, 1204, 1220, 1235, 1248, 1258, 1270, 1281, 1295, 1308, 1319, 1329, 1344, 1355, 1366, 1379, 1395, 1412, 1436, 1453, 1468, 1478, 1487, 1500, 1516, 1532, 1543, 1558, 1574, 1588, 1604, 1618, 1635, 1655, 1668, 1684, 1698, 1715, 1732, 1749, 1764, 1778, 1792, 1803, 1815, 1828, 1845, 1858, 1869, 1882, 1894, 1903}
+var _ErrorCode_index = [...]uint16{0, 4, 16, 33, 46, 59, 71, 85, 97, 113, 126, 142, 158, 174, 189, 205, 215, 231, 250, 258, 274, 292, 309, 327, 351, 359, 374, 390, 408, 425, 440, 447, 458, 481, 496, 508, 519, 534, 548, 563, 578, 591, 600, 614, 629, 640, 655, 664, 680, 700, 718, 737, 749, 768, 787, 803, 820, 839, 853, 864, 879, 892, 907, 923, 937, 953, 968, 985, 1003, 1018, 1028, 1038, 1055, 1077, 1091, 1105, 1125, 1143, 1163, 1181, 1204, 1220, 1235, 1248, 1258, 1270, 1281, 1295, 1308, 1319, 1329, 1344, 1355, 1366, 1379, 1395, 1412, 1436, 1453, 1468, 1478, 1487, 1500, 1516, 1532, 1543, 1558, 1574, 1588, 1604, 1618, 1635, 1655, 1668, 1684, 1698, 1715, 1732, 1749, 1764, 1778, 1792, 1803, 1815, 1828, 1845, 1858, 1869, 1882, 1894, 1903, 1910, 1922, 1938, 1956, 1974, 1989, 2006, 2025, 2039, 2059, 2071, 2095, 2118, 2136}
 
 func (i ErrorCode) String() string {
 	i -= 1