libgo: update to final Go 1.18 release

Change-Id: Iabbc0f21c727d09b712e70cad7ebe20c39b0119b
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/393377
Trust: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
diff --git a/libgo/MERGE b/libgo/MERGE
index 11da9a2..85536ad 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-cb5a598d7f2ebd276686403d141a97c026d33458
+4aa1efed4853ea067d665a952eee77c52faac774
 
 The first line of this file holds the git revision number of the
 last merge done from the master library sources.
diff --git a/libgo/VERSION b/libgo/VERSION
index 6a12199..39560f0 100644
--- a/libgo/VERSION
+++ b/libgo/VERSION
@@ -1 +1 @@
-go1.18rc1
+go1.18
diff --git a/libgo/go/cmd/go/alldocs.go b/libgo/go/cmd/go/alldocs.go
index 63e7900..420529b 100644
--- a/libgo/go/cmd/go/alldocs.go
+++ b/libgo/go/cmd/go/alldocs.go
@@ -1356,7 +1356,7 @@
 //
 // Workspace maintenance
 //
-// Go workspace provides access to operations on workspaces.
+// Work provides access to operations on workspaces.
 //
 // Note that support for workspaces is built into many other commands, not
 // just 'go work'.
@@ -1364,6 +1364,12 @@
 // See 'go help modules' for information about Go's module system of which
 // workspaces are a part.
 //
+// See https://go.dev/ref/mod#workspaces for an in-depth reference on
+// workspaces.
+//
+// See https://go.dev/doc/tutorial/workspaces for an introductory
+// tutorial on workspaces.
+//
 // A workspace is specified by a go.work file that specifies a set of
 // module directories with the "use" directive. These modules are used as
 // root modules by the go command for builds and related operations.  A
@@ -1485,9 +1491,8 @@
 // 		Version string
 // 	}
 //
-// See the workspaces design proposal at
-// https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for
-// more information.
+// See the workspaces reference at https://go.dev/ref/mod#workspaces
+// for more information.
 //
 //
 // Initialize workspace file
@@ -1507,6 +1512,9 @@
 // Each argument path is added to a use directive in the go.work file. The
 // current go version will also be listed in the go.work file.
 //
+// See the workspaces reference at https://go.dev/ref/mod#workspaces
+// for more information.
+//
 //
 // Sync workspace build list to modules
 //
@@ -1530,12 +1538,15 @@
 // build list's version of each module is always the same or higher than
 // that in each workspace module.
 //
+// See the workspaces reference at https://go.dev/ref/mod#workspaces
+// for more information.
+//
 //
 // Add modules to workspace file
 //
 // Usage:
 //
-// 	go work use [-r] [moddirs]
+// 	go work use [-r] moddirs
 //
 // Use provides a command-line interface for adding
 // directories, optionally recursively, to a go.work file.
@@ -1549,6 +1560,9 @@
 // were specified as arguments: namely, use directives will be added for
 // directories that exist, and removed for directories that do not exist.
 //
+// See the workspaces reference at https://go.dev/ref/mod#workspaces
+// for more information.
+//
 //
 // Compile and run Go program
 //
diff --git a/libgo/go/cmd/go/internal/modfetch/coderepo.go b/libgo/go/cmd/go/internal/modfetch/coderepo.go
index 2206c7c..dfaf16d 100644
--- a/libgo/go/cmd/go/internal/modfetch/coderepo.go
+++ b/libgo/go/cmd/go/internal/modfetch/coderepo.go
@@ -305,17 +305,46 @@
 	//
 	// (If the version is +incompatible, then the go.mod file must not exist:
 	// +incompatible is not an ongoing opt-out from semantic import versioning.)
-	var canUseIncompatible func() bool
-	canUseIncompatible = func() bool {
-		var ok bool
-		if r.codeDir == "" && r.pathMajor == "" {
+	incompatibleOk := map[string]bool{}
+	canUseIncompatible := func(v string) bool {
+		if r.codeDir != "" || r.pathMajor != "" {
+			// A non-empty codeDir indicates a module within a subdirectory,
+			// which necessarily has a go.mod file indicating the module boundary.
+			// A non-empty pathMajor indicates a module path with a major-version
+			// suffix, which must match.
+			return false
+		}
+
+		ok, seen := incompatibleOk[""]
+		if !seen {
 			_, errGoMod := r.code.ReadFile(info.Name, "go.mod", codehost.MaxGoMod)
-			if errGoMod != nil {
-				ok = true
+			ok = (errGoMod != nil)
+			incompatibleOk[""] = ok
+		}
+		if !ok {
+			// A go.mod file exists at the repo root.
+			return false
+		}
+
+		// Per https://go.dev/issue/51324, previous versions of the 'go' command
+		// didn't always check for go.mod files in subdirectories, so if the user
+		// requests a +incompatible version explicitly, we should continue to allow
+		// it. Otherwise, if vN/go.mod exists, expect that release tags for that
+		// major version are intended for the vN module.
+		if v != "" && !strings.HasSuffix(statVers, "+incompatible") {
+			major := semver.Major(v)
+			ok, seen = incompatibleOk[major]
+			if !seen {
+				_, errGoModSub := r.code.ReadFile(info.Name, path.Join(major, "go.mod"), codehost.MaxGoMod)
+				ok = (errGoModSub != nil)
+				incompatibleOk[major] = ok
+			}
+			if !ok {
+				return false
 			}
 		}
-		canUseIncompatible = func() bool { return ok }
-		return ok
+
+		return true
 	}
 
 	// checkCanonical verifies that the canonical version v is compatible with the
@@ -367,7 +396,7 @@
 		base := strings.TrimSuffix(v, "+incompatible")
 		var errIncompatible error
 		if !module.MatchPathMajor(base, r.pathMajor) {
-			if canUseIncompatible() {
+			if canUseIncompatible(base) {
 				v = base + "+incompatible"
 			} else {
 				if r.pathMajor != "" {
@@ -495,7 +524,7 @@
 		// Save the highest non-retracted canonical tag for the revision.
 		// If we don't find a better match, we'll use it as the canonical version.
 		if tagIsCanonical && semver.Compare(highestCanonical, v) < 0 && !isRetracted(v) {
-			if module.MatchPathMajor(v, r.pathMajor) || canUseIncompatible() {
+			if module.MatchPathMajor(v, r.pathMajor) || canUseIncompatible(v) {
 				highestCanonical = v
 			}
 		}
@@ -513,12 +542,12 @@
 	// retracted versions.
 	allowedMajor := func(major string) func(v string) bool {
 		return func(v string) bool {
-			return (major == "" || semver.Major(v) == major) && !isRetracted(v)
+			return ((major == "" && canUseIncompatible(v)) || semver.Major(v) == major) && !isRetracted(v)
 		}
 	}
 	if pseudoBase == "" {
 		var tag string
-		if r.pseudoMajor != "" || canUseIncompatible() {
+		if r.pseudoMajor != "" || canUseIncompatible("") {
 			tag, _ = r.code.RecentTag(info.Name, tagPrefix, allowedMajor(r.pseudoMajor))
 		} else {
 			// Allow either v1 or v0, but not incompatible higher versions.
diff --git a/libgo/go/cmd/go/internal/modfetch/coderepo_test.go b/libgo/go/cmd/go/internal/modfetch/coderepo_test.go
index d98ea87..bb9268a 100644
--- a/libgo/go/cmd/go/internal/modfetch/coderepo_test.go
+++ b/libgo/go/cmd/go/internal/modfetch/coderepo_test.go
@@ -458,6 +458,54 @@
 		rev:  "v3.0.0-devel",
 		err:  `resolves to version v0.1.1-0.20220203155313-d59622f6e4d7 (v3.0.0-devel is not a tag)`,
 	},
+
+	// If v2/go.mod exists, then we should prefer to match the "v2"
+	// pseudo-versions to the nested module, and resolve the module in the parent
+	// directory to only compatible versions.
+	//
+	// However (https://go.dev/issue/51324), previous versions of the 'go' command
+	// didn't always do so, so if the user explicitly requests a +incompatible
+	// version (as would be present in an existing go.mod file), we should
+	// continue to allow it.
+	{
+		vcs:     "git",
+		path:    "vcs-test.golang.org/git/v2sub.git",
+		rev:     "80beb17a1603",
+		version: "v0.0.0-20220222205507-80beb17a1603",
+		name:    "80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5",
+		short:   "80beb17a1603",
+		time:    time.Date(2022, 2, 22, 20, 55, 7, 0, time.UTC),
+	},
+	{
+		vcs:  "git",
+		path: "vcs-test.golang.org/git/v2sub.git",
+		rev:  "v2.0.0",
+		err:  `module contains a go.mod file, so module path must match major version ("vcs-test.golang.org/git/v2sub.git/v2")`,
+	},
+	{
+		vcs:  "git",
+		path: "vcs-test.golang.org/git/v2sub.git",
+		rev:  "v2.0.1-0.20220222205507-80beb17a1603",
+		err:  `module contains a go.mod file, so module path must match major version ("vcs-test.golang.org/git/v2sub.git/v2")`,
+	},
+	{
+		vcs:     "git",
+		path:    "vcs-test.golang.org/git/v2sub.git",
+		rev:     "v2.0.0+incompatible",
+		version: "v2.0.0+incompatible",
+		name:    "5fcd3eaeeb391d399f562fd45a50dac9fc34ae8b",
+		short:   "5fcd3eaeeb39",
+		time:    time.Date(2022, 2, 22, 20, 53, 33, 0, time.UTC),
+	},
+	{
+		vcs:     "git",
+		path:    "vcs-test.golang.org/git/v2sub.git",
+		rev:     "v2.0.1-0.20220222205507-80beb17a1603+incompatible",
+		version: "v2.0.1-0.20220222205507-80beb17a1603+incompatible",
+		name:    "80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5",
+		short:   "80beb17a1603",
+		time:    time.Date(2022, 2, 22, 20, 55, 7, 0, time.UTC),
+	},
 }
 
 func TestCodeRepo(t *testing.T) {
diff --git a/libgo/go/cmd/go/internal/modload/init.go b/libgo/go/cmd/go/internal/modload/init.go
index a070666..f960edd 100644
--- a/libgo/go/cmd/go/internal/modload/init.go
+++ b/libgo/go/cmd/go/internal/modload/init.go
@@ -288,6 +288,11 @@
 // operate in workspace mode. It should not be called by other commands,
 // for example 'go mod tidy', that don't operate in workspace mode.
 func InitWorkfile() {
+	if RootMode == NoRoot {
+		workFilePath = ""
+		return
+	}
+
 	switch gowork := cfg.Getenv("GOWORK"); gowork {
 	case "off":
 		workFilePath = ""
diff --git a/libgo/go/cmd/go/internal/modload/modfile.go b/libgo/go/cmd/go/internal/modload/modfile.go
index 627cf1d..75c278a 100644
--- a/libgo/go/cmd/go/internal/modload/modfile.go
+++ b/libgo/go/cmd/go/internal/modload/modfile.go
@@ -802,7 +802,7 @@
 // an absolute path or a relative path starting with a '.' or '..'
 // path component.
 func ToDirectoryPath(path string) string {
-	if modfile.IsDirectoryPath(path) {
+	if path == "." || modfile.IsDirectoryPath(path) {
 		return path
 	}
 	// The path is not a relative path or an absolute path, so make it relative
diff --git a/libgo/go/cmd/go/internal/run/run.go b/libgo/go/cmd/go/internal/run/run.go
index 00a3e4b..312b49e 100644
--- a/libgo/go/cmd/go/internal/run/run.go
+++ b/libgo/go/cmd/go/internal/run/run.go
@@ -73,8 +73,6 @@
 }
 
 func runRun(ctx context.Context, cmd *base.Command, args []string) {
-	modload.InitWorkfile()
-
 	if shouldUseOutsideModuleMode(args) {
 		// Set global module flags for 'go run cmd@version'.
 		// This must be done before modload.Init, but we need to call work.BuildInit
@@ -84,7 +82,10 @@
 		modload.RootMode = modload.NoRoot
 		modload.AllowMissingModuleImports()
 		modload.Init()
+	} else {
+		modload.InitWorkfile()
 	}
+
 	work.BuildInit()
 	var b work.Builder
 	b.Init()
diff --git a/libgo/go/cmd/go/internal/vcs/vcs.go b/libgo/go/cmd/go/internal/vcs/vcs.go
index fd521b2..2acabf7 100644
--- a/libgo/go/cmd/go/internal/vcs/vcs.go
+++ b/libgo/go/cmd/go/internal/vcs/vcs.go
@@ -312,7 +312,7 @@
 	// uncommitted files and skip tagging revision / committime.
 	var rev string
 	var commitTime time.Time
-	out, err = vcsGit.runOutputVerboseOnly(rootDir, "show -s --no-show-signature --format=%H:%ct")
+	out, err = vcsGit.runOutputVerboseOnly(rootDir, "-c log.showsignature=false show -s --format=%H:%ct")
 	if err != nil && !uncommitted {
 		return Status{}, err
 	} else if err == nil {
diff --git a/libgo/go/cmd/go/internal/workcmd/edit.go b/libgo/go/cmd/go/internal/workcmd/edit.go
index 05f4f3d..1478c19 100644
--- a/libgo/go/cmd/go/internal/workcmd/edit.go
+++ b/libgo/go/cmd/go/internal/workcmd/edit.go
@@ -84,9 +84,8 @@
 		Version string
 	}
 
-See the workspaces design proposal at
-https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for
-more information.
+See the workspaces reference at https://go.dev/ref/mod#workspaces
+for more information.
 `,
 }
 
diff --git a/libgo/go/cmd/go/internal/workcmd/init.go b/libgo/go/cmd/go/internal/workcmd/init.go
index 63bee6e..c2513ba 100644
--- a/libgo/go/cmd/go/internal/workcmd/init.go
+++ b/libgo/go/cmd/go/internal/workcmd/init.go
@@ -27,6 +27,8 @@
 Each argument path is added to a use directive in the go.work file. The
 current go version will also be listed in the go.work file.
 
+See the workspaces reference at https://go.dev/ref/mod#workspaces
+for more information.
 `,
 	Run: runInit,
 }
diff --git a/libgo/go/cmd/go/internal/workcmd/sync.go b/libgo/go/cmd/go/internal/workcmd/sync.go
index b0f61c5..7712eb6 100644
--- a/libgo/go/cmd/go/internal/workcmd/sync.go
+++ b/libgo/go/cmd/go/internal/workcmd/sync.go
@@ -33,6 +33,9 @@
 list's version. Note that Minimal Version Selection guarantees that the
 build list's version of each module is always the same or higher than
 that in each workspace module.
+
+See the workspaces reference at https://go.dev/ref/mod#workspaces
+for more information.
 `,
 	Run: runSync,
 }
diff --git a/libgo/go/cmd/go/internal/workcmd/use.go b/libgo/go/cmd/go/internal/workcmd/use.go
index 1ee2d4e..e20041f 100644
--- a/libgo/go/cmd/go/internal/workcmd/use.go
+++ b/libgo/go/cmd/go/internal/workcmd/use.go
@@ -20,7 +20,7 @@
 )
 
 var cmdUse = &base.Command{
-	UsageLine: "go work use [-r] [moddirs]",
+	UsageLine: "go work use [-r] moddirs",
 	Short:     "add modules to workspace file",
 	Long: `Use provides a command-line interface for adding
 directories, optionally recursively, to a go.work file.
@@ -33,6 +33,9 @@
 directories, and the use command operates as if each of the directories
 were specified as arguments: namely, use directives will be added for
 directories that exist, and removed for directories that do not exist.
+
+See the workspaces reference at https://go.dev/ref/mod#workspaces
+for more information.
 `,
 }
 
@@ -101,6 +104,9 @@
 		keepDirs[absDir] = dir
 	}
 
+	if len(args) == 0 {
+		base.Fatalf("go: 'go work use' requires one or more directory arguments")
+	}
 	for _, useDir := range args {
 		if !*useR {
 			lookDir(useDir)
@@ -186,5 +192,5 @@
 
 	// Normalize relative paths to use slashes, so that checked-in go.work
 	// files with relative paths within the repo are platform-independent.
-	return abs, filepath.ToSlash(rel)
+	return abs, modload.ToDirectoryPath(rel)
 }
diff --git a/libgo/go/cmd/go/internal/workcmd/work.go b/libgo/go/cmd/go/internal/workcmd/work.go
index d3cc250..39c81e8 100644
--- a/libgo/go/cmd/go/internal/workcmd/work.go
+++ b/libgo/go/cmd/go/internal/workcmd/work.go
@@ -12,7 +12,7 @@
 var CmdWork = &base.Command{
 	UsageLine: "go work",
 	Short:     "workspace maintenance",
-	Long: `Go workspace provides access to operations on workspaces.
+	Long: `Work provides access to operations on workspaces.
 
 Note that support for workspaces is built into many other commands, not
 just 'go work'.
@@ -20,6 +20,12 @@
 See 'go help modules' for information about Go's module system of which
 workspaces are a part.
 
+See https://go.dev/ref/mod#workspaces for an in-depth reference on
+workspaces.
+
+See https://go.dev/doc/tutorial/workspaces for an introductory
+tutorial on workspaces.
+
 A workspace is specified by a go.work file that specifies a set of
 module directories with the "use" directive. These modules are used as
 root modules by the go command for builds and related operations.  A
diff --git a/libgo/go/cmd/go/testdata/script/run_work_versioned.txt b/libgo/go/cmd/go/testdata/script/run_work_versioned.txt
new file mode 100644
index 0000000..eb0f22d
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/script/run_work_versioned.txt
@@ -0,0 +1,16 @@
+[short] skip
+go run example.com/printversion@v0.1.0
+stdout '^main is example.com/printversion v0.1.0$'
+
+-- go.work --
+go 1.18
+
+use (
+	.
+)
+-- go.mod --
+module example
+
+go 1.18
+
+require example.com/printversion v1.0.0
diff --git a/libgo/go/cmd/go/testdata/script/test_fuzz_minimize_dirty_cov.txt b/libgo/go/cmd/go/testdata/script/test_fuzz_minimize_dirty_cov.txt
new file mode 100644
index 0000000..571bf75
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/script/test_fuzz_minimize_dirty_cov.txt
@@ -0,0 +1,84 @@
+# Test that minimization doesn't use dirty coverage snapshots when it
+# is unable to actually minimize the input. We do this by checking that
+# a expected value appears in the cache. If a dirty coverage map is used
+# (i.e. the coverage map generated during the last minimization step,
+# rather than the map provided with the initial input) then this value
+# is unlikely to appear in the cache, since the map generated during
+# the last minimization step should not increase the coverage.
+
+[short] skip
+[!fuzz-instrumented] skip
+
+env GOCACHE=$WORK/gocache
+go test -fuzz=FuzzCovMin -fuzztime=25s -test.fuzzcachedir=$GOCACHE/fuzz
+go run check_file/main.go $GOCACHE/fuzz/FuzzCovMin abcd
+
+-- go.mod --
+module test
+
+-- covmin_test.go --
+package covmin
+
+import "testing"
+
+func FuzzCovMin(f *testing.F) {
+	f.Fuzz(func(t *testing.T, data []byte) {
+		if len(data) >= 4 && data[0] == 'a' && data[1] == 'b' && data[2] == 'c' && data[3] == 'd' {
+			return
+		}
+	})
+}
+
+-- check_file/main.go --
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"os"
+	"path/filepath"
+	"regexp"
+	"strconv"
+)
+
+func checkFile(name, expected string) (bool, error) {
+	data, err := os.ReadFile(name)
+	if err != nil {
+		return false, err
+	}
+	for _, line := range bytes.Split(data, []byte("\n")) {
+		m := valRe.FindSubmatch(line)
+		if m == nil {
+			continue
+		}
+		fmt.Println(strconv.Unquote(string(m[1])))
+		if s, err := strconv.Unquote(string(m[1])); err != nil {
+			return false, err
+		} else if s == expected {
+			return true, nil
+		}
+	}
+	return false, nil
+}
+
+var valRe = regexp.MustCompile(`^\[\]byte\(([^)]+)\)$`)
+
+func main() {
+	dir, expected := os.Args[1], os.Args[2]
+	ents, err := os.ReadDir(dir)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		os.Exit(1)
+	}
+	for _, ent := range ents {
+		name := filepath.Join(dir, ent.Name())
+		if good, err := checkFile(name, expected); err != nil {
+			fmt.Fprintln(os.Stderr, err)
+			os.Exit(1)
+		} else if good {
+			os.Exit(0)
+		}
+	}
+	fmt.Fprintln(os.Stderr, "input over minimized")
+	os.Exit(1)
+}
diff --git a/libgo/go/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt b/libgo/go/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt
index 5d0de17..a09e85b 100644
--- a/libgo/go/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt
+++ b/libgo/go/cmd/go/testdata/script/test_fuzz_minimize_interesting.txt
@@ -127,19 +127,8 @@
 		if bytes.Equal(buf, seed) {
 			return
 		}
-		if n := sum(buf); n < 0 {
-			t.Error("sum cannot be negative")
-		}
 	})
 }
-
-func sum(buf []byte) int {
-	n := 0
-	for _, b := range buf {
-		n += int(b)
-	}
-	return n
-}
 -- check_testdata/check_testdata.go --
 //go:build ignore
 // +build ignore
diff --git a/libgo/go/cmd/go/testdata/script/version_buildvcs_git.txt b/libgo/go/cmd/go/testdata/script/version_buildvcs_git.txt
index 86d1de0..4470687 100644
--- a/libgo/go/cmd/go/testdata/script/version_buildvcs_git.txt
+++ b/libgo/go/cmd/go/testdata/script/version_buildvcs_git.txt
@@ -111,7 +111,7 @@
 go list -x ./...
 stdout -count=3 '^example.com'
 stderr -count=1 '^git status'
-stderr -count=1 '^git show'
+stderr -count=1 '^git -c log.showsignature=false show'
 
 -- $WORK/fakebin/git --
 #!/bin/sh
diff --git a/libgo/go/cmd/go/testdata/script/work.txt b/libgo/go/cmd/go/testdata/script/work.txt
index a10bf5a..fa1558f 100644
--- a/libgo/go/cmd/go/testdata/script/work.txt
+++ b/libgo/go/cmd/go/testdata/script/work.txt
@@ -4,7 +4,7 @@
 ! stdout .
 
 go work init ./a ./b
-cmp go.work go.work.want
+cmpenv go.work go.work.want
 go env GOWORK
 stdout '^'$WORK'(\\|/)gopath(\\|/)src(\\|/)go.work$'
 
@@ -69,7 +69,7 @@
   ../src/a
 )
 -- go.work.want --
-go 1.18
+go $goversion
 
 use (
 	./a
diff --git a/libgo/go/cmd/go/testdata/script/work_edit.txt b/libgo/go/cmd/go/testdata/script/work_edit.txt
index 71959ca..278afb7 100644
--- a/libgo/go/cmd/go/testdata/script/work_edit.txt
+++ b/libgo/go/cmd/go/testdata/script/work_edit.txt
@@ -1,10 +1,10 @@
 # Test editing go.work files.
 
 go work init m
-cmp go.work go.work.want_initial
+cmpenv go.work go.work.want_initial
 
 go work edit -use n
-cmp go.work go.work.want_use_n
+cmpenv go.work go.work.want_use_n
 
 go work edit -go 1.18
 cmp go.work go.work.want_go_118
@@ -39,11 +39,11 @@
 
 go 1.18
 -- go.work.want_initial --
-go 1.18
+go $goversion
 
 use ./m
 -- go.work.want_use_n --
-go 1.18
+go $goversion
 
 use (
 	./m
diff --git a/libgo/go/cmd/go/testdata/script/work_init_path.txt b/libgo/go/cmd/go/testdata/script/work_init_path.txt
new file mode 100644
index 0000000..e397788
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/script/work_init_path.txt
@@ -0,0 +1,17 @@
+# Regression test for https://go.dev/issue/51448.
+# 'go work init . foo/bar' should produce a go.work file
+# with the same paths as 'go work init; go work use -r .'.
+
+go work init . foo/bar
+mv go.work go.work.init
+
+go work init
+go work use -r .
+cmp go.work go.work.init
+
+-- go.mod --
+module example
+go 1.18
+-- foo/bar/go.mod --
+module example
+go 1.18
diff --git a/libgo/go/cmd/go/testdata/script/work_use.txt b/libgo/go/cmd/go/testdata/script/work_use.txt
index f5ea89c..12c8cec 100644
--- a/libgo/go/cmd/go/testdata/script/work_use.txt
+++ b/libgo/go/cmd/go/testdata/script/work_use.txt
@@ -14,16 +14,16 @@
 go 1.18
 
 use (
-	foo
-	foo/bar/baz
+	./foo
+	./foo/bar/baz
 )
 -- go.want_work_other --
 go 1.18
 
 use (
-	foo
-	foo/bar/baz
-	other
+	./foo
+	./foo/bar/baz
+	./other
 )
 -- foo/go.mod --
 module foo
diff --git a/libgo/go/cmd/go/testdata/script/work_use_deleted.txt b/libgo/go/cmd/go/testdata/script/work_use_deleted.txt
index 660eb56..b379cbc 100644
--- a/libgo/go/cmd/go/testdata/script/work_use_deleted.txt
+++ b/libgo/go/cmd/go/testdata/script/work_use_deleted.txt
@@ -6,13 +6,13 @@
 
 use (
 	.
-	sub
-	sub/dir/deleted
+	./sub
+	./sub/dir/deleted
 )
 -- go.work.want --
 go 1.18
 
-use sub/dir
+use ./sub/dir
 -- sub/README.txt --
 A go.mod file has been deleted from this directory.
 In addition, the entire subdirectory sub/dir/deleted
diff --git a/libgo/go/cmd/go/testdata/script/work_use_dot.txt b/libgo/go/cmd/go/testdata/script/work_use_dot.txt
index ccd83d6..8f21042 100644
--- a/libgo/go/cmd/go/testdata/script/work_use_dot.txt
+++ b/libgo/go/cmd/go/testdata/script/work_use_dot.txt
@@ -31,7 +31,7 @@
 # resulting workspace would contain a duplicate module.
 cp ../../go.work.orig ../../go.work
 ! go work use $PWD .
-stderr '^go: already added "bar/baz" as "'$PWD'"$'
+stderr '^go: already added "\./bar/baz" as "'$PWD'"$'
 cmp ../../go.work ../../go.work.orig
 
 
@@ -43,7 +43,7 @@
 -- go.work.rel --
 go 1.18
 
-use bar/baz
+use ./bar/baz
 -- bar/baz/go.mod --
 module example/bar/baz
 go 1.18
diff --git a/libgo/go/cmd/go/testdata/script/work_use_noargs.txt b/libgo/go/cmd/go/testdata/script/work_use_noargs.txt
new file mode 100644
index 0000000..ca05434
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/script/work_use_noargs.txt
@@ -0,0 +1,11 @@
+# For now, 'go work use' requires arguments.
+# (Eventually, we may may it implicitly behave like 'go work use .'.
+
+! go work use
+stderr '^go: ''go work use'' requires one or more directory arguments'
+
+! go work use -r
+stderr '^go: ''go work use'' requires one or more directory arguments'
+
+-- go.work --
+go 1.18
diff --git a/libgo/go/encoding/xml/marshal.go b/libgo/go/encoding/xml/marshal.go
index 6859be0..7792ac7 100644
--- a/libgo/go/encoding/xml/marshal.go
+++ b/libgo/go/encoding/xml/marshal.go
@@ -512,7 +512,7 @@
 		}
 		fv := finfo.value(val, dontInitNilPointers)
 
-		if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) {
+		if finfo.flags&fOmitEmpty != 0 && (!fv.IsValid() || isEmptyValue(fv)) {
 			continue
 		}
 
diff --git a/libgo/go/encoding/xml/marshal_test.go b/libgo/go/encoding/xml/marshal_test.go
index 115a93f..0b6965d 100644
--- a/libgo/go/encoding/xml/marshal_test.go
+++ b/libgo/go/encoding/xml/marshal_test.go
@@ -2499,3 +2499,39 @@
 		t.Errorf("error %q does not contain %q", err, want)
 	}
 }
+
+// Issue 50164. Crash on zero value XML attribute.
+type LayerOne struct {
+	XMLName Name `xml:"l1"`
+
+	Value     *float64 `xml:"value,omitempty"`
+	*LayerTwo `xml:",omitempty"`
+}
+
+type LayerTwo struct {
+	ValueTwo *int `xml:"value_two,attr,omitempty"`
+}
+
+func TestMarshalZeroValue(t *testing.T) {
+	proofXml := `<l1><value>1.2345</value></l1>`
+	var l1 LayerOne
+	err := Unmarshal([]byte(proofXml), &l1)
+	if err != nil {
+		t.Fatalf("unmarshal XML error: %v", err)
+	}
+	want := float64(1.2345)
+	got := *l1.Value
+	if got != want {
+		t.Fatalf("unexpected unmarshal result, want %f but got %f", want, got)
+	}
+
+	// Marshal again (or Encode again)
+	// In issue 50164, here `Marshal(l1)` will panic because of the zero value of xml attribute ValueTwo `value_two`.
+	anotherXML, err := Marshal(l1)
+	if err != nil {
+		t.Fatalf("marshal XML error: %v", err)
+	}
+	if string(anotherXML) != proofXml {
+		t.Fatalf("unexpected unmarshal result, want %q but got %q", proofXml, anotherXML)
+	}
+}
diff --git a/libgo/go/go/internal/gcimporter/iimport.go b/libgo/go/go/internal/gcimporter/iimport.go
index 8ec4c54..bff1c09 100644
--- a/libgo/go/go/internal/gcimporter/iimport.go
+++ b/libgo/go/go/internal/gcimporter/iimport.go
@@ -181,6 +181,15 @@
 		p.doDecl(localpkg, name)
 	}
 
+	// SetConstraint can't be called if the constraint type is not yet complete.
+	// When type params are created in the 'P' case of (*importReader).obj(),
+	// the associated constraint type may not be complete due to recursion.
+	// Therefore, we defer calling SetConstraint there, and call it here instead
+	// after all types are complete.
+	for _, d := range p.later {
+		d.t.SetConstraint(d.constraint)
+	}
+
 	for _, typ := range p.interfaceList {
 		typ.Complete()
 	}
@@ -195,6 +204,11 @@
 	return localpkg, nil
 }
 
+type setConstraintArgs struct {
+	t          *types.TypeParam
+	constraint types.Type
+}
+
 type iimporter struct {
 	exportVersion int64
 	ipath         string
@@ -211,6 +225,9 @@
 
 	fake          fakeFileSet
 	interfaceList []*types.Interface
+
+	// Arguments for calls to SetConstraint that are deferred due to recursive types
+	later []setConstraintArgs
 }
 
 func (p *iimporter) doDecl(pkg *types.Package, name string) {
@@ -391,7 +408,11 @@
 			}
 			iface.MarkImplicit()
 		}
-		t.SetConstraint(constraint)
+		// The constraint type may not be complete, if we
+		// are in the middle of a type recursion involving type
+		// constraints. So, we defer SetConstraint until we have
+		// completely set up all types in ImportData.
+		r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint})
 
 	case 'V':
 		typ := r.typ()
diff --git a/libgo/go/go/printer/nodes.go b/libgo/go/go/printer/nodes.go
index f2170db..9a09d58 100644
--- a/libgo/go/go/printer/nodes.go
+++ b/libgo/go/go/printer/nodes.go
@@ -319,9 +319,17 @@
 	}
 }
 
-func (p *printer) parameters(fields *ast.FieldList, isTypeParam bool) {
+type paramMode int
+
+const (
+	funcParam paramMode = iota
+	funcTParam
+	typeTParam
+)
+
+func (p *printer) parameters(fields *ast.FieldList, mode paramMode) {
 	openTok, closeTok := token.LPAREN, token.RPAREN
-	if isTypeParam {
+	if mode != funcParam {
 		openTok, closeTok = token.LBRACK, token.RBRACK
 	}
 	p.print(fields.Opening, openTok)
@@ -373,7 +381,7 @@
 		if closing := p.lineFor(fields.Closing); 0 < prevLine && prevLine < closing {
 			p.print(token.COMMA)
 			p.linebreak(closing, 0, ignore, true)
-		} else if isTypeParam && fields.NumFields() == 1 {
+		} else if mode == typeTParam && fields.NumFields() == 1 {
 			// Otherwise, if we are in a type parameter list that could be confused
 			// with the constant array length expression [P*C], print a comma so that
 			// parsing is unambiguous.
@@ -411,10 +419,10 @@
 
 func (p *printer) signature(sig *ast.FuncType) {
 	if sig.TypeParams != nil {
-		p.parameters(sig.TypeParams, true)
+		p.parameters(sig.TypeParams, funcTParam)
 	}
 	if sig.Params != nil {
-		p.parameters(sig.Params, false)
+		p.parameters(sig.Params, funcParam)
 	} else {
 		p.print(token.LPAREN, token.RPAREN)
 	}
@@ -428,7 +436,7 @@
 			p.expr(stripParensAlways(res.List[0].Type))
 			return
 		}
-		p.parameters(res, false)
+		p.parameters(res, funcParam)
 	}
 }
 
@@ -1639,7 +1647,7 @@
 		p.setComment(s.Doc)
 		p.expr(s.Name)
 		if s.TypeParams != nil {
-			p.parameters(s.TypeParams, true)
+			p.parameters(s.TypeParams, typeTParam)
 		}
 		if n == 1 {
 			p.print(blank)
@@ -1829,7 +1837,7 @@
 	// FUNC is emitted).
 	startCol := p.out.Column - len("func ")
 	if d.Recv != nil {
-		p.parameters(d.Recv, false) // method: print receiver
+		p.parameters(d.Recv, funcParam) // method: print receiver
 		p.print(blank)
 	}
 	p.expr(d.Name)
diff --git a/libgo/go/go/printer/testdata/generics.golden b/libgo/go/go/printer/testdata/generics.golden
index 4fac2c9..c3a7df8 100644
--- a/libgo/go/go/printer/testdata/generics.golden
+++ b/libgo/go/go/printer/testdata/generics.golden
@@ -64,3 +64,29 @@
 type _[
 	P *T,
 ] struct{}
+
+// equivalent test cases for potentially ambiguous type parameter lists, except
+// for function declarations there is no ambiguity (issue #51548)
+func _[P *T]()		{}
+func _[P *T, _ any]()	{}
+func _[P *T]()		{}
+func _[P *T, _ any]()	{}
+func _[P T]()		{}
+func _[P T, _ any]()	{}
+
+func _[P *struct{}]()	{}
+func _[P *struct{}]()	{}
+func _[P []int]()	{}
+
+func _[P T]()	{}
+func _[P T]()	{}
+func _[P **T]()	{}
+func _[P *T]()	{}
+func _[P *T]()	{}
+func _[P **T]()	{}
+func _[P *T]()	{}
+
+func _[
+	P *T,
+]() {
+}
diff --git a/libgo/go/go/printer/testdata/generics.input b/libgo/go/go/printer/testdata/generics.input
index fde9d32..66e1554 100644
--- a/libgo/go/go/printer/testdata/generics.input
+++ b/libgo/go/go/printer/testdata/generics.input
@@ -61,3 +61,28 @@
 type _[
 	P *T,
 ] struct{}
+
+// equivalent test cases for potentially ambiguous type parameter lists, except
+// for function declarations there is no ambiguity (issue #51548)
+func _[P *T,]() {}
+func _[P *T, _ any]() {}
+func _[P (*T),]() {}
+func _[P (*T), _ any]() {}
+func _[P (T),]() {}
+func _[P (T), _ any]() {}
+
+func _[P *struct{}] () {}
+func _[P (*struct{})] () {}
+func _[P ([]int)] () {}
+
+func _ [P(T)]() {}
+func _ [P((T))]() {}
+func _ [P * *T]() {}
+func _ [P * T]() {}
+func _ [P(*T)]() {}
+func _ [P(**T)]() {}
+func _ [P * T]() {}
+
+func _[
+	P *T,
+]() {}
diff --git a/libgo/go/go/types/api.go b/libgo/go/go/types/api.go
index e5ae240..248db18 100644
--- a/libgo/go/go/types/api.go
+++ b/libgo/go/go/types/api.go
@@ -201,12 +201,12 @@
 	// qualified identifiers are collected in the Uses map.
 	Types map[ast.Expr]TypeAndValue
 
-	// Instances maps identifiers denoting parameterized types or functions to
-	// their type arguments and instantiated type.
+	// Instances maps identifiers denoting generic types or functions to their
+	// type arguments and instantiated type.
 	//
 	// For example, Instances will map the identifier for 'T' in the type
 	// instantiation T[int, string] to the type arguments [int, string] and
-	// resulting instantiated *Named type. Given a parameterized function
+	// resulting instantiated *Named type. Given a generic function
 	// func F[A any](A), Instances will map the identifier for 'F' in the call
 	// expression F(int(1)) to the inferred type arguments [int], and resulting
 	// instantiated *Signature.
@@ -419,8 +419,11 @@
 }
 
 // AssertableTo reports whether a value of type V can be asserted to have type T.
-// The behavior of AssertableTo is undefined if V is a generalized interface; i.e.,
-// an interface that may only be used as a type constraint in Go code.
+//
+// The behavior of AssertableTo is undefined in two cases:
+//  - if V is a generalized interface; i.e., an interface that may only be used
+//    as a type constraint in Go code
+//  - if T is an uninstantiated generic type
 func AssertableTo(V *Interface, T Type) bool {
 	// Checker.newAssertableTo suppresses errors for invalid types, so we need special
 	// handling here.
@@ -430,20 +433,31 @@
 	return (*Checker)(nil).newAssertableTo(V, T) == nil
 }
 
-// AssignableTo reports whether a value of type V is assignable to a variable of type T.
+// AssignableTo reports whether a value of type V is assignable to a variable
+// of type T.
+//
+// The behavior of AssignableTo is undefined if V or T is an uninstantiated
+// generic type.
 func AssignableTo(V, T Type) bool {
 	x := operand{mode: value, typ: V}
 	ok, _ := x.assignableTo(nil, T, nil) // check not needed for non-constant x
 	return ok
 }
 
-// ConvertibleTo reports whether a value of type V is convertible to a value of type T.
+// ConvertibleTo reports whether a value of type V is convertible to a value of
+// type T.
+//
+// The behavior of ConvertibleTo is undefined if V or T is an uninstantiated
+// generic type.
 func ConvertibleTo(V, T Type) bool {
 	x := operand{mode: value, typ: V}
 	return x.convertibleTo(nil, T, nil) // check not needed for non-constant x
 }
 
 // Implements reports whether type V implements interface T.
+//
+// The behavior of Implements is undefined if V is an uninstantiated generic
+// type.
 func Implements(V Type, T *Interface) bool {
 	if T.Empty() {
 		// All types (even Typ[Invalid]) implement the empty interface.
diff --git a/libgo/go/go/types/api_test.go b/libgo/go/go/types/api_test.go
index b67af8c..5003ce2 100644
--- a/libgo/go/go/types/api_test.go
+++ b/libgo/go/go/types/api_test.go
@@ -16,6 +16,7 @@
 	"internal/testenv"
 	"reflect"
 	"regexp"
+	"sort"
 	"strings"
 	"testing"
 
@@ -435,129 +436,146 @@
 }
 
 func TestInstanceInfo(t *testing.T) {
-	var tests = []struct {
-		src   string
-		name  string
-		targs []string
-		typ   string
-	}{
-		{`package p0; func f[T any](T) {}; func _() { f(42) }`,
-			`f`,
-			[]string{`int`},
-			`func(int)`,
-		},
-		{`package p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`,
-			`f`,
-			[]string{`rune`},
-			`func(rune) rune`,
-		},
-		{`package p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`,
-			`f`,
-			[]string{`complex128`},
-			`func(...complex128) complex128`,
-		},
-		{`package p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`,
-			`f`,
-			[]string{`float64`, `string`, `byte`},
-			`func(float64, *string, []byte)`,
-		},
-		{`package p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`,
-			`f`,
-			[]string{`float64`, `byte`},
-			`func(float64, *byte, ...[]byte)`,
-		},
-
-		{`package s1; func f[T any, P interface{~*T}](x T) {}; func _(x string) { f(x) }`,
-			`f`,
-			[]string{`string`, `*string`},
-			`func(x string)`,
-		},
-		{`package s2; func f[T any, P interface{~*T}](x []T) {}; func _(x []int) { f(x) }`,
-			`f`,
-			[]string{`int`, `*int`},
-			`func(x []int)`,
-		},
-		{`package s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`,
-			`f`,
-			[]string{`int`, `chan<- int`},
-			`func(x []int)`,
-		},
-		{`package s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`,
-			`f`,
-			[]string{`int`, `chan<- int`, `chan<- []*chan<- int`},
-			`func(x []int)`,
-		},
-
-		{`package t1; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = f[string] }`,
-			`f`,
-			[]string{`string`, `*string`},
-			`func() string`,
-		},
-		{`package t2; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = (f[string]) }`,
-			`f`,
-			[]string{`string`, `*string`},
-			`func() string`,
-		},
-		{`package t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]]() []T { return nil }; func _() { _ = f[int] }`,
-			`f`,
-			[]string{`int`, `chan<- int`},
-			`func() []int`,
-		},
-		{`package t4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`,
-			`f`,
-			[]string{`int`, `chan<- int`, `chan<- []*chan<- int`},
-			`func() []int`,
-		},
-		{`package i0; import "lib"; func _() { lib.F(42) }`,
-			`F`,
-			[]string{`int`},
-			`func(int)`,
-		},
-		{`package type0; type T[P interface{~int}] struct{ x P }; var _ T[int]`,
-			`T`,
-			[]string{`int`},
-			`struct{x int}`,
-		},
-		{`package type1; type T[P interface{~int}] struct{ x P }; var _ (T[int])`,
-			`T`,
-			[]string{`int`},
-			`struct{x int}`,
-		},
-		{`package type2; type T[P interface{~int}] struct{ x P }; var _ T[(int)]`,
-			`T`,
-			[]string{`int`},
-			`struct{x int}`,
-		},
-		{`package type3; type T[P1 interface{~[]P2}, P2 any] struct{ x P1; y P2 }; var _ T[[]int, int]`,
-			`T`,
-			[]string{`[]int`, `int`},
-			`struct{x []int; y int}`,
-		},
-		{`package type4; import "lib"; var _ lib.T[int]`,
-			`T`,
-			[]string{`int`},
-			`[]int`,
-		},
-	}
-
-	for _, test := range tests {
-		const lib = `package lib
+	const lib = `package lib
 
 func F[P any](P) {}
 
 type T[P any] []P
 `
 
+	type testInst struct {
+		name  string
+		targs []string
+		typ   string
+	}
+
+	var tests = []struct {
+		src       string
+		instances []testInst // recorded instances in source order
+	}{
+		{`package p0; func f[T any](T) {}; func _() { f(42) }`,
+			[]testInst{{`f`, []string{`int`}, `func(int)`}},
+		},
+		{`package p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`,
+			[]testInst{{`f`, []string{`rune`}, `func(rune) rune`}},
+		},
+		{`package p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`,
+			[]testInst{{`f`, []string{`complex128`}, `func(...complex128) complex128`}},
+		},
+		{`package p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`,
+			[]testInst{{`f`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`}},
+		},
+		{`package p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`,
+			[]testInst{{`f`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`}},
+		},
+
+		{`package s1; func f[T any, P interface{*T}](x T) {}; func _(x string) { f(x) }`,
+			[]testInst{{`f`, []string{`string`, `*string`}, `func(x string)`}},
+		},
+		{`package s2; func f[T any, P interface{*T}](x []T) {}; func _(x []int) { f(x) }`,
+			[]testInst{{`f`, []string{`int`, `*int`}, `func(x []int)`}},
+		},
+		{`package s3; type C[T any] interface{chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`,
+			[]testInst{
+				{`C`, []string{`T`}, `interface{chan<- T}`},
+				{`f`, []string{`int`, `chan<- int`}, `func(x []int)`},
+			},
+		},
+		{`package s4; type C[T any] interface{chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`,
+			[]testInst{
+				{`C`, []string{`T`}, `interface{chan<- T}`},
+				{`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
+				{`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func(x []int)`},
+			},
+		},
+
+		{`package t1; func f[T any, P interface{*T}]() T { panic(0) }; func _() { _ = f[string] }`,
+			[]testInst{{`f`, []string{`string`, `*string`}, `func() string`}},
+		},
+		{`package t2; func f[T any, P interface{*T}]() T { panic(0) }; func _() { _ = (f[string]) }`,
+			[]testInst{{`f`, []string{`string`, `*string`}, `func() string`}},
+		},
+		{`package t3; type C[T any] interface{chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`,
+			[]testInst{
+				{`C`, []string{`T`}, `interface{chan<- T}`},
+				{`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
+				{`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`},
+			},
+		},
+		{`package t4; type C[T any] interface{chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = (f[int]) }`,
+			[]testInst{
+				{`C`, []string{`T`}, `interface{chan<- T}`},
+				{`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
+				{`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`},
+			},
+		},
+		{`package i0; import "lib"; func _() { lib.F(42) }`,
+			[]testInst{{`F`, []string{`int`}, `func(int)`}},
+		},
+
+		{`package duplfunc0; func f[T any](T) {}; func _() { f(42); f("foo"); f[int](3) }`,
+			[]testInst{
+				{`f`, []string{`int`}, `func(int)`},
+				{`f`, []string{`string`}, `func(string)`},
+				{`f`, []string{`int`}, `func(int)`},
+			},
+		},
+		{`package duplfunc1; import "lib"; func _() { lib.F(42); lib.F("foo"); lib.F(3) }`,
+			[]testInst{
+				{`F`, []string{`int`}, `func(int)`},
+				{`F`, []string{`string`}, `func(string)`},
+				{`F`, []string{`int`}, `func(int)`},
+			},
+		},
+
+		{`package type0; type T[P interface{~int}] struct{ x P }; var _ T[int]`,
+			[]testInst{{`T`, []string{`int`}, `struct{x int}`}},
+		},
+		{`package type1; type T[P interface{~int}] struct{ x P }; var _ (T[int])`,
+			[]testInst{{`T`, []string{`int`}, `struct{x int}`}},
+		},
+		{`package type2; type T[P interface{~int}] struct{ x P }; var _ T[(int)]`,
+			[]testInst{{`T`, []string{`int`}, `struct{x int}`}},
+		},
+		{`package type3; type T[P1 interface{~[]P2}, P2 any] struct{ x P1; y P2 }; var _ T[[]int, int]`,
+			[]testInst{{`T`, []string{`[]int`, `int`}, `struct{x []int; y int}`}},
+		},
+		{`package type4; import "lib"; var _ lib.T[int]`,
+			[]testInst{{`T`, []string{`int`}, `[]int`}},
+		},
+
+		{`package dupltype0; type T[P interface{~int}] struct{ x P }; var x T[int]; var y T[int]`,
+			[]testInst{
+				{`T`, []string{`int`}, `struct{x int}`},
+				{`T`, []string{`int`}, `struct{x int}`},
+			},
+		},
+		{`package dupltype1; type T[P ~int] struct{ x P }; func (r *T[Q]) add(z T[Q]) { r.x += z.x }`,
+			[]testInst{
+				{`T`, []string{`Q`}, `struct{x Q}`},
+				{`T`, []string{`Q`}, `struct{x Q}`},
+			},
+		},
+		{`package dupltype1; import "lib"; var x lib.T[int]; var y lib.T[int]; var z lib.T[string]`,
+			[]testInst{
+				{`T`, []string{`int`}, `[]int`},
+				{`T`, []string{`int`}, `[]int`},
+				{`T`, []string{`string`}, `[]string`},
+			},
+		},
+	}
+
+	for _, test := range tests {
 		imports := make(testImporter)
 		conf := Config{Importer: imports}
-		instances := make(map[*ast.Ident]Instance)
-		uses := make(map[*ast.Ident]Object)
+		instMap := make(map[*ast.Ident]Instance)
+		useMap := make(map[*ast.Ident]Object)
 		makePkg := func(src string) *Package {
 			f, err := parser.ParseFile(fset, "p.go", src, 0)
 			if err != nil {
 				t.Fatal(err)
 			}
-			pkg, err := conf.Check("", fset, []*ast.File{f}, &Info{Instances: instances, Uses: uses})
+			pkg, err := conf.Check("", fset, []*ast.File{f}, &Info{Instances: instMap, Uses: useMap})
 			if err != nil {
 				t.Fatal(err)
 			}
@@ -567,60 +585,71 @@
 		makePkg(lib)
 		pkg := makePkg(test.src)
 
-		// look for instance information
-		var targs []Type
-		var typ Type
-		for ident, inst := range instances {
-			if ExprString(ident) == test.name {
-				for i := 0; i < inst.TypeArgs.Len(); i++ {
-					targs = append(targs, inst.TypeArgs.At(i))
-				}
-				typ = inst.Type
+		t.Run(pkg.Name(), func(t *testing.T) {
+			// Sort instances in source order for stability.
+			instances := sortedInstances(instMap)
+			if got, want := len(instances), len(test.instances); got != want {
+				t.Fatalf("got %d instances, want %d", got, want)
+			}
 
-				// Check that we can find the corresponding parameterized type.
-				ptype := uses[ident].Type()
+			// Pairwise compare with the expected instances.
+			for ii, inst := range instances {
+				var targs []Type
+				for i := 0; i < inst.Inst.TypeArgs.Len(); i++ {
+					targs = append(targs, inst.Inst.TypeArgs.At(i))
+				}
+				typ := inst.Inst.Type
+
+				testInst := test.instances[ii]
+				if got := inst.Ident.Name; got != testInst.name {
+					t.Fatalf("got name %s, want %s", got, testInst.name)
+				}
+				if len(targs) != len(testInst.targs) {
+					t.Fatalf("got %d type arguments; want %d", len(targs), len(testInst.targs))
+				}
+				for i, targ := range targs {
+					if got := targ.String(); got != testInst.targs[i] {
+						t.Errorf("type argument %d: got %s; want %s", i, got, testInst.targs[i])
+					}
+				}
+				if got := typ.Underlying().String(); got != testInst.typ {
+					t.Errorf("package %s: got %s; want %s", pkg.Name(), got, testInst.typ)
+				}
+
+				// Verify the invariant that re-instantiating the corresponding generic
+				// type with TypeArgs results in an identical instance.
+				ptype := useMap[inst.Ident].Type()
 				lister, _ := ptype.(interface{ TypeParams() *TypeParamList })
 				if lister == nil || lister.TypeParams().Len() == 0 {
-					t.Errorf("package %s: info.Types[%v] = %v, want parameterized type", pkg.Name(), ident, ptype)
-					continue
+					t.Fatalf("info.Types[%v] = %v, want parameterized type", inst.Ident, ptype)
 				}
-
-				// Verify the invariant that re-instantiating the generic type with
-				// TypeArgs results in an equivalent type.
 				inst2, err := Instantiate(nil, ptype, targs, true)
 				if err != nil {
 					t.Errorf("Instantiate(%v, %v) failed: %v", ptype, targs, err)
 				}
-				if !Identical(inst.Type, inst2) {
-					t.Errorf("%v and %v are not identical", inst.Type, inst2)
+				if !Identical(inst.Inst.Type, inst2) {
+					t.Errorf("%v and %v are not identical", inst.Inst.Type, inst2)
 				}
-				break
 			}
-		}
-		if targs == nil {
-			t.Errorf("package %s: no instance information found for %s", pkg.Name(), test.name)
-			continue
-		}
-
-		// check that type arguments are correct
-		if len(targs) != len(test.targs) {
-			t.Errorf("package %s: got %d type arguments; want %d", pkg.Name(), len(targs), len(test.targs))
-			continue
-		}
-		for i, targ := range targs {
-			if got := targ.String(); got != test.targs[i] {
-				t.Errorf("package %s, %d. type argument: got %s; want %s", pkg.Name(), i, got, test.targs[i])
-				continue
-			}
-		}
-
-		// check that the types match
-		if got := typ.Underlying().String(); got != test.typ {
-			t.Errorf("package %s: got %s; want %s", pkg.Name(), got, test.typ)
-		}
+		})
 	}
 }
 
+type recordedInstance struct {
+	Ident *ast.Ident
+	Inst  Instance
+}
+
+func sortedInstances(m map[*ast.Ident]Instance) (instances []recordedInstance) {
+	for id, inst := range m {
+		instances = append(instances, recordedInstance{id, inst})
+	}
+	sort.Slice(instances, func(i, j int) bool {
+		return instances[i].Ident.Pos() < instances[j].Ident.Pos()
+	})
+	return instances
+}
+
 func TestDefsInfo(t *testing.T) {
 	var tests = []struct {
 		src  string
@@ -1690,7 +1719,7 @@
 	var F = /*F=func:12*/ F /*F=var:17*/ ; _ = F
 
 	var a []int
-	for i, x := range /*i=undef*/ /*x=var:16*/ a /*i=var:20*/ /*x=var:20*/ { _ = i; _ = x }
+	for i, x := range a /*i=undef*/ /*x=var:16*/ { _ = i; _ = x }
 
 	var i interface{}
 	switch y := i.(type) { /*y=undef*/
diff --git a/libgo/go/go/types/assignments.go b/libgo/go/go/types/assignments.go
index f75b8b6..f5e22c2 100644
--- a/libgo/go/go/types/assignments.go
+++ b/libgo/go/go/types/assignments.go
@@ -290,15 +290,14 @@
 	return "(" + strings.Join(res, ", ") + ")"
 }
 
-func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) {
-	measure := func(x int, unit string) string {
-		s := fmt.Sprintf("%d %s", x, unit)
-		if x != 1 {
-			s += "s"
-		}
-		return s
+func measure(x int, unit string) string {
+	if x != 1 {
+		unit += "s"
 	}
+	return fmt.Sprintf("%d %s", x, unit)
+}
 
+func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) {
 	vars := measure(nvars, "variable")
 	vals := measure(nvals, "value")
 	rhs0 := rhs[0]
diff --git a/libgo/go/go/types/call.go b/libgo/go/go/types/call.go
index 3dab284..5d1f60d 100644
--- a/libgo/go/go/types/call.go
+++ b/libgo/go/go/types/call.go
@@ -429,7 +429,7 @@
 	"_Cmacro_", // function to evaluate the expanded expression
 }
 
-func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
+func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *Named) {
 	// these must be declared before the "goto Error" statements
 	var (
 		obj      Object
@@ -527,7 +527,18 @@
 	}
 
 	check.exprOrType(x, e.X, false)
-	if x.mode == invalid {
+	switch x.mode {
+	case typexpr:
+		// don't crash for "type T T.x" (was issue #51509)
+		if def != nil && x.typ == def {
+			check.cycleError([]Object{def.obj})
+			goto Error
+		}
+	case builtin:
+		// types2 uses the position of '.' for the error
+		check.errorf(e.Sel, _UncalledBuiltin, "cannot select on %s", x)
+		goto Error
+	case invalid:
 		goto Error
 	}
 
diff --git a/libgo/go/go/types/check.go b/libgo/go/go/types/check.go
index 6e1da04..2313637 100644
--- a/libgo/go/go/types/check.go
+++ b/libgo/go/go/types/check.go
@@ -133,7 +133,7 @@
 	untyped  map[ast.Expr]exprInfo // map of expressions without final type
 	delayed  []action              // stack of delayed action segments; segments are processed in FIFO order
 	objPath  []Object              // path of object dependencies during type inference (for cycle reporting)
-	defTypes []*Named              // defined types created during type checking, for final validation.
+	cleaners []cleaner             // list of types that may need a final cleanup at the end of type-checking
 
 	// environment within which the current object is type-checked (valid only
 	// for the duration of type-checking a specific object)
@@ -212,6 +212,16 @@
 	return obj
 }
 
+type cleaner interface {
+	cleanup()
+}
+
+// needsCleanup records objects/types that implement the cleanup method
+// which will be called at the end of type-checking.
+func (check *Checker) needsCleanup(c cleaner) {
+	check.cleaners = append(check.cleaners, c)
+}
+
 // NewChecker returns a new Checker instance for a given package.
 // Package files may be added incrementally via checker.Files.
 func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Checker {
@@ -255,6 +265,8 @@
 	check.methods = nil
 	check.untyped = nil
 	check.delayed = nil
+	check.objPath = nil
+	check.cleaners = nil
 
 	// determine package name and collect valid files
 	pkg := check.pkg
@@ -304,22 +316,37 @@
 
 	defer check.handleBailout(&err)
 
+	print := func(msg string) {
+		if trace {
+			fmt.Println()
+			fmt.Println(msg)
+		}
+	}
+
+	print("== initFiles ==")
 	check.initFiles(files)
 
+	print("== collectObjects ==")
 	check.collectObjects()
 
+	print("== packageObjects ==")
 	check.packageObjects()
 
+	print("== processDelayed ==")
 	check.processDelayed(0) // incl. all functions
 
-	check.expandDefTypes()
+	print("== cleanup ==")
+	check.cleanup()
 
+	print("== initOrder ==")
 	check.initOrder()
 
 	if !check.conf.DisableUnusedImportCheck {
+		print("== unusedImports ==")
 		check.unusedImports()
 	}
 
+	print("== recordUntyped ==")
 	check.recordUntyped()
 
 	if check.firstErr == nil {
@@ -337,7 +364,6 @@
 	check.recvTParamMap = nil
 	check.brokenAliases = nil
 	check.unionTypeSets = nil
-	check.defTypes = nil
 	check.ctxt = nil
 
 	// TODO(rFindley) There's more memory we should release at this point.
@@ -365,27 +391,13 @@
 	check.delayed = check.delayed[:top]
 }
 
-func (check *Checker) expandDefTypes() {
-	// Ensure that every defined type created in the course of type-checking has
-	// either non-*Named underlying, or is unresolved.
-	//
-	// This guarantees that we don't leak any types whose underlying is *Named,
-	// because any unresolved instances will lazily compute their underlying by
-	// substituting in the underlying of their origin. The origin must have
-	// either been imported or type-checked and expanded here, and in either case
-	// its underlying will be fully expanded.
-	for i := 0; i < len(check.defTypes); i++ {
-		n := check.defTypes[i]
-		switch n.underlying.(type) {
-		case nil:
-			if n.resolver == nil {
-				panic("nil underlying")
-			}
-		case *Named:
-			n.under() // n.under may add entries to check.defTypes
-		}
-		n.check = nil
+// cleanup runs cleanup for all collected cleaners.
+func (check *Checker) cleanup() {
+	// Don't use a range clause since Named.cleanup may add more cleaners.
+	for i := 0; i < len(check.cleaners); i++ {
+		check.cleaners[i].cleanup()
 	}
+	check.cleaners = nil
 }
 
 func (check *Checker) record(x *operand) {
diff --git a/libgo/go/go/types/conversions.go b/libgo/go/go/types/conversions.go
index 8474135..c5a69cd 100644
--- a/libgo/go/go/types/conversions.go
+++ b/libgo/go/go/types/conversions.go
@@ -48,11 +48,14 @@
 		// have specific types, constant x cannot be
 		// converted.
 		ok = T.(*TypeParam).underIs(func(u Type) bool {
-			// t is nil if there are no specific type terms
+			// u is nil if there are no specific type terms
 			if u == nil {
 				cause = check.sprintf("%s does not contain specific types", T)
 				return false
 			}
+			if isString(x.typ) && isBytesOrRunes(u) {
+				return true
+			}
 			if !constConvertibleTo(u, nil) {
 				cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T)
 				return false
diff --git a/libgo/go/go/types/decl.go b/libgo/go/go/types/decl.go
index cd6f709..93a37d7 100644
--- a/libgo/go/go/types/decl.go
+++ b/libgo/go/go/types/decl.go
@@ -624,7 +624,6 @@
 	}()
 
 	index := 0
-	var bounds []Type
 	for _, f := range list.List {
 		var bound Type
 		// NOTE: we may be able to assert that f.Type != nil here, but this is not
@@ -642,7 +641,6 @@
 		} else {
 			bound = Typ[Invalid]
 		}
-		bounds = append(bounds, bound)
 		for i := range f.Names {
 			tparams[index+i].bound = bound
 		}
diff --git a/libgo/go/go/types/errorcodes.go b/libgo/go/go/types/errorcodes.go
index a7514b3..64cf24c 100644
--- a/libgo/go/go/types/errorcodes.go
+++ b/libgo/go/go/types/errorcodes.go
@@ -1339,11 +1339,6 @@
 	//  func _() {
 	//  	f()
 	//  }
-	//
-	// Example:
-	//   type N[P, Q any] struct{}
-	//
-	//   var _ N[int]
 	_CannotInferTypeArgs
 
 	// _InvalidTypeArg occurs when a type argument does not satisfy its
diff --git a/libgo/go/go/types/eval.go b/libgo/go/go/types/eval.go
index c8bb005..5700cbf 100644
--- a/libgo/go/go/types/eval.go
+++ b/libgo/go/go/types/eval.go
@@ -37,8 +37,8 @@
 
 // CheckExpr type checks the expression expr as if it had appeared at position
 // pos of package pkg. Type information about the expression is recorded in
-// info. The expression may be an uninstantiated parameterized function or
-// type.
+// info. The expression may be an identifier denoting an uninstantiated generic
+// function or type.
 //
 // If pkg == nil, the Universe scope is used and the provided
 // position pos is ignored. If pkg != nil, and pos is invalid,
diff --git a/libgo/go/go/types/expr.go b/libgo/go/go/types/expr.go
index 8747838..e24bd60 100644
--- a/libgo/go/go/types/expr.go
+++ b/libgo/go/go/types/expr.go
@@ -859,7 +859,7 @@
 	}
 	// see if we can extract a more specific error
 	var cause string
-	comparable(typ, nil, func(format string, args ...interface{}) {
+	comparable(typ, true, nil, func(format string, args ...interface{}) {
 		cause = check.sprintf(format, args...)
 	})
 	return cause
@@ -1339,6 +1339,10 @@
 			// no composite literal type present - use hint (element type of enclosing type)
 			typ = hint
 			base, _ = deref(coreType(typ)) // *T implies &T{}
+			if base == nil {
+				check.errorf(e, _InvalidLit, "invalid composite literal element type %s: no core type", typ)
+				goto Error
+			}
 
 		default:
 			// TODO(gri) provide better error messages depending on context
@@ -1529,7 +1533,7 @@
 		return kind
 
 	case *ast.SelectorExpr:
-		check.selector(x, e)
+		check.selector(x, e, nil)
 
 	case *ast.IndexExpr, *ast.IndexListExpr:
 		ix := typeparams.UnpackIndexExpr(e)
@@ -1584,6 +1588,7 @@
 		case invalid:
 			goto Error
 		case typexpr:
+			check.validVarType(e.X, x.typ)
 			x.typ = &Pointer{base: x.typ}
 		default:
 			var base Type
diff --git a/libgo/go/go/types/index.go b/libgo/go/go/types/index.go
index eac6017..33075ed 100644
--- a/libgo/go/go/types/index.go
+++ b/libgo/go/go/types/index.go
@@ -183,6 +183,7 @@
 	}
 
 	if !valid {
+		// types2 uses the position of '[' for the error
 		check.invalidOp(x, _NonIndexableOperand, "cannot index %s", x)
 		x.mode = invalid
 		return false
diff --git a/libgo/go/go/types/infer.go b/libgo/go/go/types/infer.go
index 8f22144..6bed55c 100644
--- a/libgo/go/go/types/infer.go
+++ b/libgo/go/go/types/infer.go
@@ -487,21 +487,88 @@
 		}
 	}
 
-	// If a constraint has a core type, unify the corresponding type parameter with it.
-	for _, tpar := range tparams {
-		if ctype := adjCoreType(tpar); ctype != nil {
-			if !u.unify(tpar, ctype) {
-				// TODO(gri) improve error message by providing the type arguments
-				//           which we know already
-				check.errorf(posn, _InvalidTypeArg, "%s does not match %s", tpar, ctype)
-				return nil, 0
+	// Repeatedly apply constraint type inference as long as
+	// there are still unknown type arguments and progress is
+	// being made.
+	//
+	// This is an O(n^2) algorithm where n is the number of
+	// type parameters: if there is progress (and iteration
+	// continues), at least one type argument is inferred
+	// per iteration and we have a doubly nested loop.
+	// In practice this is not a problem because the number
+	// of type parameters tends to be very small (< 5 or so).
+	// (It should be possible for unification to efficiently
+	// signal newly inferred type arguments; then the loops
+	// here could handle the respective type parameters only,
+	// but that will come at a cost of extra complexity which
+	// may not be worth it.)
+	for n := u.x.unknowns(); n > 0; {
+		nn := n
+
+		for i, tpar := range tparams {
+			// If there is a core term (i.e., a core type with tilde information)
+			// unify the type parameter with the core type.
+			if core, single := coreTerm(tpar); core != nil {
+				// A type parameter can be unified with its core type in two cases.
+				tx := u.x.at(i)
+				switch {
+				case tx != nil:
+					// The corresponding type argument tx is known.
+					// In this case, if the core type has a tilde, the type argument's underlying
+					// type must match the core type, otherwise the type argument and the core type
+					// must match.
+					// If tx is an external type parameter, don't consider its underlying type
+					// (which is an interface). Core type unification will attempt to unify against
+					// core.typ.
+					// Note also that even with inexact unification we cannot leave away the under
+					// call here because it's possible that both tx and core.typ are named types,
+					// with under(tx) being a (named) basic type matching core.typ. Such cases do
+					// not match with inexact unification.
+					if core.tilde && !isTypeParam(tx) {
+						tx = under(tx)
+					}
+					if !u.unify(tx, core.typ) {
+						// TODO(gri) improve error message by providing the type arguments
+						//           which we know already
+						// Don't use term.String() as it always qualifies types, even if they
+						// are in the current package.
+						tilde := ""
+						if core.tilde {
+							tilde = "~"
+						}
+						check.errorf(posn, _InvalidTypeArg, "%s does not match %s%s", tpar, tilde, core.typ)
+						return nil, 0
+					}
+
+				case single && !core.tilde:
+					// The corresponding type argument tx is unknown and there's a single
+					// specific type and no tilde.
+					// In this case the type argument must be that single type; set it.
+					u.x.set(i, core.typ)
+
+				default:
+					// Unification is not possible and no progress was made.
+					continue
+				}
+
+				// The number of known type arguments may have changed.
+				nn = u.x.unknowns()
+				if nn == 0 {
+					break // all type arguments are known
+				}
 			}
 		}
+
+		assert(nn <= n)
+		if nn == n {
+			break // no progress
+		}
+		n = nn
 	}
 
 	// u.x.types() now contains the incoming type arguments plus any additional type
-	// arguments which were inferred from core types. The newly inferred non-
-	// nil entries may still contain references to other type parameters.
+	// arguments which were inferred from core terms. The newly inferred non-nil
+	// entries may still contain references to other type parameters.
 	// For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int
 	// was given, unification produced the type list [int, []C, *A]. We eliminate the
 	// remaining type parameters by substituting the type parameters in this type list
@@ -590,17 +657,40 @@
 	return
 }
 
-func adjCoreType(tpar *TypeParam) Type {
-	// If the type parameter embeds a single, possibly named
-	// type, use that one instead of the core type (which is
-	// always the underlying type of that single type).
-	if single := tpar.singleType(); single != nil {
-		if debug {
-			assert(under(single) == coreType(tpar))
+// If the type parameter has a single specific type S, coreTerm returns (S, true).
+// Otherwise, if tpar has a core type T, it returns a term corresponding to that
+// core type and false. In that case, if any term of tpar has a tilde, the core
+// term has a tilde. In all other cases coreTerm returns (nil, false).
+func coreTerm(tpar *TypeParam) (*term, bool) {
+	n := 0
+	var single *term // valid if n == 1
+	var tilde bool
+	tpar.is(func(t *term) bool {
+		if t == nil {
+			assert(n == 0)
+			return false // no terms
 		}
-		return single
+		n++
+		single = t
+		if t.tilde {
+			tilde = true
+		}
+		return true
+	})
+	if n == 1 {
+		if debug {
+			assert(debug && under(single.typ) == coreType(tpar))
+		}
+		return single, true
 	}
-	return coreType(tpar)
+	if typ := coreType(tpar); typ != nil {
+		// A core type is always an underlying type.
+		// If any term of tpar has a tilde, we don't
+		// have a precise core type and we must return
+		// a tilde as well.
+		return &term{tilde, typ}, false
+	}
+	return nil, false
 }
 
 type cycleFinder struct {
@@ -648,8 +738,6 @@
 	//      in signatures where they are handled explicitly.
 
 	case *Signature:
-		// There are no "method types" so we should never see a recv.
-		assert(t.recv == nil)
 		if t.params != nil {
 			w.varList(t.params.vars)
 		}
diff --git a/libgo/go/go/types/instantiate.go b/libgo/go/go/types/instantiate.go
index 4aeaeb7..a481746 100644
--- a/libgo/go/go/types/instantiate.go
+++ b/libgo/go/go/types/instantiate.go
@@ -15,10 +15,10 @@
 
 // Instantiate instantiates the type orig with the given type arguments targs.
 // orig must be a *Named or a *Signature type. If there is no error, the
-// resulting Type is a new, instantiated (not parameterized) type of the same
-// kind (either a *Named or a *Signature). Methods attached to a *Named type
-// are also instantiated, and associated with a new *Func that has the same
-// position as the original method, but nil function scope.
+// resulting Type is an instantiated type of the same kind (either a *Named or
+// a *Signature). Methods attached to a *Named type are also instantiated, and
+// associated with a new *Func that has the same position as the original
+// method, but nil function scope.
 //
 // If ctxt is non-nil, it may be used to de-duplicate the instance against
 // previous instances with the same identity. As a special case, generic
@@ -204,7 +204,7 @@
 	// If T is comparable, V must be comparable.
 	// Remember as a pending error and report only if we don't have a more specific error.
 	var pending error
-	if Ti.IsComparable() && ((Vi != nil && !Vi.IsComparable()) || (Vi == nil && !Comparable(V))) {
+	if Ti.IsComparable() && !comparable(V, false, nil, nil) {
 		pending = errorf("%s does not implement comparable", V)
 	}
 
diff --git a/libgo/go/go/types/interface.go b/libgo/go/go/types/interface.go
index b9d4660..3db3580 100644
--- a/libgo/go/go/types/interface.go
+++ b/libgo/go/go/types/interface.go
@@ -56,7 +56,7 @@
 	}
 
 	// set method receivers if necessary
-	typ := new(Interface)
+	typ := (*Checker)(nil).newInterface()
 	for _, m := range methods {
 		if sig := m.typ.(*Signature); sig.recv == nil {
 			sig.recv = NewVar(m.pos, m.pkg, "", typ)
@@ -73,6 +73,15 @@
 	return typ
 }
 
+// check may be nil
+func (check *Checker) newInterface() *Interface {
+	typ := &Interface{check: check}
+	if check != nil {
+		check.needsCleanup(typ)
+	}
+	return typ
+}
+
 // MarkImplicit marks the interface t as implicit, meaning this interface
 // corresponds to a constraint literal such as ~T or A|B without explicit
 // interface embedding. MarkImplicit should be called before any concurrent use
@@ -141,6 +150,11 @@
 // ----------------------------------------------------------------------------
 // Implementation
 
+func (t *Interface) cleanup() {
+	t.check = nil
+	t.embedPos = nil
+}
+
 func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) {
 	addEmbedded := func(pos token.Pos, typ Type) {
 		ityp.embeddeds = append(ityp.embeddeds, typ)
@@ -210,16 +224,10 @@
 	sortMethods(ityp.methods)
 	// (don't sort embeddeds: they must correspond to *embedPos entries)
 
-	// Compute type set with a non-nil *Checker as soon as possible
-	// to report any errors. Subsequent uses of type sets will use
-	// this computed type set and won't need to pass in a *Checker.
-	//
-	// Pin the checker to the interface type in the interim, in case the type set
-	// must be used before delayed funcs are processed (see issue #48234).
-	// TODO(rfindley): clean up use of *Checker with computeInterfaceTypeSet
-	ityp.check = check
+	// Compute type set as soon as possible to report any errors.
+	// Subsequent uses of type sets will use this computed type
+	// set and won't need to pass in a *Checker.
 	check.later(func() {
 		computeInterfaceTypeSet(check, iface.Pos(), ityp)
-		ityp.check = nil
 	}).describef(iface, "compute type set for %s", ityp)
 }
diff --git a/libgo/go/go/types/lookup.go b/libgo/go/go/types/lookup.go
index 501c230..335fada 100644
--- a/libgo/go/go/types/lookup.go
+++ b/libgo/go/go/types/lookup.go
@@ -70,7 +70,8 @@
 	// see if there is a matching field (but not a method, those need to be declared
 	// explicitly in the constraint). If the constraint is a named pointer type (see
 	// above), we are ok here because only fields are accepted as results.
-	if obj == nil && isTypeParam(T) {
+	const enableTParamFieldLookup = false // see issue #51576
+	if enableTParamFieldLookup && obj == nil && isTypeParam(T) {
 		if t := coreType(T); t != nil {
 			obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name, false)
 			if _, ok := obj.(*Var); !ok {
diff --git a/libgo/go/go/types/named.go b/libgo/go/go/types/named.go
index 5e84c39..876f7e8 100644
--- a/libgo/go/go/types/named.go
+++ b/libgo/go/go/types/named.go
@@ -72,18 +72,38 @@
 	}
 	// Ensure that typ is always expanded and sanity-checked.
 	if check != nil {
-		check.defTypes = append(check.defTypes, typ)
+		check.needsCleanup(typ)
 	}
 	return typ
 }
 
+func (t *Named) cleanup() {
+	// Ensure that every defined type created in the course of type-checking has
+	// either non-*Named underlying, or is unresolved.
+	//
+	// This guarantees that we don't leak any types whose underlying is *Named,
+	// because any unresolved instances will lazily compute their underlying by
+	// substituting in the underlying of their origin. The origin must have
+	// either been imported or type-checked and expanded here, and in either case
+	// its underlying will be fully expanded.
+	switch t.underlying.(type) {
+	case nil:
+		if t.resolver == nil {
+			panic("nil underlying")
+		}
+	case *Named:
+		t.under() // t.under may add entries to check.cleaners
+	}
+	t.check = nil
+}
+
 // Obj returns the type name for the declaration defining the named type t. For
-// instantiated types, this is the type name of the base type.
+// instantiated types, this is same as the type name of the origin type.
 func (t *Named) Obj() *TypeName {
 	return t.orig.obj // for non-instances this is the same as t.obj
 }
 
-// Origin returns the parameterized type from which the named type t is
+// Origin returns the generic type from which the named type t is
 // instantiated. If t is not an instantiated type, the result is t.
 func (t *Named) Origin() *Named { return t.orig }
 
@@ -91,7 +111,7 @@
 //           between parameterized instantiated and non-instantiated types.
 
 // TypeParams returns the type parameters of the named type t, or nil.
-// The result is non-nil for an (originally) parameterized type even if it is instantiated.
+// The result is non-nil for an (originally) generic type even if it is instantiated.
 func (t *Named) TypeParams() *TypeParamList { return t.resolve(nil).tparams }
 
 // SetTypeParams sets the type parameters of the named type t.
@@ -104,7 +124,11 @@
 // TypeArgs returns the type arguments used to instantiate the named type t.
 func (t *Named) TypeArgs() *TypeList { return t.targs }
 
-// NumMethods returns the number of explicit methods whose receiver is named type t.
+// NumMethods returns the number of explicit methods defined for t.
+//
+// For an ordinary or instantiated type t, the receiver base type of these
+// methods will be the named type t. For an uninstantiated generic type t, each
+// method receiver will be instantiated with its receiver type parameters.
 func (t *Named) NumMethods() int { return t.resolve(nil).methods.Len() }
 
 // Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
@@ -362,11 +386,11 @@
 				// that it wasn't substituted. In this case we need to create a new
 				// *Interface before modifying receivers.
 				if iface == n.orig.underlying {
-					iface = &Interface{
-						embeddeds: iface.embeddeds,
-						complete:  iface.complete,
-						implicit:  iface.implicit, // should be false but be conservative
-					}
+					old := iface
+					iface = check.newInterface()
+					iface.embeddeds = old.embeddeds
+					iface.complete = old.complete
+					iface.implicit = old.implicit // should be false but be conservative
 					underlying = iface
 				}
 				iface.methods = methods
diff --git a/libgo/go/go/types/predicates.go b/libgo/go/go/types/predicates.go
index 14e99bf..0360f27 100644
--- a/libgo/go/go/types/predicates.go
+++ b/libgo/go/go/types/predicates.go
@@ -104,11 +104,12 @@
 
 // Comparable reports whether values of type T are comparable.
 func Comparable(T Type) bool {
-	return comparable(T, nil, nil)
+	return comparable(T, true, nil, nil)
 }
 
+// If dynamic is set, non-type parameter interfaces are always comparable.
 // If reportf != nil, it may be used to report why T is not comparable.
-func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{})) bool {
+func comparable(T Type, dynamic bool, seen map[Type]bool, reportf func(string, ...interface{})) bool {
 	if seen[T] {
 		return true
 	}
@@ -126,7 +127,7 @@
 		return true
 	case *Struct:
 		for _, f := range t.fields {
-			if !comparable(f.typ, seen, nil) {
+			if !comparable(f.typ, dynamic, seen, nil) {
 				if reportf != nil {
 					reportf("struct containing %s cannot be compared", f.typ)
 				}
@@ -135,7 +136,7 @@
 		}
 		return true
 	case *Array:
-		if !comparable(t.elem, seen, nil) {
+		if !comparable(t.elem, dynamic, seen, nil) {
 			if reportf != nil {
 				reportf("%s cannot be compared", t)
 			}
@@ -143,7 +144,7 @@
 		}
 		return true
 	case *Interface:
-		return !isTypeParam(T) || t.typeSet().IsComparable(seen)
+		return dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen)
 	}
 	return false
 }
diff --git a/libgo/go/go/types/signature.go b/libgo/go/go/types/signature.go
index 8f89e93..a340ac7 100644
--- a/libgo/go/go/types/signature.go
+++ b/libgo/go/go/types/signature.go
@@ -112,7 +112,8 @@
 		// - the receiver specification acts as local declaration for its type parameters, which may be blank
 		_, rname, rparams := check.unpackRecv(recvPar.List[0].Type, true)
 		if len(rparams) > 0 {
-			sig.rparams = bindTParams(check.declareTypeParams(nil, rparams))
+			tparams := check.declareTypeParams(nil, rparams)
+			sig.rparams = bindTParams(tparams)
 			// Blank identifiers don't get declared, so naive type-checking of the
 			// receiver type expression would fail in Checker.collectParams below,
 			// when Checker.ident cannot resolve the _ to a type.
@@ -122,11 +123,10 @@
 			// lookup in the scope.
 			for i, p := range rparams {
 				if p.Name == "_" {
-					tpar := sig.rparams.At(i)
 					if check.recvTParamMap == nil {
 						check.recvTParamMap = make(map[*ast.Ident]*TypeParam)
 					}
-					check.recvTParamMap[p] = tpar
+					check.recvTParamMap[p] = tparams[i]
 				}
 			}
 			// determine receiver type to get its type parameters
@@ -142,22 +142,23 @@
 				}
 			}
 			// provide type parameter bounds
-			// - only do this if we have the right number (otherwise an error is reported elsewhere)
-			if sig.RecvTypeParams().Len() == len(recvTParams) {
-				// We have a list of *TypeNames but we need a list of Types.
-				list := make([]Type, sig.RecvTypeParams().Len())
-				for i, t := range sig.RecvTypeParams().list() {
-					list[i] = t
-					check.mono.recordCanon(t, recvTParams[i])
+			if len(tparams) == len(recvTParams) {
+				smap := makeRenameMap(recvTParams, tparams)
+				for i, tpar := range tparams {
+					recvTPar := recvTParams[i]
+					check.mono.recordCanon(tpar, recvTPar)
+					// recvTPar.bound is (possibly) parameterized in the context of the
+					// receiver type declaration. Substitute parameters for the current
+					// context.
+					tpar.bound = check.subst(tpar.obj.pos, recvTPar.bound, smap, nil)
 				}
-				smap := makeSubstMap(recvTParams, list)
-				for i, tpar := range sig.RecvTypeParams().list() {
-					bound := recvTParams[i].bound
-					// bound is (possibly) parameterized in the context of the
-					// receiver type declaration. Substitute parameters for the
-					// current context.
-					tpar.bound = check.subst(tpar.obj.pos, bound, smap, nil)
-				}
+			} else if len(tparams) < len(recvTParams) {
+				// Reporting an error here is a stop-gap measure to avoid crashes in the
+				// compiler when a type parameter/argument cannot be inferred later. It
+				// may lead to follow-on errors (see issues #51339, #51343).
+				// TODO(gri) find a better solution
+				got := measure(len(tparams), "type parameter")
+				check.errorf(recvPar, _BadRecv, "got %s, but receiver base type declares %d", got, len(recvTParams))
 			}
 		}
 	}
@@ -192,66 +193,77 @@
 		switch len(recvList) {
 		case 0:
 			// error reported by resolver
-			recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below
+			recv = NewParam(token.NoPos, nil, "", Typ[Invalid]) // ignore recv below
 		default:
 			// more than one receiver
-			check.error(recvList[len(recvList)-1], _BadRecv, "method must have exactly one receiver")
+			check.error(recvList[len(recvList)-1], _InvalidRecv, "method must have exactly one receiver")
 			fallthrough // continue with first receiver
 		case 1:
 			recv = recvList[0]
 		}
+		sig.recv = recv
 
-		// TODO(gri) We should delay rtyp expansion to when we actually need the
-		//           receiver; thus all checks here should be delayed to later.
-		rtyp, _ := deref(recv.typ)
+		// Delay validation of receiver type as it may cause premature expansion
+		// of types the receiver type is dependent on (see issues #51232, #51233).
+		check.later(func() {
+			rtyp, _ := deref(recv.typ)
 
-		// spec: "The receiver type must be of the form T or *T where T is a type name."
-		// (ignore invalid types - error was reported before)
-		if rtyp != Typ[Invalid] {
-			var err string
-			switch T := rtyp.(type) {
-			case *Named:
-				T.resolve(check.bestContext(nil))
-				// The receiver type may be an instantiated type referred to
-				// by an alias (which cannot have receiver parameters for now).
-				if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
-					check.errorf(atPos(recv.pos), _InvalidRecv, "cannot define methods on instantiated type %s", recv.typ)
-					break
-				}
-				// spec: "The type denoted by T is called the receiver base type; it must not
-				// be a pointer or interface type and it must be declared in the same package
-				// as the method."
-				if T.obj.pkg != check.pkg {
-					err = "type not defined in this package"
-				} else {
-					// The underlying type of a receiver base type can be a type parameter;
-					// e.g. for methods with a generic receiver T[P] with type T[P any] P.
-					underIs(T, func(u Type) bool {
-						switch u := u.(type) {
-						case *Basic:
-							// unsafe.Pointer is treated like a regular pointer
-							if u.kind == UnsafePointer {
-								err = "unsafe.Pointer"
+			// spec: "The receiver type must be of the form T or *T where T is a type name."
+			// (ignore invalid types - error was reported before)
+			if rtyp != Typ[Invalid] {
+				var err string
+				switch T := rtyp.(type) {
+				case *Named:
+					T.resolve(check.bestContext(nil))
+					// The receiver type may be an instantiated type referred to
+					// by an alias (which cannot have receiver parameters for now).
+					if T.TypeArgs() != nil && sig.RecvTypeParams() == nil {
+						check.errorf(recv, _InvalidRecv, "cannot define methods on instantiated type %s", recv.typ)
+						break
+					}
+					// spec: "The type denoted by T is called the receiver base type; it must not
+					// be a pointer or interface type and it must be declared in the same package
+					// as the method."
+					if T.obj.pkg != check.pkg {
+						err = "type not defined in this package"
+						if compilerErrorMessages {
+							check.errorf(recv, _InvalidRecv, "cannot define new methods on non-local type %s", recv.typ)
+							err = ""
+						}
+					} else {
+						// The underlying type of a receiver base type can be a type parameter;
+						// e.g. for methods with a generic receiver T[P] with type T[P any] P.
+						// TODO(gri) Such declarations are currently disallowed.
+						//           Revisit the need for underIs.
+						underIs(T, func(u Type) bool {
+							switch u := u.(type) {
+							case *Basic:
+								// unsafe.Pointer is treated like a regular pointer
+								if u.kind == UnsafePointer {
+									err = "unsafe.Pointer"
+									return false
+								}
+							case *Pointer, *Interface:
+								err = "pointer or interface type"
 								return false
 							}
-						case *Pointer, *Interface:
-							err = "pointer or interface type"
-							return false
-						}
-						return true
-					})
+							return true
+						})
+					}
+				case *Basic:
+					err = "basic or unnamed type"
+					if compilerErrorMessages {
+						check.errorf(recv, _InvalidRecv, "cannot define new methods on non-local type %s", recv.typ)
+						err = ""
+					}
+				default:
+					check.errorf(recv, _InvalidRecv, "invalid receiver type %s", recv.typ)
 				}
-			case *Basic:
-				err = "basic or unnamed type"
-			default:
-				check.errorf(recv, _InvalidRecv, "invalid receiver type %s", recv.typ)
+				if err != "" {
+					check.errorf(recv, _InvalidRecv, "invalid receiver type %s (%s)", recv.typ, err)
+				}
 			}
-			if err != "" {
-				check.errorf(recv, _InvalidRecv, "invalid receiver type %s (%s)", recv.typ, err)
-				// ok to continue
-			}
-		}
-		sig.recv = recv
+		}).describef(recv, "validate receiver %s", recv)
 	}
 
 	sig.params = NewTuple(params...)
diff --git a/libgo/go/go/types/stmt.go b/libgo/go/go/types/stmt.go
index a5aee48..9ebfbb6 100644
--- a/libgo/go/go/types/stmt.go
+++ b/libgo/go/go/types/stmt.go
@@ -821,8 +821,6 @@
 
 	case *ast.RangeStmt:
 		inner |= breakOk | continueOk
-		check.openScope(s, "for")
-		defer check.closeScope()
 
 		// check expression to iterate over
 		var x operand
@@ -857,6 +855,11 @@
 			}
 		}
 
+		// Open the for-statement block scope now, after the range clause.
+		// Iteration variables declared with := need to go in this scope (was issue #51437).
+		check.openScope(s, "range")
+		defer check.closeScope()
+
 		// check assignment to/declaration of iteration variables
 		// (irregular assignment, cannot easily map to existing assignment checks)
 
@@ -865,9 +868,7 @@
 		rhs := [2]Type{key, val} // key, val may be nil
 
 		if s.Tok == token.DEFINE {
-			// short variable declaration; variable scope starts after the range clause
-			// (the for loop opens a new scope, so variables on the lhs never redeclare
-			// previously declared variables)
+			// short variable declaration
 			var vars []*Var
 			for i, lhs := range lhs {
 				if lhs == nil {
@@ -904,12 +905,8 @@
 
 			// declare variables
 			if len(vars) > 0 {
-				scopePos := s.X.End()
+				scopePos := s.Body.Pos()
 				for _, obj := range vars {
-					// spec: "The scope of a constant or variable identifier declared inside
-					// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
-					// for short variable declarations) and ends at the end of the innermost
-					// containing block."
 					check.declare(check.scope, nil /* recordDef already called */, obj, scopePos)
 				}
 			} else {
diff --git a/libgo/go/go/types/subst.go b/libgo/go/go/types/subst.go
index 53247a3..4b4a0f4 100644
--- a/libgo/go/go/types/subst.go
+++ b/libgo/go/go/types/subst.go
@@ -160,7 +160,10 @@
 		methods, mcopied := subst.funcList(t.methods)
 		embeddeds, ecopied := subst.typeList(t.embeddeds)
 		if mcopied || ecopied {
-			iface := &Interface{embeddeds: embeddeds, implicit: t.implicit, complete: t.complete}
+			iface := subst.check.newInterface()
+			iface.embeddeds = embeddeds
+			iface.implicit = t.implicit
+			iface.complete = t.complete
 			// If we've changed the interface type, we may need to replace its
 			// receiver if the receiver type is the original interface. Receivers of
 			// *Named type are replaced during named type expansion.
diff --git a/libgo/go/go/types/termlist.go b/libgo/go/go/types/termlist.go
index c4ab0e0..94e49ca 100644
--- a/libgo/go/go/types/termlist.go
+++ b/libgo/go/go/types/termlist.go
@@ -92,15 +92,6 @@
 	return rl
 }
 
-// If the type set represented by xl is specified by a single (non-𝓤) term,
-// singleType returns that type. Otherwise it returns nil.
-func (xl termlist) singleType() Type {
-	if nl := xl.norm(); len(nl) == 1 {
-		return nl[0].typ // if nl.isAll() then typ is nil, which is ok
-	}
-	return nil
-}
-
 // union returns the union xl ∪ yl.
 func (xl termlist) union(yl termlist) termlist {
 	return append(xl, yl...).norm()
diff --git a/libgo/go/go/types/termlist_test.go b/libgo/go/go/types/termlist_test.go
index dddca7a..f0d58ac 100644
--- a/libgo/go/go/types/termlist_test.go
+++ b/libgo/go/go/types/termlist_test.go
@@ -106,35 +106,6 @@
 	}
 }
 
-func TestTermlistSingleType(t *testing.T) {
-	// helper to deal with nil types
-	tstring := func(typ Type) string {
-		if typ == nil {
-			return "nil"
-		}
-		return typ.String()
-	}
-
-	for test, want := range map[string]string{
-		"∅":                 "nil",
-		"𝓤":                 "nil",
-		"int":               "int",
-		"myInt":             "myInt",
-		"~int":              "int",
-		"~int ∪ string":     "nil",
-		"~int ∪ myInt":      "int",
-		"∅ ∪ int":           "int",
-		"∅ ∪ ~int":          "int",
-		"∅ ∪ ~int ∪ string": "nil",
-	} {
-		xl := maketl(test)
-		got := tstring(xl.singleType())
-		if got != want {
-			t.Errorf("(%v).singleType() == %v; want %v", test, got, want)
-		}
-	}
-}
-
 func TestTermlistUnion(t *testing.T) {
 	for _, test := range []struct {
 		xl, yl, want string
diff --git a/libgo/go/go/types/testdata/examples/inference.go2 b/libgo/go/go/types/testdata/examples/inference.go2
index 70d393b..e59a544 100644
--- a/libgo/go/go/types/testdata/examples/inference.go2
+++ b/libgo/go/go/types/testdata/examples/inference.go2
@@ -78,7 +78,7 @@
 	related1(si, "foo" /* ERROR cannot use "foo" */ )
 }
 
-func related2[Elem any, Slice interface{~[]Elem}](e Elem, s Slice) {}
+func related2[Elem any, Slice interface{[]Elem}](e Elem, s Slice) {}
 
 func _() {
 	// related2 can be called with explicit instantiation.
@@ -109,16 +109,8 @@
 	related3[int, []int]()
 	related3[byte, List[byte]]()
 
-	// Alternatively, the 2nd type argument can be inferred
-	// from the first one through constraint type inference.
-	related3[int]()
-
-	// The inferred type is the core type of the Slice
-	// type parameter.
-	var _ []int = related3[int]()
-
-	// It is not the defined parameterized type List.
-	type anotherList []float32
-	var _ anotherList = related3[float32]() // valid
-	var _ anotherList = related3 /* ERROR cannot use .* \(value of type List\[float32\]\) as anotherList */ [float32, List[float32]]()
+	// The 2nd type argument cannot be inferred from the first
+	// one because there's two possible choices: []Elem and
+	// List[Elem].
+	related3 /* ERROR cannot infer Slice */ [int]()
 }
diff --git a/libgo/go/go/types/testdata/examples/methods.go2 b/libgo/go/go/types/testdata/examples/methods.go2
index 1d76d55..a46f789 100644
--- a/libgo/go/go/types/testdata/examples/methods.go2
+++ b/libgo/go/go/types/testdata/examples/methods.go2
@@ -35,7 +35,7 @@
 // style. In m3 below, int is the name of the local receiver type parameter
 // and it shadows the predeclared identifier int which then cannot be used
 // anymore as expected.
-// This is no different from locally redelaring a predeclared identifier
+// This is no different from locally re-declaring a predeclared identifier
 // and usually should be avoided. There are some notable exceptions; e.g.,
 // sometimes it makes sense to use the identifier "copy" which happens to
 // also be the name of a predeclared built-in function.
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue41124.go2 b/libgo/go/go/types/testdata/fixedbugs/issue41124.go2
index 7f55ba8..4550dd7 100644
--- a/libgo/go/go/types/testdata/fixedbugs/issue41124.go2
+++ b/libgo/go/go/types/testdata/fixedbugs/issue41124.go2
@@ -47,7 +47,7 @@
 }
 
 type _ struct{
-	I3 // ERROR interface is .* comparable
+	I3 // ERROR interface contains type constraints
 }
 
 // General composite types.
@@ -59,19 +59,19 @@
 	_ []I1 // ERROR interface is .* comparable
 	_ []I2 // ERROR interface contains type constraints
 
-	_ *I3 // ERROR interface is .* comparable
+	_ *I3 // ERROR interface contains type constraints
 	_ map[I1 /* ERROR interface is .* comparable */ ]I2 // ERROR interface contains type constraints
-	_ chan I3 // ERROR interface is .* comparable
+	_ chan I3 // ERROR interface contains type constraints
 	_ func(I1 /* ERROR interface is .* comparable */ )
 	_ func() I2 // ERROR interface contains type constraints
 )
 
 // Other cases.
 
-var _ = [...]I3 /* ERROR interface is .* comparable */ {}
+var _ = [...]I3 /* ERROR interface contains type constraints */ {}
 
 func _(x interface{}) {
-	_ = x.(I3 /* ERROR interface is .* comparable */ )
+	_ = x.(I3 /* ERROR interface contains type constraints */ )
 }
 
 type T1[_ any] struct{}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue45548.go2 b/libgo/go/go/types/testdata/fixedbugs/issue45548.go2
index b8ba0ad..01c9672 100644
--- a/libgo/go/go/types/testdata/fixedbugs/issue45548.go2
+++ b/libgo/go/go/types/testdata/fixedbugs/issue45548.go2
@@ -4,7 +4,7 @@
 
 package p
 
-func f[F interface{~*Q}, G interface{~*R}, Q, R any](q Q, r R) {}
+func f[F interface{*Q}, G interface{*R}, Q, R any](q Q, r R) {}
 
 func _() {
 	f[*float64, *int](1, 2)
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue51229.go2 b/libgo/go/go/types/testdata/fixedbugs/issue51229.go2
new file mode 100644
index 0000000..808b647
--- /dev/null
+++ b/libgo/go/go/types/testdata/fixedbugs/issue51229.go2
@@ -0,0 +1,164 @@
+// 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 p
+
+// Constraint type inference should be independent of the
+// ordering of the type parameter declarations. Try all
+// permutations in the test case below.
+// Permutations produced by https://go.dev/play/p/PHcZNGJTEBZ.
+
+func f00[S1 ~[]E1, S2 ~[]E2, E1 ~byte, E2 ~byte](S1, S2) {}
+func f01[S2 ~[]E2, S1 ~[]E1, E1 ~byte, E2 ~byte](S1, S2) {}
+func f02[E1 ~byte, S1 ~[]E1, S2 ~[]E2, E2 ~byte](S1, S2) {}
+func f03[S1 ~[]E1, E1 ~byte, S2 ~[]E2, E2 ~byte](S1, S2) {}
+func f04[S2 ~[]E2, E1 ~byte, S1 ~[]E1, E2 ~byte](S1, S2) {}
+func f05[E1 ~byte, S2 ~[]E2, S1 ~[]E1, E2 ~byte](S1, S2) {}
+func f06[E2 ~byte, S2 ~[]E2, S1 ~[]E1, E1 ~byte](S1, S2) {}
+func f07[S2 ~[]E2, E2 ~byte, S1 ~[]E1, E1 ~byte](S1, S2) {}
+func f08[S1 ~[]E1, E2 ~byte, S2 ~[]E2, E1 ~byte](S1, S2) {}
+func f09[E2 ~byte, S1 ~[]E1, S2 ~[]E2, E1 ~byte](S1, S2) {}
+func f10[S2 ~[]E2, S1 ~[]E1, E2 ~byte, E1 ~byte](S1, S2) {}
+func f11[S1 ~[]E1, S2 ~[]E2, E2 ~byte, E1 ~byte](S1, S2) {}
+func f12[S1 ~[]E1, E1 ~byte, E2 ~byte, S2 ~[]E2](S1, S2) {}
+func f13[E1 ~byte, S1 ~[]E1, E2 ~byte, S2 ~[]E2](S1, S2) {}
+func f14[E2 ~byte, S1 ~[]E1, E1 ~byte, S2 ~[]E2](S1, S2) {}
+func f15[S1 ~[]E1, E2 ~byte, E1 ~byte, S2 ~[]E2](S1, S2) {}
+func f16[E1 ~byte, E2 ~byte, S1 ~[]E1, S2 ~[]E2](S1, S2) {}
+func f17[E2 ~byte, E1 ~byte, S1 ~[]E1, S2 ~[]E2](S1, S2) {}
+func f18[E2 ~byte, E1 ~byte, S2 ~[]E2, S1 ~[]E1](S1, S2) {}
+func f19[E1 ~byte, E2 ~byte, S2 ~[]E2, S1 ~[]E1](S1, S2) {}
+func f20[S2 ~[]E2, E2 ~byte, E1 ~byte, S1 ~[]E1](S1, S2) {}
+func f21[E2 ~byte, S2 ~[]E2, E1 ~byte, S1 ~[]E1](S1, S2) {}
+func f22[E1 ~byte, S2 ~[]E2, E2 ~byte, S1 ~[]E1](S1, S2) {}
+func f23[S2 ~[]E2, E1 ~byte, E2 ~byte, S1 ~[]E1](S1, S2) {}
+
+type myByte byte
+
+func _(a []byte, b []myByte) {
+	f00(a, b)
+	f01(a, b)
+	f02(a, b)
+	f03(a, b)
+	f04(a, b)
+	f05(a, b)
+	f06(a, b)
+	f07(a, b)
+	f08(a, b)
+	f09(a, b)
+	f10(a, b)
+	f11(a, b)
+	f12(a, b)
+	f13(a, b)
+	f14(a, b)
+	f15(a, b)
+	f16(a, b)
+	f17(a, b)
+	f18(a, b)
+	f19(a, b)
+	f20(a, b)
+	f21(a, b)
+	f22(a, b)
+	f23(a, b)
+}
+
+// Constraint type inference may have to iterate.
+// Again, the order of the type parameters shouldn't matter.
+
+func g0[S ~[]E, M ~map[string]S, E any](m M) {}
+func g1[M ~map[string]S, S ~[]E, E any](m M) {}
+func g2[E any, S ~[]E, M ~map[string]S](m M) {}
+func g3[S ~[]E, E any, M ~map[string]S](m M) {}
+func g4[M ~map[string]S, E any, S ~[]E](m M) {}
+func g5[E any, M ~map[string]S, S ~[]E](m M) {}
+
+func _(m map[string][]byte) {
+	g0(m)
+	g1(m)
+	g2(m)
+	g3(m)
+	g4(m)
+	g5(m)
+}
+
+// Worst-case scenario.
+// There are 10 unknown type parameters. In each iteration of
+// constraint type inference we infer one more, from right to left.
+// Each iteration looks repeatedly at all 11 type parameters,
+// requiring a total of 10*11 = 110 iterations with the current
+// implementation. Pathological case.
+
+func h[K any, J ~*K, I ~*J, H ~*I, G ~*H, F ~*G, E ~*F, D ~*E, C ~*D, B ~*C, A ~*B](x A) {}
+
+func _(x **********int) {
+	h(x)
+}
+
+// Examples with channel constraints and tilde.
+
+func ch1[P chan<- int]() (_ P)           { return } // core(P) == chan<- int   (single type, no tilde)
+func ch2[P ~chan int]()                  { return } // core(P) == ~chan<- int  (tilde)
+func ch3[P chan E, E any](E)             { return } // core(P) == chan<- E     (single type, no tilde)
+func ch4[P chan E | ~chan<- E, E any](E) { return } // core(P) == ~chan<- E    (tilde)
+func ch5[P chan int | chan<- int]()      { return } // core(P) == chan<- int   (not a single type)
+
+func _() {
+	// P can be inferred as there's a single specific type and no tilde.
+	var _ chan int = ch1 /* ERROR cannot use ch1.*value of type chan<- int */ ()
+	var _ chan<- int = ch1()
+
+	// P cannot be inferred as there's a tilde.
+	ch2 /* ERROR cannot infer P */ ()
+	type myChan chan int
+	ch2[myChan]()
+
+	// P can be inferred as there's a single specific type and no tilde.
+	var e int
+	ch3(e)
+
+	// P cannot be inferred as there's more than one specific type and a tilde.
+	ch4 /* ERROR cannot infer P */ (e)
+	_ = ch4[chan int]
+
+	// P cannot be inferred as there's more than one specific type.
+	ch5 /* ERROR cannot infer P */ ()
+	ch5[chan<- int]()
+}
+
+// test case from issue
+
+func equal[M1 ~map[K1]V1, M2 ~map[K2]V2, K1, K2 ~uint32, V1, V2 ~string](m1 M1, m2 M2) bool {
+	if len(m1) != len(m2) {
+		return false
+	}
+	for k, v1 := range m1 {
+		if v2, ok := m2[K2(k)]; !ok || V2(v1) != v2 {
+			return false
+		}
+	}
+	return true
+}
+
+func equalFixed[K1, K2 ~uint32, V1, V2 ~string](m1 map[K1]V1, m2 map[K2]V2) bool {
+	if len(m1) != len(m2) {
+		return false
+	}
+	for k, v1 := range m1 {
+		if v2, ok := m2[K2(k)]; !ok || v1 != V1(v2) {
+			return false
+		}
+	}
+	return true
+}
+
+type (
+	someNumericID uint32
+	someStringID  string
+)
+
+func _() {
+	foo := map[uint32]string{10: "bar"}
+	bar := map[someNumericID]someStringID{10: "bar"}
+	equal(foo, bar)
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue51232.go2 b/libgo/go/go/types/testdata/fixedbugs/issue51232.go2
new file mode 100644
index 0000000..3fa6a05
--- /dev/null
+++ b/libgo/go/go/types/testdata/fixedbugs/issue51232.go2
@@ -0,0 +1,30 @@
+// 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 p
+
+type RC[RG any] interface {
+	~[]RG
+}
+
+type Fn[RCT RC[RG], RG any] func(RCT)
+
+type F[RCT RC[RG], RG any] interface {
+	Fn() Fn /* ERROR got 1 arguments */ [RCT]
+}
+
+type concreteF[RCT RC[RG], RG any] struct {
+	makeFn func() Fn /* ERROR got 1 arguments */ [RCT]
+}
+
+func (c *concreteF[RCT, RG]) Fn() Fn /* ERROR got 1 arguments */ [RCT] {
+	return c.makeFn()
+}
+
+func NewConcrete[RCT RC[RG], RG any](Rc RCT) F /* ERROR got 1 arguments */ [RCT] {
+	// TODO(rfindley): eliminate the duplicate error below.
+	return & /* ERROR cannot use .* as F\[RCT\] */ concreteF /* ERROR got 1 arguments */ [RCT]{
+		makeFn: nil,
+	}
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue51233.go2 b/libgo/go/go/types/testdata/fixedbugs/issue51233.go2
new file mode 100644
index 0000000..9c15028
--- /dev/null
+++ b/libgo/go/go/types/testdata/fixedbugs/issue51233.go2
@@ -0,0 +1,27 @@
+// 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 p
+
+// As of issue #51527, type-type inference has been disabled.
+
+type RC[RG any] interface {
+	~[]RG
+}
+
+type Fn[RCT RC[RG], RG any] func(RCT)
+
+type FFn[RCT RC[RG], RG any] func() Fn /* ERROR got 1 arguments */ [RCT]
+
+type F[RCT RC[RG], RG any] interface {
+	Fn() Fn /* ERROR got 1 arguments */ [RCT]
+}
+
+type concreteF[RCT RC[RG], RG any] struct {
+	makeFn FFn /* ERROR got 1 arguments */ [RCT]
+}
+
+func (c *concreteF[RCT, RG]) Fn() Fn /* ERROR got 1 arguments */ [RCT] {
+	return c.makeFn()
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue51257.go2 b/libgo/go/go/types/testdata/fixedbugs/issue51257.go2
new file mode 100644
index 0000000..8a3eb32
--- /dev/null
+++ b/libgo/go/go/types/testdata/fixedbugs/issue51257.go2
@@ -0,0 +1,46 @@
+// 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 p
+
+func f[_ comparable]() {}
+
+type S1 struct{ x int }
+type S2 struct{ x any }
+type S3 struct{ x [10]interface{ m() } }
+
+func _[P1 comparable, P2 S2]() {
+	_ = f[S1]
+	_ = f[S2 /* ERROR S2 does not implement comparable */ ]
+	_ = f[S3 /* ERROR S3 does not implement comparable */ ]
+
+	type L1 struct { x P1 }
+	type L2 struct { x P2 }
+	_ = f[L1]
+	_ = f[L2 /* ERROR L2 does not implement comparable */ ]
+}
+
+
+// example from issue
+
+type Set[T comparable] map[T]struct{}
+
+func NewSetFromSlice[T comparable](items []T) *Set[T] {
+	s := Set[T]{}
+
+	for _, item := range items {
+		s[item] = struct{}{}
+	}
+
+	return &s
+}
+
+type T struct{ x any }
+
+func main() {
+	NewSetFromSlice /* ERROR T does not implement comparable */ ([]T{
+		{"foo"},
+		{5},
+	})
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue51335.go2 b/libgo/go/go/types/testdata/fixedbugs/issue51335.go2
new file mode 100644
index 0000000..0b5a1af
--- /dev/null
+++ b/libgo/go/go/types/testdata/fixedbugs/issue51335.go2
@@ -0,0 +1,16 @@
+// 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 p
+
+type S1 struct{}
+type S2 struct{}
+
+func _[P *S1|*S2]() {
+	_= []P{{ /* ERROR invalid composite literal element type P: no core type */ }}
+}
+
+func _[P *S1|S1]() {
+	_= []P{{ /* ERROR invalid composite literal element type P: no core type */ }}
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue51339.go2 b/libgo/go/go/types/testdata/fixedbugs/issue51339.go2
new file mode 100644
index 0000000..38f8610
--- /dev/null
+++ b/libgo/go/go/types/testdata/fixedbugs/issue51339.go2
@@ -0,0 +1,18 @@
+// 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.
+
+// This file is tested when running "go test -run Manual"
+// without source arguments. Use for one-off debugging.
+
+package p
+
+type T[P any, B *P] struct{}
+
+func (T /* ERROR cannot use generic type */ ) m0() {}
+
+// TODO(rfindley): eliminate the duplicate errors here.
+func (/* ERROR got 1 type parameter, but receiver base type declares 2 */ T /* ERROR got 1 arguments but 2 type parameters */ [_]) m1() {}
+func (T[_, _]) m2() {}
+// TODO(gri) this error is unfortunate (issue #51343)
+func (T /* ERROR got 3 arguments but 2 type parameters */ [_, _, _]) m3() {}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue51360.go b/libgo/go/go/types/testdata/fixedbugs/issue51360.go
new file mode 100644
index 0000000..fe3de04
--- /dev/null
+++ b/libgo/go/go/types/testdata/fixedbugs/issue51360.go
@@ -0,0 +1,13 @@
+// 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 p
+
+func _() {
+	len.Println /* ERROR cannot select on len */
+	len.Println /* ERROR cannot select on len */ ()
+	_ = len.Println /* ERROR cannot select on len */
+	_ = len /* ERROR cannot index len */ [0]
+	_ = *len /* ERROR cannot indirect len */
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue51376.go2 b/libgo/go/go/types/testdata/fixedbugs/issue51376.go2
new file mode 100644
index 0000000..d51607b
--- /dev/null
+++ b/libgo/go/go/types/testdata/fixedbugs/issue51376.go2
@@ -0,0 +1,24 @@
+// 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 p
+
+type Map map[string]int
+
+func f[M ~map[K]V, K comparable, V any](M) {}
+func g[M map[K]V, K comparable, V any](M) {}
+
+func _[M1 ~map[K]V, M2 map[K]V, K comparable, V any]() {
+        var m1 M1
+        f(m1)
+        g /* ERROR M1 does not implement map\[K\]V */ (m1) // M1 has tilde
+
+        var m2 M2
+        f(m2)
+        g(m2) // M1 does not have tilde
+
+        var m3 Map
+        f(m3)
+        g /* ERROR Map does not implement map\[string\]int */ (m3) // M in g does not have tilde
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue51386.go2 b/libgo/go/go/types/testdata/fixedbugs/issue51386.go2
new file mode 100644
index 0000000..ef62239
--- /dev/null
+++ b/libgo/go/go/types/testdata/fixedbugs/issue51386.go2
@@ -0,0 +1,17 @@
+// 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 p
+
+type myString string
+
+func _[P ~string | ~[]byte | ~[]rune]() {
+	_ = P("")
+	const s myString = ""
+	_ = P(s)
+}
+
+func _[P myString]() {
+	_ = P("")
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue51437.go b/libgo/go/go/types/testdata/fixedbugs/issue51437.go
new file mode 100644
index 0000000..3762615
--- /dev/null
+++ b/libgo/go/go/types/testdata/fixedbugs/issue51437.go
@@ -0,0 +1,17 @@
+// 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 p
+
+type T struct{}
+
+func (T) m() []int { return nil }
+
+func f(x T) {
+	for _, x := range func() []int {
+		return x.m() // x declared in parameter list of f
+	}() {
+		_ = x // x declared by range clause
+	}
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue51472.go2 b/libgo/go/go/types/testdata/fixedbugs/issue51472.go2
new file mode 100644
index 0000000..3126770
--- /dev/null
+++ b/libgo/go/go/types/testdata/fixedbugs/issue51472.go2
@@ -0,0 +1,54 @@
+// 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 p
+
+func _[T comparable](x T) {
+        _ = x == x
+}
+
+func _[T interface{interface{comparable}}](x T) {
+        _ = x == x
+}
+
+func _[T interface{comparable; interface{comparable}}](x T) {
+        _ = x == x
+}
+
+func _[T interface{comparable; ~int}](x T) {
+        _ = x == x
+}
+
+func _[T interface{comparable; ~[]byte}](x T) {
+        _ = x /* ERROR cannot compare */ == x
+}
+
+// TODO(gri) The error message here should be better. See issue #51525.
+func _[T interface{comparable; ~int; ~string}](x T) {
+        _ = x /* ERROR cannot compare */ == x
+}
+
+// TODO(gri) The error message here should be better. See issue #51525.
+func _[T interface{~int; ~string}](x T) {
+        _ = x /* ERROR cannot compare */ == x
+}
+
+func _[T interface{comparable; interface{~int}; interface{int|float64}}](x T) {
+        _ = x == x
+}
+
+func _[T interface{interface{comparable; ~int}; interface{~float64; comparable; m()}}](x T) {
+        _ = x /* ERROR cannot compare */ == x
+}
+
+// test case from issue
+
+func f[T interface{comparable; []byte|string}](x T) {
+        _ = x == x
+}
+
+func _(s []byte) {
+	f /* ERROR \[\]byte does not implement interface{comparable; \[\]byte\|string} */ (s)
+        _ = f[[ /* ERROR does not implement */ ]byte]
+}
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue51509.go b/libgo/go/go/types/testdata/fixedbugs/issue51509.go
new file mode 100644
index 0000000..5ae4717
--- /dev/null
+++ b/libgo/go/go/types/testdata/fixedbugs/issue51509.go
@@ -0,0 +1,7 @@
+// 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 p
+
+type T /* ERROR illegal cycle */ T.x
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue51578.go2 b/libgo/go/go/types/testdata/fixedbugs/issue51578.go2
new file mode 100644
index 0000000..5c204ba
--- /dev/null
+++ b/libgo/go/go/types/testdata/fixedbugs/issue51578.go2
@@ -0,0 +1,17 @@
+// 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 p
+
+var _ = (*interface /* ERROR interface contains type constraints */ {int})(nil)
+
+// abbreviated test case from issue
+
+type TypeSet interface{ int | string }
+
+func _() {
+	f((*TypeSet /* ERROR interface contains type constraints */)(nil))
+}
+
+func f(any) {}
\ No newline at end of file
diff --git a/libgo/go/go/types/testdata/fixedbugs/issue51593.go2 b/libgo/go/go/types/testdata/fixedbugs/issue51593.go2
new file mode 100644
index 0000000..e06c39f
--- /dev/null
+++ b/libgo/go/go/types/testdata/fixedbugs/issue51593.go2
@@ -0,0 +1,13 @@
+// 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 p
+
+func f[P interface{ m(R) }, R any]() {}
+
+type T = interface { m(int) }
+
+func _() {
+	_ = f /* ERROR cannot infer R */ [T] // don't crash in type inference
+}
diff --git a/libgo/go/go/types/type.go b/libgo/go/go/types/type.go
index 323365a..1306375 100644
--- a/libgo/go/go/types/type.go
+++ b/libgo/go/go/types/type.go
@@ -7,9 +7,7 @@
 // A Type represents a type of Go.
 // All types implement the Type interface.
 type Type interface {
-	// Underlying returns the underlying type of a type
-	// w/o following forwarding chains. Only used by
-	// client packages.
+	// Underlying returns the underlying type of a type.
 	Underlying() Type
 
 	// String returns a string representation of a type.
diff --git a/libgo/go/go/types/typeparam.go b/libgo/go/go/types/typeparam.go
index 71e6861..40d96ac 100644
--- a/libgo/go/go/types/typeparam.go
+++ b/libgo/go/go/types/typeparam.go
@@ -30,11 +30,13 @@
 // or Signature type by calling SetTypeParams. Setting a type parameter on more
 // than one type will result in a panic.
 //
-// The constraint argument can be nil, and set later via SetConstraint.
+// The constraint argument can be nil, and set later via SetConstraint. If the
+// constraint is non-nil, it must be fully defined.
 func NewTypeParam(obj *TypeName, constraint Type) *TypeParam {
 	return (*Checker)(nil).newTypeParam(obj, constraint)
 }
 
+// check may be nil
 func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam {
 	// Always increment lastID, even if it is not used.
 	id := nextID()
@@ -49,9 +51,7 @@
 	// iface may mutate typ.bound, so we must ensure that iface() is called
 	// at least once before the resulting TypeParam escapes.
 	if check != nil {
-		check.later(func() {
-			typ.iface()
-		})
+		check.needsCleanup(typ)
 	} else if constraint != nil {
 		typ.iface()
 	}
@@ -74,8 +74,10 @@
 
 // SetConstraint sets the type constraint for t.
 //
-// SetConstraint should not be called concurrently, but once SetConstraint
-// returns the receiver t is safe for concurrent use.
+// It must be called by users of NewTypeParam after the bound's underlying is
+// fully defined, and before using the type parameter in any way other than to
+// form other types. Once SetConstraint returns the receiver, t is safe for
+// concurrent use.
 func (t *TypeParam) SetConstraint(bound Type) {
 	if bound == nil {
 		panic("nil constraint")
@@ -95,9 +97,12 @@
 // ----------------------------------------------------------------------------
 // Implementation
 
+func (t *TypeParam) cleanup() {
+	t.iface()
+	t.check = nil
+}
+
 // iface returns the constraint interface of t.
-// TODO(gri) If we make tparamIsIface the default, this should be renamed to under
-//           (similar to Named.under).
 func (t *TypeParam) iface() *Interface {
 	bound := t.bound
 
@@ -138,16 +143,6 @@
 	return ityp
 }
 
-// singleType returns the single type of the type parameter constraint; or nil.
-func (t *TypeParam) singleType() Type {
-	return t.iface().typeSet().singleType()
-}
-
-// hasTerms reports whether the type parameter constraint has specific type terms.
-func (t *TypeParam) hasTerms() bool {
-	return t.iface().typeSet().hasTerms()
-}
-
 // is calls f with the specific type terms of t's constraint and reports whether
 // all calls to f returned true. If there are no specific terms, is
 // returns the result of f(nil).
diff --git a/libgo/go/go/types/typeset.go b/libgo/go/go/types/typeset.go
index e1f7301..6603383 100644
--- a/libgo/go/go/types/typeset.go
+++ b/libgo/go/go/types/typeset.go
@@ -15,18 +15,25 @@
 // API
 
 // A _TypeSet represents the type set of an interface.
+// Because of existing language restrictions, methods can be "factored out"
+// from the terms. The actual type set is the intersection of the type set
+// implied by the methods and the type set described by the terms and the
+// comparable bit. To test whether a type is included in a type set
+// ("implements" relation), the type must implement all methods _and_ be
+// an element of the type set described by the terms and the comparable bit.
+// If the term list describes the set of all types and comparable is true,
+// only comparable types are meant; in all other cases comparable is false.
 type _TypeSet struct {
-	comparable bool // if set, the interface is or embeds comparable
-	// TODO(gri) consider using a set for the methods for faster lookup
-	methods []*Func  // all methods of the interface; sorted by unique ID
-	terms   termlist // type terms of the type set
+	methods    []*Func  // all methods of the interface; sorted by unique ID
+	terms      termlist // type terms of the type set
+	comparable bool     // invariant: !comparable || terms.isAll()
 }
 
 // IsEmpty reports whether type set s is the empty set.
 func (s *_TypeSet) IsEmpty() bool { return s.terms.isEmpty() }
 
 // IsAll reports whether type set s is the set of all types (corresponding to the empty interface).
-func (s *_TypeSet) IsAll() bool { return !s.comparable && len(s.methods) == 0 && s.terms.isAll() }
+func (s *_TypeSet) IsAll() bool { return s.IsMethodSet() && len(s.methods) == 0 }
 
 // IsMethodSet reports whether the interface t is fully described by its method set.
 func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isAll() }
@@ -37,17 +44,10 @@
 		return s.comparable
 	}
 	return s.is(func(t *term) bool {
-		return t != nil && comparable(t.typ, seen, nil)
+		return t != nil && comparable(t.typ, false, seen, nil)
 	})
 }
 
-// TODO(gri) IsTypeSet is not a great name for this predicate. Find a better one.
-
-// IsTypeSet reports whether the type set s is represented by a finite set of underlying types.
-func (s *_TypeSet) IsTypeSet() bool {
-	return !s.comparable && len(s.methods) == 0
-}
-
 // NumMethods returns the number of methods available.
 func (s *_TypeSet) NumMethods() int { return len(s.methods) }
 
@@ -101,9 +101,6 @@
 // hasTerms reports whether the type set has specific type terms.
 func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() }
 
-// singleType returns the single type in s if there is exactly one; otherwise the result is nil.
-func (s *_TypeSet) singleType() Type { return s.terms.singleType() }
-
 // subsetOf reports whether s1 ⊆ s2.
 func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) }
 
@@ -220,12 +217,12 @@
 
 	var todo []*Func
 	var seen objset
-	var methods []*Func
+	var allMethods []*Func
 	mpos := make(map[*Func]token.Pos) // method specification or method embedding position, for good error messages
 	addMethod := func(pos token.Pos, m *Func, explicit bool) {
 		switch other := seen.insert(m); {
 		case other == nil:
-			methods = append(methods, m)
+			allMethods = append(allMethods, m)
 			mpos[m] = pos
 		case explicit:
 			if check == nil {
@@ -260,7 +257,8 @@
 	}
 
 	// collect embedded elements
-	var allTerms = allTermlist
+	allTerms := allTermlist
+	allComparable := false
 	for i, typ := range ityp.embeddeds {
 		// The embedding position is nil for imported interfaces
 		// and also for interface copies after substitution (but
@@ -269,6 +267,7 @@
 		if ityp.embedPos != nil {
 			pos = (*ityp.embedPos)[i]
 		}
+		var comparable bool
 		var terms termlist
 		switch u := under(typ).(type) {
 		case *Interface:
@@ -280,9 +279,7 @@
 				check.errorf(atPos(pos), _UnsupportedFeature, "embedding constraint interface %s requires go1.18 or later", typ)
 				continue
 			}
-			if tset.comparable {
-				ityp.tset.comparable = true
-			}
+			comparable = tset.comparable
 			for _, m := range tset.methods {
 				addMethod(pos, m, false) // use embedding position pos rather than m.pos
 			}
@@ -296,6 +293,8 @@
 			if tset == &invalidTypeSet {
 				continue // ignore invalid unions
 			}
+			assert(!tset.comparable)
+			assert(len(tset.methods) == 0)
 			terms = tset.terms
 		default:
 			if u == Typ[Invalid] {
@@ -307,11 +306,11 @@
 			}
 			terms = termlist{{false, typ}}
 		}
-		// The type set of an interface is the intersection
-		// of the type sets of all its elements.
-		// Intersection cannot produce longer termlists and
-		// thus cannot overflow.
-		allTerms = allTerms.intersect(terms)
+
+		// The type set of an interface is the intersection of the type sets of all its elements.
+		// Due to language restrictions, only embedded interfaces can add methods, they are handled
+		// separately. Here we only need to intersect the term lists and comparable bits.
+		allTerms, allComparable = intersectTermLists(allTerms, allComparable, terms, comparable)
 	}
 	ityp.embedPos = nil // not needed anymore (errors have been reported)
 
@@ -324,15 +323,46 @@
 		}
 	}
 
-	if methods != nil {
-		sort.Sort(byUniqueMethodName(methods))
-		ityp.tset.methods = methods
+	ityp.tset.comparable = allComparable
+	if len(allMethods) != 0 {
+		sortMethods(allMethods)
+		ityp.tset.methods = allMethods
 	}
 	ityp.tset.terms = allTerms
 
 	return ityp.tset
 }
 
+// TODO(gri) The intersectTermLists function belongs to the termlist implementation.
+//           The comparable type set may also be best represented as a term (using
+//           a special type).
+
+// intersectTermLists computes the intersection of two term lists and respective comparable bits.
+// xcomp, ycomp are valid only if xterms.isAll() and yterms.isAll() respectively.
+func intersectTermLists(xterms termlist, xcomp bool, yterms termlist, ycomp bool) (termlist, bool) {
+	terms := xterms.intersect(yterms)
+	// If one of xterms or yterms is marked as comparable,
+	// the result must only include comparable types.
+	comp := xcomp || ycomp
+	if comp && !terms.isAll() {
+		// only keep comparable terms
+		i := 0
+		for _, t := range terms {
+			assert(t.typ != nil)
+			if Comparable(t.typ) {
+				terms[i] = t
+				i++
+			}
+		}
+		terms = terms[:i]
+		if !terms.isAll() {
+			comp = false
+		}
+	}
+	assert(!comp || terms.isAll()) // comparable invariant
+	return terms, comp
+}
+
 func sortMethods(list []*Func) {
 	sort.Sort(byUniqueMethodName(list))
 }
diff --git a/libgo/go/go/types/typeset_test.go b/libgo/go/go/types/typeset_test.go
index 1c0eece..2bbe611 100644
--- a/libgo/go/go/types/typeset_test.go
+++ b/libgo/go/go/types/typeset_test.go
@@ -26,9 +26,9 @@
 		"{int; string}": "∅",
 
 		"{comparable}":              "{comparable}",
-		"{comparable; int}":         "{comparable; int}",
-		"{~int; comparable}":        "{comparable; ~int}",
-		"{int|string; comparable}":  "{comparable; int ∪ string}",
+		"{comparable; int}":         "{int}",
+		"{~int; comparable}":        "{~int}",
+		"{int|string; comparable}":  "{int ∪ string}",
 		"{comparable; int; string}": "∅",
 
 		"{m()}":                         "{func (p.T).m()}",
@@ -38,8 +38,8 @@
 		"{m1(); comparable; m2() int }": "{comparable; func (p.T).m1(); func (p.T).m2() int}",
 		"{comparable; error}":           "{comparable; func (error).Error() string}",
 
-		"{m(); comparable; int|float32|string}": "{comparable; func (p.T).m(); int ∪ float32 ∪ string}",
-		"{m1(); int; m2(); comparable }":        "{comparable; func (p.T).m1(); func (p.T).m2(); int}",
+		"{m(); comparable; int|float32|string}": "{func (p.T).m(); int ∪ float32 ∪ string}",
+		"{m1(); int; m2(); comparable }":        "{func (p.T).m1(); func (p.T).m2(); int}",
 
 		"{E}; type E interface{}":           "𝓤",
 		"{E}; type E interface{int;string}": "∅",
diff --git a/libgo/go/go/types/typexpr.go b/libgo/go/go/types/typexpr.go
index db6a904..5bb2d8f 100644
--- a/libgo/go/go/types/typexpr.go
+++ b/libgo/go/go/types/typexpr.go
@@ -144,10 +144,16 @@
 // constraint interface.
 func (check *Checker) varType(e ast.Expr) Type {
 	typ := check.definedType(e, nil)
+	check.validVarType(e, typ)
+	return typ
+}
 
+// validVarType reports an error if typ is a constraint interface.
+// The expression e is used for error reporting, if any.
+func (check *Checker) validVarType(e ast.Expr, typ Type) {
 	// If we have a type parameter there's nothing to do.
 	if isTypeParam(typ) {
-		return typ
+		return
 	}
 
 	// We don't want to call under() or complete interfaces while we are in
@@ -165,8 +171,6 @@
 			}
 		}
 	})
-
-	return typ
 }
 
 // definedType is like typ but also accepts a type name def.
@@ -254,7 +258,7 @@
 
 	case *ast.SelectorExpr:
 		var x operand
-		check.selector(&x, e)
+		check.selector(&x, e, def)
 
 		switch x.mode {
 		case typexpr:
@@ -323,7 +327,7 @@
 		return typ
 
 	case *ast.InterfaceType:
-		typ := new(Interface)
+		typ := check.newInterface()
 		def.setUnderlying(typ)
 		if def != nil {
 			typ.obj = def.obj
@@ -415,10 +419,14 @@
 	// evaluate arguments
 	targs := check.typeList(ix.Indices)
 	if targs == nil {
-		def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation
+		def.setUnderlying(Typ[Invalid]) // avoid errors later due to lazy instantiation
 		return Typ[Invalid]
 	}
 
+	// enableTypeTypeInference controls whether to infer missing type arguments
+	// using constraint type inference. See issue #51527.
+	const enableTypeTypeInference = false
+
 	// create the instance
 	ctxt := check.bestContext(nil)
 	h := ctxt.instanceHash(orig, targs)
@@ -438,19 +446,18 @@
 	def.setUnderlying(inst)
 
 	inst.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, *methodList) {
-		tparams := orig.TypeParams().list()
+		tparams := n.orig.TypeParams().list()
 
-		inferred := targs
-		if len(targs) < len(tparams) {
+		targs := n.targs.list()
+		if enableTypeTypeInference && len(targs) < len(tparams) {
 			// If inference fails, len(inferred) will be 0, and inst.underlying will
 			// be set to Typ[Invalid] in expandNamed.
-			inferred = check.infer(ix.Orig, tparams, targs, nil, nil)
+			inferred := check.infer(ix.Orig, tparams, targs, nil, nil)
 			if len(inferred) > len(targs) {
-				inst.targs = newTypeList(inferred)
+				n.targs = newTypeList(inferred)
 			}
 		}
 
-		check.recordInstance(ix.Orig, inferred, inst)
 		return expandNamed(ctxt, n, pos)
 	}
 
@@ -463,6 +470,7 @@
 		// Since check is non-nil, we can still mutate inst. Unpinning the resolver
 		// frees some memory.
 		inst.resolver = nil
+		check.recordInstance(ix.Orig, inst.TypeArgs().list(), inst)
 
 		if check.validateTArgLen(pos, inst.tparams.Len(), inst.targs.Len()) {
 			if i, err := check.verify(pos, inst.tparams.list(), inst.targs.list()); err != nil {
diff --git a/libgo/go/go/types/unify.go b/libgo/go/go/types/unify.go
index ac904d6..7b9aeee 100644
--- a/libgo/go/go/types/unify.go
+++ b/libgo/go/go/types/unify.go
@@ -247,6 +247,17 @@
 	}
 }
 
+// unknowns returns the number of type parameters for which no type has been set yet.
+func (d *tparamsList) unknowns() int {
+	n := 0
+	for _, ti := range d.indices {
+		if ti <= 0 {
+			n++
+		}
+	}
+	return n
+}
+
 // types returns the list of inferred types (via unification) for the type parameters
 // described by d, and an index. If all types were inferred, the returned index is < 0.
 // Otherwise, it is the index of the first type parameter which couldn't be inferred;
@@ -349,12 +360,16 @@
 	if enableCoreTypeUnification && !u.exact {
 		if isTypeParam(x) && !hasName(y) {
 			// When considering the type parameter for unification
-			// we look at the adjusted core type (adjCoreType).
+			// we look at the adjusted core term (adjusted core type
+			// with tilde information).
 			// If the adjusted core type is a named type N; the
 			// corresponding core type is under(N). Since !u.exact
 			// and y doesn't have a name, unification will end up
 			// comparing under(N) to y, so we can just use the core
-			// type instead. Optimization.
+			// type instead. And we can ignore the tilde because we
+			// already look at the underlying types on both sides
+			// and we have known types on both sides.
+			// Optimization.
 			if cx := coreType(x); cx != nil {
 				if traceInference {
 					u.tracef("core %s ≡ %s", x, y)
diff --git a/libgo/go/go/types/union.go b/libgo/go/go/types/union.go
index 9c59279..8397d65 100644
--- a/libgo/go/go/types/union.go
+++ b/libgo/go/go/types/union.go
@@ -103,25 +103,27 @@
 
 				if !Identical(u, t.typ) {
 					check.errorf(tlist[i], _InvalidUnion, "invalid use of ~ (underlying type of %s is %s)", t.typ, u)
-					continue // don't report another error for t
+					continue
 				}
 			}
 
 			// Stand-alone embedded interfaces are ok and are handled by the single-type case
 			// in the beginning. Embedded interfaces with tilde are excluded above. If we reach
-			// here, we must have at least two terms in the union.
-			if f != nil && !f.typeSet().IsTypeSet() {
+			// here, we must have at least two terms in the syntactic term list (but not necessarily
+			// in the term list of the union's type set).
+			if f != nil {
+				tset := f.typeSet()
 				switch {
-				case f.typeSet().NumMethods() != 0:
+				case tset.NumMethods() != 0:
 					check.errorf(tlist[i], _InvalidUnion, "cannot use %s in union (%s contains methods)", t, t)
+					continue
 				case t.typ == universeComparable.Type():
 					check.error(tlist[i], _InvalidUnion, "cannot use comparable in union")
-				case f.typeSet().comparable:
+					continue
+				case tset.comparable:
 					check.errorf(tlist[i], _InvalidUnion, "cannot use %s in union (%s embeds comparable)", t, t)
-				default:
-					panic("not a type set but no methods and not comparable")
+					continue
 				}
-				continue // don't report another error for t
 			}
 
 			// Report overlapping (non-disjoint) terms such as
diff --git a/libgo/go/go/types/universe.go b/libgo/go/go/types/universe.go
index 3421634..303ada4 100644
--- a/libgo/go/go/types/universe.go
+++ b/libgo/go/go/types/universe.go
@@ -112,7 +112,7 @@
 		typ := NewNamed(obj, nil, nil)
 
 		// interface{} // marked as comparable
-		ityp := &Interface{obj: obj, complete: true, tset: &_TypeSet{true, nil, allTermlist}}
+		ityp := &Interface{obj: obj, complete: true, tset: &_TypeSet{nil, allTermlist, true}}
 
 		typ.SetUnderlying(ityp)
 		def(obj)
diff --git a/libgo/go/go/types/validtype.go b/libgo/go/go/types/validtype.go
index c4ec2f2..7d7029b 100644
--- a/libgo/go/go/types/validtype.go
+++ b/libgo/go/go/types/validtype.go
@@ -79,7 +79,7 @@
 			// would have reported a type cycle and couldn't have been
 			// imported in the first place.
 			assert(t.obj.pkg == check.pkg)
-			t.underlying = Typ[Invalid] // t is in the current package (no race possibilty)
+			t.underlying = Typ[Invalid] // t is in the current package (no race possibility)
 			// Find the starting point of the cycle and report it.
 			for i, tn := range path {
 				if tn == t.obj {
diff --git a/libgo/go/internal/fuzz/coverage.go b/libgo/go/internal/fuzz/coverage.go
index 3dee73b..88f98a1 100644
--- a/libgo/go/internal/fuzz/coverage.go
+++ b/libgo/go/internal/fuzz/coverage.go
@@ -66,6 +66,17 @@
 	return n
 }
 
+// isCoverageSubset returns true if all the base coverage bits are set in
+// snapshot
+func isCoverageSubset(base, snapshot []byte) bool {
+	for i, v := range base {
+		if v&snapshot[i] != v {
+			return false
+		}
+	}
+	return true
+}
+
 // hasCoverageBit returns true if snapshot has at least one bit set that is
 // also set in base.
 func hasCoverageBit(base, snapshot []byte) bool {
diff --git a/libgo/go/internal/fuzz/encoding.go b/libgo/go/internal/fuzz/encoding.go
index 2bfa02b..c95d9e0 100644
--- a/libgo/go/internal/fuzz/encoding.go
+++ b/libgo/go/internal/fuzz/encoding.go
@@ -10,7 +10,9 @@
 	"go/ast"
 	"go/parser"
 	"go/token"
+	"math"
 	"strconv"
+	"unicode/utf8"
 )
 
 // encVersion1 will be the first line of a file with version 1 encoding.
@@ -27,13 +29,64 @@
 	// instead of changing to byte and rune respectively.
 	for _, val := range vals {
 		switch t := val.(type) {
-		case int, int8, int16, int64, uint, uint16, uint32, uint64, float32, float64, bool:
+		case int, int8, int16, int64, uint, uint16, uint32, uint64, bool:
 			fmt.Fprintf(b, "%T(%v)\n", t, t)
+		case float32:
+			if math.IsNaN(float64(t)) && math.Float32bits(t) != math.Float32bits(float32(math.NaN())) {
+				// We encode unusual NaNs as hex values, because that is how users are
+				// likely to encounter them in literature about floating-point encoding.
+				// This allows us to reproduce fuzz failures that depend on the specific
+				// NaN representation (for float32 there are about 2^24 possibilities!),
+				// not just the fact that the value is *a* NaN.
+				//
+				// Note that the specific value of float32(math.NaN()) can vary based on
+				// whether the architecture represents signaling NaNs using a low bit
+				// (as is common) or a high bit (as commonly implemented on MIPS
+				// hardware before around 2012). We believe that the increase in clarity
+				// from identifying "NaN" with math.NaN() is worth the slight ambiguity
+				// from a platform-dependent value.
+				fmt.Fprintf(b, "math.Float32frombits(0x%x)\n", math.Float32bits(t))
+			} else {
+				// We encode all other values — including the NaN value that is
+				// bitwise-identical to float32(math.Nan()) — using the default
+				// formatting, which is equivalent to strconv.FormatFloat with format
+				// 'g' and can be parsed by strconv.ParseFloat.
+				//
+				// For an ordinary floating-point number this format includes
+				// sufficiently many digits to reconstruct the exact value. For positive
+				// or negative infinity it is the string "+Inf" or "-Inf". For positive
+				// or negative zero it is "0" or "-0". For NaN, it is the string "NaN".
+				fmt.Fprintf(b, "%T(%v)\n", t, t)
+			}
+		case float64:
+			if math.IsNaN(t) && math.Float64bits(t) != math.Float64bits(math.NaN()) {
+				fmt.Fprintf(b, "math.Float64frombits(0x%x)\n", math.Float64bits(t))
+			} else {
+				fmt.Fprintf(b, "%T(%v)\n", t, t)
+			}
 		case string:
 			fmt.Fprintf(b, "string(%q)\n", t)
 		case rune: // int32
-			fmt.Fprintf(b, "rune(%q)\n", t)
+			// Although rune and int32 are represented by the same type, only a subset
+			// of valid int32 values can be expressed as rune literals. Notably,
+			// negative numbers, surrogate halves, and values above unicode.MaxRune
+			// have no quoted representation.
+			//
+			// fmt with "%q" (and the corresponding functions in the strconv package)
+			// would quote out-of-range values to the Unicode replacement character
+			// instead of the original value (see https://go.dev/issue/51526), so
+			// they must be treated as int32 instead.
+			//
+			// We arbitrarily draw the line at UTF-8 validity, which biases toward the
+			// "rune" interpretation. (However, we accept either format as input.)
+			if utf8.ValidRune(t) {
+				fmt.Fprintf(b, "rune(%q)\n", t)
+			} else {
+				fmt.Fprintf(b, "int32(%v)\n", t)
+			}
 		case byte: // uint8
+			// For bytes, we arbitrarily prefer the character interpretation.
+			// (Every byte has a valid character encoding.)
 			fmt.Fprintf(b, "byte(%q)\n", t)
 		case []byte: // []uint8
 			fmt.Fprintf(b, "[]byte(%q)\n", t)
@@ -105,44 +158,78 @@
 		return []byte(s), nil
 	}
 
-	idType, ok := call.Fun.(*ast.Ident)
-	if !ok {
-		return nil, fmt.Errorf("expected []byte or primitive type")
-	}
-	if idType.Name == "bool" {
-		id, ok := arg.(*ast.Ident)
+	var idType *ast.Ident
+	if selector, ok := call.Fun.(*ast.SelectorExpr); ok {
+		xIdent, ok := selector.X.(*ast.Ident)
+		if !ok || xIdent.Name != "math" {
+			return nil, fmt.Errorf("invalid selector type")
+		}
+		switch selector.Sel.Name {
+		case "Float64frombits":
+			idType = &ast.Ident{Name: "float64-bits"}
+		case "Float32frombits":
+			idType = &ast.Ident{Name: "float32-bits"}
+		default:
+			return nil, fmt.Errorf("invalid selector type")
+		}
+	} else {
+		idType, ok = call.Fun.(*ast.Ident)
 		if !ok {
-			return nil, fmt.Errorf("malformed bool")
+			return nil, fmt.Errorf("expected []byte or primitive type")
 		}
-		if id.Name == "true" {
-			return true, nil
-		} else if id.Name == "false" {
-			return false, nil
-		} else {
-			return nil, fmt.Errorf("true or false required for type bool")
+		if idType.Name == "bool" {
+			id, ok := arg.(*ast.Ident)
+			if !ok {
+				return nil, fmt.Errorf("malformed bool")
+			}
+			if id.Name == "true" {
+				return true, nil
+			} else if id.Name == "false" {
+				return false, nil
+			} else {
+				return nil, fmt.Errorf("true or false required for type bool")
+			}
 		}
 	}
+
 	var (
 		val  string
 		kind token.Token
 	)
 	if op, ok := arg.(*ast.UnaryExpr); ok {
-		// Special case for negative numbers.
-		lit, ok := op.X.(*ast.BasicLit)
-		if !ok || (lit.Kind != token.INT && lit.Kind != token.FLOAT) {
+		switch lit := op.X.(type) {
+		case *ast.BasicLit:
+			if op.Op != token.SUB {
+				return nil, fmt.Errorf("unsupported operation on int/float: %v", op.Op)
+			}
+			// Special case for negative numbers.
+			val = op.Op.String() + lit.Value // e.g. "-" + "124"
+			kind = lit.Kind
+		case *ast.Ident:
+			if lit.Name != "Inf" {
+				return nil, fmt.Errorf("expected operation on int or float type")
+			}
+			if op.Op == token.SUB {
+				val = "-Inf"
+			} else {
+				val = "+Inf"
+			}
+			kind = token.FLOAT
+		default:
 			return nil, fmt.Errorf("expected operation on int or float type")
 		}
-		if op.Op != token.SUB {
-			return nil, fmt.Errorf("unsupported operation on int: %v", op.Op)
-		}
-		val = op.Op.String() + lit.Value // e.g. "-" + "124"
-		kind = lit.Kind
 	} else {
-		lit, ok := arg.(*ast.BasicLit)
-		if !ok {
+		switch lit := arg.(type) {
+		case *ast.BasicLit:
+			val, kind = lit.Value, lit.Kind
+		case *ast.Ident:
+			if lit.Name != "NaN" {
+				return nil, fmt.Errorf("literal value required for primitive type")
+			}
+			val, kind = "NaN", token.FLOAT
+		default:
 			return nil, fmt.Errorf("literal value required for primitive type")
 		}
-		val, kind = lit.Value, lit.Kind
 	}
 
 	switch typ := idType.Name; typ {
@@ -152,6 +239,14 @@
 		}
 		return strconv.Unquote(val)
 	case "byte", "rune":
+		if kind == token.INT {
+			switch typ {
+			case "rune":
+				return parseInt(val, typ)
+			case "byte":
+				return parseUint(val, typ)
+			}
+		}
 		if kind != token.CHAR {
 			return nil, fmt.Errorf("character literal required for byte/rune types")
 		}
@@ -191,6 +286,24 @@
 			return nil, fmt.Errorf("float or integer literal required for float64 type")
 		}
 		return strconv.ParseFloat(val, 64)
+	case "float32-bits":
+		if kind != token.INT {
+			return nil, fmt.Errorf("integer literal required for math.Float32frombits type")
+		}
+		bits, err := parseUint(val, "uint32")
+		if err != nil {
+			return nil, err
+		}
+		return math.Float32frombits(bits.(uint32)), nil
+	case "float64-bits":
+		if kind != token.FLOAT && kind != token.INT {
+			return nil, fmt.Errorf("integer literal required for math.Float64frombits type")
+		}
+		bits, err := parseUint(val, "uint64")
+		if err != nil {
+			return nil, err
+		}
+		return math.Float64frombits(bits.(uint64)), nil
 	default:
 		return nil, fmt.Errorf("expected []byte or primitive type")
 	}
@@ -200,18 +313,24 @@
 func parseInt(val, typ string) (any, error) {
 	switch typ {
 	case "int":
-		return strconv.Atoi(val)
+		// The int type may be either 32 or 64 bits. If 32, the fuzz tests in the
+		// corpus may include 64-bit values produced by fuzzing runs on 64-bit
+		// architectures. When running those tests, we implicitly wrap the values to
+		// fit in a regular int. (The test case is still “interesting”, even if the
+		// specific values of its inputs are platform-dependent.)
+		i, err := strconv.ParseInt(val, 0, 64)
+		return int(i), err
 	case "int8":
-		i, err := strconv.ParseInt(val, 10, 8)
+		i, err := strconv.ParseInt(val, 0, 8)
 		return int8(i), err
 	case "int16":
-		i, err := strconv.ParseInt(val, 10, 16)
+		i, err := strconv.ParseInt(val, 0, 16)
 		return int16(i), err
-	case "int32":
-		i, err := strconv.ParseInt(val, 10, 32)
+	case "int32", "rune":
+		i, err := strconv.ParseInt(val, 0, 32)
 		return int32(i), err
 	case "int64":
-		return strconv.ParseInt(val, 10, 64)
+		return strconv.ParseInt(val, 0, 64)
 	default:
 		panic("unreachable")
 	}
@@ -221,19 +340,19 @@
 func parseUint(val, typ string) (any, error) {
 	switch typ {
 	case "uint":
-		i, err := strconv.ParseUint(val, 10, 0)
+		i, err := strconv.ParseUint(val, 0, 64)
 		return uint(i), err
-	case "uint8":
-		i, err := strconv.ParseUint(val, 10, 8)
+	case "uint8", "byte":
+		i, err := strconv.ParseUint(val, 0, 8)
 		return uint8(i), err
 	case "uint16":
-		i, err := strconv.ParseUint(val, 10, 16)
+		i, err := strconv.ParseUint(val, 0, 16)
 		return uint16(i), err
 	case "uint32":
-		i, err := strconv.ParseUint(val, 10, 32)
+		i, err := strconv.ParseUint(val, 0, 32)
 		return uint32(i), err
 	case "uint64":
-		return strconv.ParseUint(val, 10, 64)
+		return strconv.ParseUint(val, 0, 64)
 	default:
 		panic("unreachable")
 	}
diff --git a/libgo/go/internal/fuzz/encoding_test.go b/libgo/go/internal/fuzz/encoding_test.go
index b429d42..8e3800e 100644
--- a/libgo/go/internal/fuzz/encoding_test.go
+++ b/libgo/go/internal/fuzz/encoding_test.go
@@ -5,85 +5,104 @@
 package fuzz
 
 import (
+	"math"
 	"strconv"
-	"strings"
 	"testing"
+	"unicode"
 )
 
 func TestUnmarshalMarshal(t *testing.T) {
 	var tests = []struct {
-		in string
-		ok bool
+		desc   string
+		in     string
+		reject bool
+		want   string // if different from in
 	}{
 		{
-			in: "int(1234)",
-			ok: false, // missing version
+			desc:   "missing version",
+			in:     "int(1234)",
+			reject: true,
 		},
 		{
+			desc: "malformed string",
 			in: `go test fuzz v1
 string("a"bcad")`,
-			ok: false, // malformed
+			reject: true,
 		},
 		{
+			desc: "empty value",
 			in: `go test fuzz v1
 int()`,
-			ok: false, // empty value
+			reject: true,
 		},
 		{
+			desc: "negative uint",
 			in: `go test fuzz v1
 uint(-32)`,
-			ok: false, // invalid negative uint
+			reject: true,
 		},
 		{
+			desc: "int8 too large",
 			in: `go test fuzz v1
 int8(1234456)`,
-			ok: false, // int8 too large
+			reject: true,
 		},
 		{
+			desc: "multiplication in int value",
 			in: `go test fuzz v1
 int(20*5)`,
-			ok: false, // expression in int value
+			reject: true,
 		},
 		{
+			desc: "double negation",
 			in: `go test fuzz v1
 int(--5)`,
-			ok: false, // expression in int value
+			reject: true,
 		},
 		{
+			desc: "malformed bool",
 			in: `go test fuzz v1
 bool(0)`,
-			ok: false, // malformed bool
+			reject: true,
 		},
 		{
+			desc: "malformed byte",
 			in: `go test fuzz v1
 byte('aa)`,
-			ok: false, // malformed byte
+			reject: true,
 		},
 		{
+			desc: "byte out of range",
 			in: `go test fuzz v1
 byte('☃')`,
-			ok: false, // byte out of range
+			reject: true,
 		},
 		{
+			desc: "extra newline",
 			in: `go test fuzz v1
-string("has final newline")
+string("has extra newline")
 `,
-			ok: true, // has final newline
+			want: `go test fuzz v1
+string("has extra newline")`,
 		},
 		{
+			desc: "trailing spaces",
 			in: `go test fuzz v1
 string("extra")
 []byte("spacing")  
     `,
-			ok: true, // extra spaces in the final newline
+			want: `go test fuzz v1
+string("extra")
+[]byte("spacing")`,
 		},
 		{
+			desc: "float types",
 			in: `go test fuzz v1
 float64(0)
 float32(0)`,
-			ok: true, // will be an integer literal since there is no decimal
 		},
 		{
+			desc: "various types",
 			in: `go test fuzz v1
 int(-23)
 int8(-2)
@@ -101,19 +120,112 @@
 string("hello\\xbd\\xb2=\\xbc ⌘")
 float64(-12.5)
 float32(2.5)`,
-			ok: true,
+		},
+		{
+			desc: "float edge cases",
+			// The two IEEE 754 bit patterns used for the math.Float{64,32}frombits
+			// encodings are non-math.NAN quiet-NaN values. Since they are not equal
+			// to math.NaN(), they should be re-encoded to their bit patterns. They
+			// are, respectively:
+			//   * math.Float64bits(math.NaN())+1
+			//   * math.Float32bits(float32(math.NaN()))+1
+			in: `go test fuzz v1
+float32(-0)
+float64(-0)
+float32(+Inf)
+float32(-Inf)
+float32(NaN)
+float64(+Inf)
+float64(-Inf)
+float64(NaN)
+math.Float64frombits(0x7ff8000000000002)
+math.Float32frombits(0x7fc00001)`,
+		},
+		{
+			desc: "int variations",
+			// Although we arbitrarily choose default integer bases (0 or 16), we may
+			// want to change those arbitrary choices in the future and should not
+			// break the parser. Verify that integers in the opposite bases still
+			// parse correctly.
+			in: `go test fuzz v1
+int(0x0)
+int32(0x41)
+int64(0xfffffffff)
+uint32(0xcafef00d)
+uint64(0xffffffffffffffff)
+uint8(0b0000000)
+byte(0x0)
+byte('\000')
+byte('\u0000')
+byte('\'')
+math.Float64frombits(9221120237041090562)
+math.Float32frombits(2143289345)`,
+			want: `go test fuzz v1
+int(0)
+rune('A')
+int64(68719476735)
+uint32(3405705229)
+uint64(18446744073709551615)
+byte('\x00')
+byte('\x00')
+byte('\x00')
+byte('\x00')
+byte('\'')
+math.Float64frombits(0x7ff8000000000002)
+math.Float32frombits(0x7fc00001)`,
+		},
+		{
+			desc: "rune validation",
+			in: `go test fuzz v1
+rune(0)
+rune(0x41)
+rune(-1)
+rune(0xfffd)
+rune(0xd800)
+rune(0x10ffff)
+rune(0x110000)
+`,
+			want: `go test fuzz v1
+rune('\x00')
+rune('A')
+int32(-1)
+rune('�')
+int32(55296)
+rune('\U0010ffff')
+int32(1114112)`,
+		},
+		{
+			desc: "int overflow",
+			in: `go test fuzz v1
+int(0x7fffffffffffffff)
+uint(0xffffffffffffffff)`,
+			want: func() string {
+				switch strconv.IntSize {
+				case 32:
+					return `go test fuzz v1
+int(-1)
+uint(4294967295)`
+				case 64:
+					return `go test fuzz v1
+int(9223372036854775807)
+uint(18446744073709551615)`
+				default:
+					panic("unreachable")
+				}
+			}(),
 		},
 	}
 	for _, test := range tests {
-		t.Run(test.in, func(t *testing.T) {
+		t.Run(test.desc, func(t *testing.T) {
 			vals, err := unmarshalCorpusFile([]byte(test.in))
-			if test.ok && err != nil {
-				t.Fatalf("unmarshal unexpected error: %v", err)
-			} else if !test.ok && err == nil {
-				t.Fatalf("unmarshal unexpected success")
+			if test.reject {
+				if err == nil {
+					t.Fatalf("unmarshal unexpected success")
+				}
+				return
 			}
-			if !test.ok {
-				return // skip the rest of the test
+			if err != nil {
+				t.Fatalf("unmarshal unexpected error: %v", err)
 			}
 			newB := marshalCorpusFile(vals...)
 			if err != nil {
@@ -122,9 +234,15 @@
 			if newB[len(newB)-1] != '\n' {
 				t.Error("didn't write final newline to corpus file")
 			}
-			before, after := strings.TrimSpace(test.in), strings.TrimSpace(string(newB))
-			if before != after {
-				t.Errorf("values changed after unmarshal then marshal\nbefore: %q\nafter:  %q", before, after)
+
+			want := test.want
+			if want == "" {
+				want = test.in
+			}
+			want += "\n"
+			got := string(newB)
+			if got != want {
+				t.Errorf("unexpected marshaled value\ngot:\n%s\nwant:\n%s", got, want)
 			}
 		})
 	}
@@ -170,3 +288,117 @@
 		})
 	}
 }
+
+func TestByteRoundTrip(t *testing.T) {
+	for x := 0; x < 256; x++ {
+		b1 := byte(x)
+		buf := marshalCorpusFile(b1)
+		vs, err := unmarshalCorpusFile(buf)
+		if err != nil {
+			t.Fatal(err)
+		}
+		b2 := vs[0].(byte)
+		if b2 != b1 {
+			t.Fatalf("unmarshaled %v, want %v:\n%s", b2, b1, buf)
+		}
+	}
+}
+
+func TestInt8RoundTrip(t *testing.T) {
+	for x := -128; x < 128; x++ {
+		i1 := int8(x)
+		buf := marshalCorpusFile(i1)
+		vs, err := unmarshalCorpusFile(buf)
+		if err != nil {
+			t.Fatal(err)
+		}
+		i2 := vs[0].(int8)
+		if i2 != i1 {
+			t.Fatalf("unmarshaled %v, want %v:\n%s", i2, i1, buf)
+		}
+	}
+}
+
+func FuzzFloat64RoundTrip(f *testing.F) {
+	f.Add(math.Float64bits(0))
+	f.Add(math.Float64bits(math.Copysign(0, -1)))
+	f.Add(math.Float64bits(math.MaxFloat64))
+	f.Add(math.Float64bits(math.SmallestNonzeroFloat64))
+	f.Add(math.Float64bits(math.NaN()))
+	f.Add(uint64(0x7FF0000000000001)) // signaling NaN
+	f.Add(math.Float64bits(math.Inf(1)))
+	f.Add(math.Float64bits(math.Inf(-1)))
+
+	f.Fuzz(func(t *testing.T, u1 uint64) {
+		x1 := math.Float64frombits(u1)
+
+		b := marshalCorpusFile(x1)
+		t.Logf("marshaled math.Float64frombits(0x%x):\n%s", u1, b)
+
+		xs, err := unmarshalCorpusFile(b)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if len(xs) != 1 {
+			t.Fatalf("unmarshaled %d values", len(xs))
+		}
+		x2 := xs[0].(float64)
+		u2 := math.Float64bits(x2)
+		if u2 != u1 {
+			t.Errorf("unmarshaled %v (bits 0x%x)", x2, u2)
+		}
+	})
+}
+
+func FuzzRuneRoundTrip(f *testing.F) {
+	f.Add(rune(-1))
+	f.Add(rune(0xd800))
+	f.Add(rune(0xdfff))
+	f.Add(rune(unicode.ReplacementChar))
+	f.Add(rune(unicode.MaxASCII))
+	f.Add(rune(unicode.MaxLatin1))
+	f.Add(rune(unicode.MaxRune))
+	f.Add(rune(unicode.MaxRune + 1))
+	f.Add(rune(-0x80000000))
+	f.Add(rune(0x7fffffff))
+
+	f.Fuzz(func(t *testing.T, r1 rune) {
+		b := marshalCorpusFile(r1)
+		t.Logf("marshaled rune(0x%x):\n%s", r1, b)
+
+		rs, err := unmarshalCorpusFile(b)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if len(rs) != 1 {
+			t.Fatalf("unmarshaled %d values", len(rs))
+		}
+		r2 := rs[0].(rune)
+		if r2 != r1 {
+			t.Errorf("unmarshaled rune(0x%x)", r2)
+		}
+	})
+}
+
+func FuzzStringRoundTrip(f *testing.F) {
+	f.Add("")
+	f.Add("\x00")
+	f.Add(string([]rune{unicode.ReplacementChar}))
+
+	f.Fuzz(func(t *testing.T, s1 string) {
+		b := marshalCorpusFile(s1)
+		t.Logf("marshaled %q:\n%s", s1, b)
+
+		rs, err := unmarshalCorpusFile(b)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if len(rs) != 1 {
+			t.Fatalf("unmarshaled %d values", len(rs))
+		}
+		s2 := rs[0].(string)
+		if s2 != s1 {
+			t.Errorf("unmarshaled %q", s2)
+		}
+	})
+}
diff --git a/libgo/go/internal/fuzz/worker.go b/libgo/go/internal/fuzz/worker.go
index e984ba7..6e4c4e2 100644
--- a/libgo/go/internal/fuzz/worker.go
+++ b/libgo/go/internal/fuzz/worker.go
@@ -800,6 +800,7 @@
 	if err != nil {
 		panic(err)
 	}
+	inpHash := sha256.Sum256(mem.valueCopy())
 	if args.Timeout != 0 {
 		var cancel func()
 		ctx, cancel = context.WithTimeout(ctx, args.Timeout)
@@ -811,12 +812,22 @@
 	success, err := ws.minimizeInput(ctx, vals, mem, args)
 	if success {
 		writeToMem(vals, mem)
+		outHash := sha256.Sum256(mem.valueCopy())
 		mem.header().rawInMem = false
 		resp.WroteToMem = true
 		if err != nil {
 			resp.Err = err.Error()
 		} else {
-			resp.CoverageData = coverageSnapshot
+			// If the values didn't change during minimization then coverageSnapshot is likely
+			// a dirty snapshot which represents the very last step of minimization, not the
+			// coverage for the initial input. In that case just return the coverage we were
+			// given initially, since it more accurately represents the coverage map for the
+			// input we are returning.
+			if outHash != inpHash {
+				resp.CoverageData = coverageSnapshot
+			} else {
+				resp.CoverageData = args.KeepCoverage
+			}
 		}
 	}
 	return resp
@@ -883,7 +894,8 @@
 			}
 			return true
 		}
-		if keepCoverage != nil && hasCoverageBit(keepCoverage, coverageSnapshot) {
+		// Minimization should preserve coverage bits.
+		if keepCoverage != nil && isCoverageSubset(keepCoverage, coverageSnapshot) {
 			return true
 		}
 		vals[args.Index] = prev
diff --git a/libgo/go/net/net.go b/libgo/go/net/net.go
index 77e54a9..d91e743 100644
--- a/libgo/go/net/net.go
+++ b/libgo/go/net/net.go
@@ -703,6 +703,12 @@
 	_ io.Reader   = (*Buffers)(nil)
 )
 
+// WriteTo writes contents of the buffers to w.
+//
+// WriteTo implements io.WriterTo for Buffers.
+//
+// WriteTo modifies the slice v as well as v[i] for 0 <= i < len(v),
+// but does not modify v[i][j] for any i, j.
 func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) {
 	if wv, ok := w.(buffersWriter); ok {
 		return wv.writeBuffers(v)
@@ -719,6 +725,12 @@
 	return n, nil
 }
 
+// Read from the buffers.
+//
+// Read implements io.Reader for Buffers.
+//
+// Read modifies the slice v as well as v[i] for 0 <= i < len(v),
+// but does not modify v[i][j] for any i, j.
 func (v *Buffers) Read(p []byte) (n int, err error) {
 	for len(p) > 0 && len(*v) > 0 {
 		n0 := copy(p, (*v)[0])
diff --git a/libgo/go/runtime/mfinal_test.go b/libgo/go/runtime/mfinal_test.go
index 81c924f..2eb60b9 100644
--- a/libgo/go/runtime/mfinal_test.go
+++ b/libgo/go/runtime/mfinal_test.go
@@ -45,6 +45,15 @@
 		{func(x *int) any { return Tintptr(x) }, func(v *int) { finalize(v) }},
 		{func(x *int) any { return (*Tint)(x) }, func(v *Tint) { finalize((*int)(v)) }},
 		{func(x *int) any { return (*Tint)(x) }, func(v Tinter) { finalize((*int)(v.(*Tint))) }},
+		// Test case for argument spill slot.
+		// If the spill slot was not counted for the frame size, it will (incorrectly) choose
+		// call32 as the result has (exactly) 32 bytes. When the argument actually spills,
+		// it clobbers the caller's frame (likely the return PC).
+		{func(x *int) any { return x }, func(v any) [4]int64 {
+			print() // force spill
+			finalize(v.(*int))
+			return [4]int64{}
+		}},
 	}
 
 	for i, tt := range finalizerTests {
diff --git a/libgo/go/runtime/testdata/testprogcgo/aprof.go b/libgo/go/runtime/testdata/testprogcgo/aprof.go
index c70d633..1687014 100644
--- a/libgo/go/runtime/testdata/testprogcgo/aprof.go
+++ b/libgo/go/runtime/testdata/testprogcgo/aprof.go
@@ -10,7 +10,7 @@
 // This is a regression test for issue 14599, where profiling fails when the
 // function is the first C function. Exported functions are the first C
 // functions, so we use an exported function. Exported functions are created in
-// lexigraphical order of source files, so this file is named aprof.go to
+// lexicographical order of source files, so this file is named aprof.go to
 // ensure its function is first.
 
 // extern void CallGoNop();
diff --git a/libgo/go/strings/builder.go b/libgo/go/strings/builder.go
index 547e52e..ba4df61 100644
--- a/libgo/go/strings/builder.go
+++ b/libgo/go/strings/builder.go
@@ -17,10 +17,9 @@
 	buf  []byte
 }
 
-// noescape hides a pointer from escape analysis.  noescape is
-// the identity function but escape analysis doesn't think the
-// output depends on the input. noescape is inlined and currently
-// compiles down to zero instructions.
+// noescape hides a pointer from escape analysis. It is the identity function
+// but escape analysis doesn't think the output depends on the input.
+// noescape is inlined and currently compiles down to zero instructions.
 // USE CAREFULLY!
 // This was copied from the runtime; see issues 23382 and 7921.
 //go:nosplit
diff --git a/libgo/go/syscall/syscall_unix_test.go b/libgo/go/syscall/syscall_unix_test.go
index 8bfbc93..9fed7c5 100644
--- a/libgo/go/syscall/syscall_unix_test.go
+++ b/libgo/go/syscall/syscall_unix_test.go
@@ -328,33 +328,6 @@
 	}
 }
 
-func TestRlimit(t *testing.T) {
-	var rlimit, zero syscall.Rlimit
-	if err := syscall.Getrlimit(syscall.RLIMIT_CPU, &rlimit); err != nil {
-		t.Fatalf("Getrlimit: save failed: %v", err)
-	}
-	if zero == rlimit {
-		t.Fatalf("Getrlimit: save failed: got zero value %#v", rlimit)
-	}
-	set := rlimit
-	set.Cur = set.Max - 1
-	if err := syscall.Setrlimit(syscall.RLIMIT_CPU, &set); err != nil {
-		t.Fatalf("Setrlimit: set failed: %#v %v", set, err)
-	}
-	var get syscall.Rlimit
-	if err := syscall.Getrlimit(syscall.RLIMIT_CPU, &get); err != nil {
-		t.Fatalf("Getrlimit: get failed: %v", err)
-	}
-	set = rlimit
-	set.Cur = set.Max - 1
-	if set != get {
-		t.Fatalf("Rlimit: change failed: wanted %#v got %#v", set, get)
-	}
-	if err := syscall.Setrlimit(syscall.RLIMIT_CPU, &rlimit); err != nil {
-		t.Fatalf("Setrlimit: restore failed: %#v %v", rlimit, err)
-	}
-}
-
 func TestSeekFailure(t *testing.T) {
 	_, err := syscall.Seek(-1, 0, io.SeekStart)
 	if err == nil {
diff --git a/libgo/merge.sh b/libgo/merge.sh
index 2ad0fe9..cd2510b 100755
--- a/libgo/merge.sh
+++ b/libgo/merge.sh
@@ -198,7 +198,7 @@
     libgofile=${libgotd}/$f
     merge ${name} ${oldfile} ${newfile} ${libgofile}
   done
-  (cd ${newtd} & git ls-files .) | while read f; do
+  (cd ${newtd} && git ls-files .) | while read f; do
     if test "`basename -- $f`" = ".gitignore"; then
       continue
     fi
diff --git a/libgo/misc/cgo/testsanitizers/asan_test.go b/libgo/misc/cgo/testsanitizers/asan_test.go
index 1b70bce..22dcf23 100644
--- a/libgo/misc/cgo/testsanitizers/asan_test.go
+++ b/libgo/misc/cgo/testsanitizers/asan_test.go
@@ -63,7 +63,7 @@
 					// sanitizer library needs a
 					// symbolizer program and can't find it.
 					const noSymbolizer = "external symbolizer"
-					// Check if -asan option can correctly print where the error occured.
+					// Check if -asan option can correctly print where the error occurred.
 					if tc.errorLocation != "" &&
 						!strings.Contains(out, tc.errorLocation) &&
 						!strings.Contains(out, noSymbolizer) &&