[dev.typeparams] all: merge master (4711bf3) into dev.typeparams

Conflicts:

- src/cmd/compile/internal/walk/builtin.go

  On dev.typeparams, CL 330194 changed OCHECKNIL to not require manual
  SetTypecheck(1) anymore; while on master, CL 331070 got rid of the
  OCHECKNIL altogether by moving the check into the runtime support
  functions.

- src/internal/buildcfg/exp.go

  On master, CL 331109 refactored the logic for parsing the
  GOEXPERIMENT string, so that it could be more easily reused by
  cmd/go; while on dev.typeparams, several CLs tweaked the regabi
  experiment defaults.

Merge List:

+ 2021-06-30 4711bf30e5 doc/go1.17: linkify "language changes" in the runtime section
+ 2021-06-30 ed56ea73e8 path/filepath: deflake TestEvalSymlinksAboveRoot on darwin
+ 2021-06-30 c080d0323b cmd/dist: pass -Wno-unknown-warning-option in swig_callback_lto
+ 2021-06-30 7d0e9e6e74 image/gif: fix typo in the comment (io.ReadByte -> io.ByteReader)
+ 2021-06-30 0fa3265fe1 os: change example to avoid deprecated function
+ 2021-06-30 d19a53338f image: add Uniform.RGBA64At and Rectangle.RGBA64At
+ 2021-06-30 c45e800e0c crypto/x509: don't fail on optional auth key id fields
+ 2021-06-29 f9d50953b9 net: fix failure of TestCVE202133195
+ 2021-06-29 e294b8a49e doc/go1.17: fix typo "MacOS" -> "macOS"
+ 2021-06-29 3463852b76 math/big: fix typo of comment (`BytesScanner` to `ByteScanner`)
+ 2021-06-29 fd4b587da3 cmd/compile: suppress details error for invalid variadic argument type
+ 2021-06-29 e2e05af6e1 cmd/internal/obj/arm64: fix an encoding error of CMPW instruction
+ 2021-06-28 4bb0847b08 cmd/compile,runtime: change unsafe.Slice((*T)(nil), 0) to return []T(nil)
+ 2021-06-28 1519271a93 spec: change unsafe.Slice((*T)(nil), 0) to return []T(nil)
+ 2021-06-28 5385e2386b runtime/internal/atomic: drop Cas64 pointer indirection in comments
+ 2021-06-28 956c81bfe6 cmd/go: add GOEXPERIMENT to `go env` output
+ 2021-06-28 a1d27269d6 cmd/go: prep for 'go env' refactoring
+ 2021-06-28 901510ed4e cmd/link/internal/ld: skip the windows ASLR test when CGO_ENABLED=0
+ 2021-06-28 361159c055 cmd/cgo: fix 'see gmp.go' to 'see doc.go'
+ 2021-06-27 c95464f0ea internal/buildcfg: refactor GOEXPERIMENT parsing code somewhat
+ 2021-06-25 ed01ceaf48 runtime/race: use race build tag on syso_test.go
+ 2021-06-25 d1916e5e84 go/types: in TestCheck/issues.src, import regexp/syntax instead of cmd/compile/internal/syntax
+ 2021-06-25 5160896c69 go/types: in TestStdlib, import from source instead of export data
+ 2021-06-25 d01bc571f7 runtime: make ncgocall a global counter

Change-Id: I1ce4a3b3ff7c824c67ad66dd27d9d5f1d25c0023
diff --git a/api/go1.17.txt b/api/go1.17.txt
index c5eb381..8e4c0f5 100644
--- a/api/go1.17.txt
+++ b/api/go1.17.txt
@@ -47,7 +47,9 @@
 pkg image, method (*Paletted) SetRGBA64(int, int, color.RGBA64)
 pkg image, method (*RGBA) RGBA64At(int, int) color.RGBA64
 pkg image, method (*RGBA) SetRGBA64(int, int, color.RGBA64)
+pkg image, method (*Uniform) RGBA64At(int, int) color.RGBA64
 pkg image, method (*YCbCr) RGBA64At(int, int) color.RGBA64
+pkg image, method (Rectangle) RGBA64At(int, int) color.RGBA64
 pkg image, type RGBA64Image interface { At, Bounds, ColorModel, RGBA64At }
 pkg image, type RGBA64Image interface, At(int, int) color.Color
 pkg image, type RGBA64Image interface, Bounds() Rectangle
diff --git a/doc/go1.17.html b/doc/go1.17.html
index 22896c8..66b4f48 100644
--- a/doc/go1.17.html
+++ b/doc/go1.17.html
@@ -401,7 +401,7 @@
 
 <p><!-- golang.org/issue/40724 -->
   Go 1.17 implements a new way of passing function arguments and results using
-  registers instead of the stack. This work is enabled for Linux, MacOS, and
+  registers instead of the stack. This work is enabled for Linux, macOS, and
   Windows on the 64-bit x86 architecture (the <code>linux/amd64</code>,
   <code>darwin/amd64</code>, <code>windows/amd64</code> ports). For a
   representative set of Go packages and programs, benchmarking has shown
@@ -811,8 +811,8 @@
     <p><!-- CL 311129 -->
       The concrete image types (<code>RGBA</code>, <code>Gray16</code> and so on)
       now implement a new <a href="/pkg/image/#RGBA64Image"><code>RGBA64Image</code></a>
-      interface. Those concrete types, other than the chroma-subsampling
-      related <code>YCbCr</code> and <code>NYCbCrA</code>, also now implement
+      interface. The concrete types that previously implemented
+      <a href="/pkg/image/draw/#Image"><code>draw.Image</code></a> now also implement
       <a href="/pkg/image/draw/#RGBA64Image"><code>draw.RGBA64Image</code></a>, a
       new interface in the <code>image/draw</code> package.
     </p>
@@ -993,7 +993,7 @@
       is no longer sufficient to guarantee that a call to
       <a href="/pkg/reflect/#Value.Convert"><code>Value.Convert</code></a> will not panic.
       It may panic when converting `[]T` to `*[N]T` if the slice's length is less than N.
-      See the language changes section above.
+      See the <a href="#language">language changes</a> section above.
     </p>
   </dd>
 </dl><!-- reflect -->
diff --git a/doc/go_spec.html b/doc/go_spec.html
index b59b37f..e060241 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
 <!--{
 	"Title": "The Go Programming Language Specification",
-	"Subtitle": "Version of Jun 22, 2021",
+	"Subtitle": "Version of Jun 28, 2021",
 	"Path": "/ref/spec"
 }-->
 
@@ -6790,10 +6790,16 @@
 </pre>
 
 <p>
+As a special case, if <code>ptr</code> is <code>nil</code> and <code>len</code> is zero,
+<code>Slice</code> returns <code>nil</code>.
+</p>
+
+<p>
 The <code>len</code> argument must be of integer type or an untyped <a href="#Constants">constant</a>.
 A constant <code>len</code> argument must be non-negative and <a href="#Representability">representable</a> by a value of type <code>int</code>;
 if it is an untyped constant it is given type <code>int</code>.
-If <code>ptr</code> is <code>nil</code> or <code>len</code> is negative at run time,
+At run time, if <code>len</code> is negative,
+or if <code>ptr</code> is <code>nil</code> and <code>len</code> is not zero,
 a <a href="#Run_time_panics">run-time panic</a> occurs.
 </p>
 
diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s
index 5f1e685..d8a20ed 100644
--- a/src/cmd/asm/internal/asm/testdata/arm64.s
+++ b/src/cmd/asm/internal/asm/testdata/arm64.s
@@ -89,7 +89,7 @@
 	CMP	R1<<33, R2
 	CMP	R22.SXTX, RSP                    // ffe336eb
 	CMP	$0x22220000, RSP                 // CMP $572653568, RSP   // 5b44a4d2ff633beb
-	CMPW	$0x22220000, RSP                 // CMPW $572653568, RSP  // 5b44a452ff633b6b
+	CMPW	$0x22220000, RSP                 // CMPW $572653568, RSP  // 5b44a452ff433b6b
 	CCMN	MI, ZR, R1, $4	                 // e44341ba
 	// MADD Rn,Rm,Ra,Rd
 	MADD	R1, R2, R3, R4                   // 6408019b
@@ -377,6 +377,7 @@
 	MOVD	$0x1000100010001000, RSP      // MOVD	$1152939097061330944, RSP   // ff8304b2
 	MOVW	$0x10001000, RSP              // MOVW	$268439552, RSP             // ff830432
 	ADDW	$0x10001000, R1               // ADDW	$268439552, R1              // fb83043221001b0b
+	ADDW	$0x22220000, RSP, R3          // ADDW	$572653568, RSP, R3         // 5b44a452e3433b0b
 
 // move a large constant to a Vd.
 	VMOVS	$0x80402010, V11                                      // VMOVS	$2151686160, V11
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index 03a662e..c6a0c52 100644
--- a/src/cmd/cgo/main.go
+++ b/src/cmd/cgo/main.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Cgo; see gmp.go for an overview.
+// Cgo; see doc.go for an overview.
 
 // TODO(rsc):
 //	Emit correct line number annotations.
diff --git a/src/cmd/compile/internal/typecheck/builtin.go b/src/cmd/compile/internal/typecheck/builtin.go
index 67a894c..833b17b 100644
--- a/src/cmd/compile/internal/typecheck/builtin.go
+++ b/src/cmd/compile/internal/typecheck/builtin.go
@@ -138,6 +138,7 @@
 	{"growslice", funcTag, 116},
 	{"unsafeslice", funcTag, 117},
 	{"unsafeslice64", funcTag, 118},
+	{"unsafeslicecheckptr", funcTag, 118},
 	{"memmove", funcTag, 119},
 	{"memclrNoHeapPointers", funcTag, 120},
 	{"memclrHasPointers", funcTag, 120},
@@ -341,8 +342,8 @@
 	typs[114] = newSig(params(typs[1], typs[15], typs[15], typs[7]), params(typs[7]))
 	typs[115] = types.NewSlice(typs[2])
 	typs[116] = newSig(params(typs[1], typs[115], typs[15]), params(typs[115]))
-	typs[117] = newSig(params(typs[1], typs[15]), nil)
-	typs[118] = newSig(params(typs[1], typs[22]), nil)
+	typs[117] = newSig(params(typs[1], typs[7], typs[15]), nil)
+	typs[118] = newSig(params(typs[1], typs[7], typs[22]), nil)
 	typs[119] = newSig(params(typs[3], typs[3], typs[5]), nil)
 	typs[120] = newSig(params(typs[7], typs[5]), nil)
 	typs[121] = newSig(params(typs[3], typs[3], typs[5]), params(typs[6]))
diff --git a/src/cmd/compile/internal/typecheck/builtin/runtime.go b/src/cmd/compile/internal/typecheck/builtin/runtime.go
index ebeaeae..2b29ea3 100644
--- a/src/cmd/compile/internal/typecheck/builtin/runtime.go
+++ b/src/cmd/compile/internal/typecheck/builtin/runtime.go
@@ -183,8 +183,9 @@
 func makeslice64(typ *byte, len int64, cap int64) unsafe.Pointer
 func makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer
 func growslice(typ *byte, old []any, cap int) (ary []any)
-func unsafeslice(typ *byte, len int)
-func unsafeslice64(typ *byte, len int64)
+func unsafeslice(typ *byte, ptr unsafe.Pointer, len int)
+func unsafeslice64(typ *byte, ptr unsafe.Pointer, len int64)
+func unsafeslicecheckptr(typ *byte, ptr unsafe.Pointer, len int64)
 
 func memmove(to *any, frm *any, length uintptr)
 func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)
diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go
index 5f9f8c6..d0aad5a 100644
--- a/src/cmd/compile/internal/typecheck/func.go
+++ b/src/cmd/compile/internal/typecheck/func.go
@@ -961,7 +961,14 @@
 	t := n.X.Type()
 	if !t.IsPtr() {
 		base.Errorf("first argument to unsafe.Slice must be pointer; have %L", t)
+	} else if t.Elem().NotInHeap() {
+		// TODO(mdempsky): This can be relaxed, but should only affect the
+		// Go runtime itself. End users should only see //go:notinheap
+		// types due to incomplete C structs in cgo, and those types don't
+		// have a meaningful size anyway.
+		base.Errorf("unsafe.Slice of incomplete (or unallocatable) type not allowed")
 	}
+
 	if !checkunsafeslice(&n.Y) {
 		n.SetType(nil)
 		return n
diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go
index 232c0e6..21d3100 100644
--- a/src/cmd/compile/internal/typecheck/typecheck.go
+++ b/src/cmd/compile/internal/typecheck/typecheck.go
@@ -1471,15 +1471,22 @@
 }
 
 func errorDetails(nl ir.Nodes, tstruct *types.Type, isddd bool) string {
-	// If we don't know any type at a call site, let's suppress any return
-	// message signatures. See Issue https://golang.org/issues/19012.
+	// Suppress any return message signatures if:
+	//
+	// (1) We don't know any type at a call site (see #19012).
+	// (2) Any node has an unknown type.
+	// (3) Invalid type for variadic parameter (see #46957).
 	if tstruct == nil {
-		return ""
+		return "" // case 1
 	}
-	// If any node has an unknown type, suppress it as well
+
+	if isddd && !nl[len(nl)-1].Type().IsSlice() {
+		return "" // case 3
+	}
+
 	for _, n := range nl {
 		if n.Type() == nil {
-			return ""
+			return "" // case 2
 		}
 	}
 	return fmt.Sprintf("\n\thave %s\n\twant %v", fmtSignature(nl, isddd), tstruct)
diff --git a/src/cmd/compile/internal/walk/builtin.go b/src/cmd/compile/internal/walk/builtin.go
index 135eaee..e1a2319 100644
--- a/src/cmd/compile/internal/walk/builtin.go
+++ b/src/cmd/compile/internal/walk/builtin.go
@@ -647,35 +647,28 @@
 }
 
 func walkUnsafeSlice(n *ir.BinaryExpr, init *ir.Nodes) ir.Node {
+	ptr := safeExpr(n.X, init)
 	len := safeExpr(n.Y, init)
 
 	fnname := "unsafeslice64"
-	argtype := types.Types[types.TINT64]
+	lenType := types.Types[types.TINT64]
 
 	// Type checking guarantees that TIDEAL len/cap are positive and fit in an int.
 	// The case of len or cap overflow when converting TUINT or TUINTPTR to TINT
 	// will be handled by the negative range checks in unsafeslice during runtime.
-	if len.Type().IsKind(types.TIDEAL) || len.Type().Size() <= types.Types[types.TUINT].Size() {
+	if ir.ShouldCheckPtr(ir.CurFunc, 1) {
+		fnname = "unsafeslicecheckptr"
+		// for simplicity, unsafeslicecheckptr always uses int64
+	} else if len.Type().IsKind(types.TIDEAL) || len.Type().Size() <= types.Types[types.TUINT].Size() {
 		fnname = "unsafeslice"
-		argtype = types.Types[types.TINT]
+		lenType = types.Types[types.TINT]
 	}
 
 	t := n.Type()
 
-	// Call runtime.unsafeslice[64] to check that the length argument is
-	// non-negative and smaller than the max length allowed for the
-	// element type.
+	// Call runtime.unsafeslice{,64,checkptr} to check ptr and len.
 	fn := typecheck.LookupRuntime(fnname)
-	init.Append(mkcall1(fn, nil, init, reflectdata.TypePtr(t.Elem()), typecheck.Conv(len, argtype)))
-
-	ptr := walkExpr(n.X, init)
-
-	check := ir.NewUnaryExpr(n.Pos(), ir.OCHECKNIL, ptr)
-	init.Append(typecheck.Stmt(check))
-
-	// TODO(mdempsky): checkptr instrumentation. Maybe merge into length
-	// check above, along with nil check? Need to be careful about
-	// notinheap pointers though: can't pass them as unsafe.Pointer.
+	init.Append(mkcall1(fn, nil, init, reflectdata.TypePtr(t.Elem()), typecheck.Conv(ptr, types.Types[types.TUNSAFEPTR]), typecheck.Conv(len, lenType)))
 
 	h := ir.NewSliceHeaderExpr(n.Pos(), t,
 		typecheck.Conv(ptr, types.Types[types.TUNSAFEPTR]),
diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go
index f2c4cf0..4acd357 100644
--- a/src/cmd/dist/test.go
+++ b/src/cmd/dist/test.go
@@ -737,9 +737,9 @@
 						fn: func(dt *distTest) error {
 							cmd := t.addCmd(dt, "misc/swig/callback", t.goTest())
 							cmd.Env = append(os.Environ(),
-								"CGO_CFLAGS=-flto -Wno-lto-type-mismatch",
-								"CGO_CXXFLAGS=-flto -Wno-lto-type-mismatch",
-								"CGO_LDFLAGS=-flto -Wno-lto-type-mismatch",
+								"CGO_CFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option",
+								"CGO_CXXFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option",
+								"CGO_LDFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option",
 							)
 							return nil
 						},
diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index fd95da2..90eb3e2 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -1903,6 +1903,12 @@
 // 	GCCGOTOOLDIR
 // 		If set, where to find gccgo tools, such as cgo.
 // 		The default is based on how gccgo was configured.
+// 	GOEXPERIMENT
+// 		Comma-separated list of toolchain experiments to enable or disable.
+// 		The list of available experiments may change arbitrarily over time.
+// 		See src/internal/goexperiment/flags.go for currently valid values.
+// 		Warning: This variable is provided for the development and testing
+// 		of the Go toolchain itself. Use beyond that purpose is unsupported.
 // 	GOROOT_FINAL
 // 		The root of the installed Go tree, when it is
 // 		installed in a location other than where it is built.
diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go
index fc69890..57a3c1f 100644
--- a/src/cmd/go/internal/cfg/cfg.go
+++ b/src/cmd/go/internal/cfg/cfg.go
@@ -79,7 +79,7 @@
 
 	// The experiments flags are based on GOARCH, so they may
 	// need to change.  TODO: This should be cleaned up.
-	buildcfg.UpdateExperiments(ctxt.GOARCH)
+	buildcfg.UpdateExperiments(ctxt.GOOS, ctxt.GOARCH, envOr("GOEXPERIMENT", buildcfg.DefaultGOEXPERIMENT))
 	ctxt.ToolTags = nil
 	for _, exp := range buildcfg.EnabledExperiments() {
 		ctxt.ToolTags = append(ctxt.ToolTags, "goexperiment."+exp)
diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go
index b30c37ab..1553d26 100644
--- a/src/cmd/go/internal/envcmd/env.go
+++ b/src/cmd/go/internal/envcmd/env.go
@@ -10,6 +10,7 @@
 	"encoding/json"
 	"fmt"
 	"go/build"
+	"internal/buildcfg"
 	"io"
 	"os"
 	"path/filepath"
@@ -72,6 +73,7 @@
 		{Name: "GOCACHE", Value: cache.DefaultDir()},
 		{Name: "GOENV", Value: envFile},
 		{Name: "GOEXE", Value: cfg.ExeSuffix},
+		{Name: "GOEXPERIMENT", Value: buildcfg.GOEXPERIMENT()},
 		{Name: "GOFLAGS", Value: cfg.Getenv("GOFLAGS")},
 		{Name: "GOHOSTARCH", Value: runtime.GOARCH},
 		{Name: "GOHOSTOS", Value: runtime.GOOS},
@@ -197,6 +199,21 @@
 	if *envU && *envW {
 		base.Fatalf("go env: cannot use -u with -w")
 	}
+
+	// Handle 'go env -w' and 'go env -u' before calling buildcfg.Check,
+	// so they can be used to recover from an invalid configuration.
+	if *envW {
+		runEnvW(args)
+		return
+	}
+
+	if *envU {
+		runEnvU(args)
+		return
+	}
+
+	buildcfg.Check()
+
 	env := cfg.CmdEnv
 	env = append(env, ExtraEnvVars()...)
 
@@ -206,14 +223,7 @@
 
 	// Do we need to call ExtraEnvVarsCostly, which is a bit expensive?
 	needCostly := false
-	if *envU || *envW {
-		// We're overwriting or removing default settings,
-		// so it doesn't really matter what the existing settings are.
-		//
-		// Moreover, we haven't validated the new settings yet, so it is
-		// important that we NOT perform any actions based on them,
-		// such as initializing the builder to compute other variables.
-	} else if len(args) == 0 {
+	if len(args) == 0 {
 		// We're listing all environment variables ("go env"),
 		// including the expensive ones.
 		needCostly = true
@@ -238,95 +248,6 @@
 		env = append(env, ExtraEnvVarsCostly()...)
 	}
 
-	if *envW {
-		// Process and sanity-check command line.
-		if len(args) == 0 {
-			base.Fatalf("go env -w: no KEY=VALUE arguments given")
-		}
-		osEnv := make(map[string]string)
-		for _, e := range cfg.OrigEnv {
-			if i := strings.Index(e, "="); i >= 0 {
-				osEnv[e[:i]] = e[i+1:]
-			}
-		}
-		add := make(map[string]string)
-		for _, arg := range args {
-			i := strings.Index(arg, "=")
-			if i < 0 {
-				base.Fatalf("go env -w: arguments must be KEY=VALUE: invalid argument: %s", arg)
-			}
-			key, val := arg[:i], arg[i+1:]
-			if err := checkEnvWrite(key, val); err != nil {
-				base.Fatalf("go env -w: %v", err)
-			}
-			if _, ok := add[key]; ok {
-				base.Fatalf("go env -w: multiple values for key: %s", key)
-			}
-			add[key] = val
-			if osVal := osEnv[key]; osVal != "" && osVal != val {
-				fmt.Fprintf(os.Stderr, "warning: go env -w %s=... does not override conflicting OS environment variable\n", key)
-			}
-		}
-
-		goos, okGOOS := add["GOOS"]
-		goarch, okGOARCH := add["GOARCH"]
-		if okGOOS || okGOARCH {
-			if !okGOOS {
-				goos = cfg.Goos
-			}
-			if !okGOARCH {
-				goarch = cfg.Goarch
-			}
-			if err := work.CheckGOOSARCHPair(goos, goarch); err != nil {
-				base.Fatalf("go env -w: %v", err)
-			}
-		}
-
-		gotmp, okGOTMP := add["GOTMPDIR"]
-		if okGOTMP {
-			if !filepath.IsAbs(gotmp) && gotmp != "" {
-				base.Fatalf("go env -w: GOTMPDIR must be an absolute path")
-			}
-		}
-
-		updateEnvFile(add, nil)
-		return
-	}
-
-	if *envU {
-		// Process and sanity-check command line.
-		if len(args) == 0 {
-			base.Fatalf("go env -u: no arguments given")
-		}
-		del := make(map[string]bool)
-		for _, arg := range args {
-			if err := checkEnvWrite(arg, ""); err != nil {
-				base.Fatalf("go env -u: %v", err)
-			}
-			del[arg] = true
-		}
-		if del["GOOS"] || del["GOARCH"] {
-			goos, goarch := cfg.Goos, cfg.Goarch
-			if del["GOOS"] {
-				goos = getOrigEnv("GOOS")
-				if goos == "" {
-					goos = build.Default.GOOS
-				}
-			}
-			if del["GOARCH"] {
-				goarch = getOrigEnv("GOARCH")
-				if goarch == "" {
-					goarch = build.Default.GOARCH
-				}
-			}
-			if err := work.CheckGOOSARCHPair(goos, goarch); err != nil {
-				base.Fatalf("go env -u: %v", err)
-			}
-		}
-		updateEnvFile(nil, del)
-		return
-	}
-
 	if len(args) > 0 {
 		if *envJson {
 			var es []cfg.EnvVar
@@ -351,6 +272,109 @@
 	PrintEnv(os.Stdout, env)
 }
 
+func runEnvW(args []string) {
+	// Process and sanity-check command line.
+	if len(args) == 0 {
+		base.Fatalf("go env -w: no KEY=VALUE arguments given")
+	}
+	osEnv := make(map[string]string)
+	for _, e := range cfg.OrigEnv {
+		if i := strings.Index(e, "="); i >= 0 {
+			osEnv[e[:i]] = e[i+1:]
+		}
+	}
+	add := make(map[string]string)
+	for _, arg := range args {
+		i := strings.Index(arg, "=")
+		if i < 0 {
+			base.Fatalf("go env -w: arguments must be KEY=VALUE: invalid argument: %s", arg)
+		}
+		key, val := arg[:i], arg[i+1:]
+		if err := checkEnvWrite(key, val); err != nil {
+			base.Fatalf("go env -w: %v", err)
+		}
+		if _, ok := add[key]; ok {
+			base.Fatalf("go env -w: multiple values for key: %s", key)
+		}
+		add[key] = val
+		if osVal := osEnv[key]; osVal != "" && osVal != val {
+			fmt.Fprintf(os.Stderr, "warning: go env -w %s=... does not override conflicting OS environment variable\n", key)
+		}
+	}
+
+	if err := checkBuildConfig(add, nil); err != nil {
+		base.Fatalf("go env -w: %v", err)
+	}
+
+	gotmp, okGOTMP := add["GOTMPDIR"]
+	if okGOTMP {
+		if !filepath.IsAbs(gotmp) && gotmp != "" {
+			base.Fatalf("go env -w: GOTMPDIR must be an absolute path")
+		}
+	}
+
+	updateEnvFile(add, nil)
+}
+
+func runEnvU(args []string) {
+	// Process and sanity-check command line.
+	if len(args) == 0 {
+		base.Fatalf("go env -u: no arguments given")
+	}
+	del := make(map[string]bool)
+	for _, arg := range args {
+		if err := checkEnvWrite(arg, ""); err != nil {
+			base.Fatalf("go env -u: %v", err)
+		}
+		del[arg] = true
+	}
+
+	if err := checkBuildConfig(nil, del); err != nil {
+		base.Fatalf("go env -u: %v", err)
+	}
+
+	updateEnvFile(nil, del)
+}
+
+// checkBuildConfig checks whether the build configuration is valid
+// after the specified configuration environment changes are applied.
+func checkBuildConfig(add map[string]string, del map[string]bool) error {
+	// get returns the value for key after applying add and del and
+	// reports whether it changed. cur should be the current value
+	// (i.e., before applying changes) and def should be the default
+	// value (i.e., when no environment variables are provided at all).
+	get := func(key, cur, def string) (string, bool) {
+		if val, ok := add[key]; ok {
+			return val, true
+		}
+		if del[key] {
+			val := getOrigEnv(key)
+			if val == "" {
+				val = def
+			}
+			return val, true
+		}
+		return cur, false
+	}
+
+	goos, okGOOS := get("GOOS", cfg.Goos, build.Default.GOOS)
+	goarch, okGOARCH := get("GOARCH", cfg.Goarch, build.Default.GOARCH)
+	if okGOOS || okGOARCH {
+		if err := work.CheckGOOSARCHPair(goos, goarch); err != nil {
+			return err
+		}
+	}
+
+	goexperiment, okGOEXPERIMENT := get("GOEXPERIMENT", buildcfg.GOEXPERIMENT(), "")
+	if okGOEXPERIMENT {
+		if _, _, err := buildcfg.ParseGOEXPERIMENT(goos, goarch, goexperiment); err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 // PrintEnv prints the environment variables to w.
 func PrintEnv(w io.Writer, env []cfg.EnvVar) {
 	for _, e := range env {
diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go
index b552777..490ff1f 100644
--- a/src/cmd/go/internal/help/helpdoc.go
+++ b/src/cmd/go/internal/help/helpdoc.go
@@ -610,6 +610,12 @@
 	GCCGOTOOLDIR
 		If set, where to find gccgo tools, such as cgo.
 		The default is based on how gccgo was configured.
+	GOEXPERIMENT
+		Comma-separated list of toolchain experiments to enable or disable.
+		The list of available experiments may change arbitrarily over time.
+		See src/internal/goexperiment/flags.go for currently valid values.
+		Warning: This variable is provided for the development and testing
+		of the Go toolchain itself. Use beyond that purpose is unsupported.
 	GOROOT_FINAL
 		The root of the installed Go tree, when it is
 		installed in a location other than where it is built.
diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go
index 02174a5..16361e0 100644
--- a/src/cmd/go/main.go
+++ b/src/cmd/go/main.go
@@ -145,24 +145,6 @@
 		os.Exit(2)
 	}
 
-	if err := buildcfg.Error; err != nil {
-		fmt.Fprintf(os.Stderr, "go: %v\n", buildcfg.Error)
-		os.Exit(2)
-	}
-
-	// Set environment (GOOS, GOARCH, etc) explicitly.
-	// In theory all the commands we invoke should have
-	// the same default computation of these as we do,
-	// but in practice there might be skew
-	// This makes sure we all agree.
-	cfg.OrigEnv = os.Environ()
-	cfg.CmdEnv = envcmd.MkEnv()
-	for _, env := range cfg.CmdEnv {
-		if os.Getenv(env.Name) != env.Value {
-			os.Setenv(env.Name, env.Value)
-		}
-	}
-
 BigCmdLoop:
 	for bigCmd := base.Go; ; {
 		for _, cmd := range bigCmd.Commands {
@@ -188,18 +170,7 @@
 			if !cmd.Runnable() {
 				continue
 			}
-			cmd.Flag.Usage = func() { cmd.Usage() }
-			if cmd.CustomFlags {
-				args = args[1:]
-			} else {
-				base.SetFromGOFLAGS(&cmd.Flag)
-				cmd.Flag.Parse(args[1:])
-				args = cmd.Flag.Args()
-			}
-			ctx := maybeStartTrace(context.Background())
-			ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command"))
-			cmd.Run(ctx, cmd, args)
-			span.Done()
+			invoke(cmd, args)
 			base.Exit()
 			return
 		}
@@ -213,6 +184,39 @@
 	}
 }
 
+func invoke(cmd *base.Command, args []string) {
+	// 'go env' handles checking the build config
+	if cmd != envcmd.CmdEnv {
+		buildcfg.Check()
+	}
+
+	// Set environment (GOOS, GOARCH, etc) explicitly.
+	// In theory all the commands we invoke should have
+	// the same default computation of these as we do,
+	// but in practice there might be skew
+	// This makes sure we all agree.
+	cfg.OrigEnv = os.Environ()
+	cfg.CmdEnv = envcmd.MkEnv()
+	for _, env := range cfg.CmdEnv {
+		if os.Getenv(env.Name) != env.Value {
+			os.Setenv(env.Name, env.Value)
+		}
+	}
+
+	cmd.Flag.Usage = func() { cmd.Usage() }
+	if cmd.CustomFlags {
+		args = args[1:]
+	} else {
+		base.SetFromGOFLAGS(&cmd.Flag)
+		cmd.Flag.Parse(args[1:])
+		args = cmd.Flag.Args()
+	}
+	ctx := maybeStartTrace(context.Background())
+	ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command"))
+	cmd.Run(ctx, cmd, args)
+	span.Done()
+}
+
 func init() {
 	base.Usage = mainUsage
 }
diff --git a/src/cmd/go/testdata/script/env_exp.txt b/src/cmd/go/testdata/script/env_exp.txt
new file mode 100644
index 0000000..681512d
--- /dev/null
+++ b/src/cmd/go/testdata/script/env_exp.txt
@@ -0,0 +1,17 @@
+# Test GOEXPERIMENT variable
+
+# go env shows default empty GOEXPERIMENT
+go env
+stdout GOEXPERIMENT=
+
+# go env shows valid experiments
+env GOEXPERIMENT=fieldtrack,staticlockranking
+go env GOEXPERIMENT
+stdout '.*fieldtrack.*staticlockranking.*'
+go env
+stdout 'GOEXPERIMENT=.*fieldtrack.*staticlockranking.*'
+
+# go env rejects unknown experiments
+env GOEXPERIMENT=bad
+! go env GOEXPERIMENT
+stderr 'unknown GOEXPERIMENT bad'
diff --git a/src/cmd/go/testdata/script/env_unset.txt b/src/cmd/go/testdata/script/env_unset.txt
new file mode 100644
index 0000000..4e0f249
--- /dev/null
+++ b/src/cmd/go/testdata/script/env_unset.txt
@@ -0,0 +1,30 @@
+# Test that we can unset variables, even if initially invalid,
+# as long as resulting config is valid.
+
+env GOENV=badenv
+env GOOS=
+env GOARCH=
+env GOEXPERIMENT=
+
+! go env
+stderr '^go(\.exe)?: unknown GOEXPERIMENT badexp$'
+
+go env -u GOEXPERIMENT
+
+! go env
+stderr '^cmd/go: unsupported GOOS/GOARCH pair bados/badarch$'
+
+! go env -u GOOS
+stderr '^go env -u: unsupported GOOS/GOARCH pair \w+/badarch$'
+
+! go env -u GOARCH
+stderr '^go env -u: unsupported GOOS/GOARCH pair bados/\w+$'
+
+go env -u GOOS GOARCH
+
+go env
+
+-- badenv --
+GOOS=bados
+GOARCH=badarch
+GOEXPERIMENT=badexp
diff --git a/src/cmd/go/testdata/script/env_write.txt b/src/cmd/go/testdata/script/env_write.txt
index 4fa39df..b5e9739 100644
--- a/src/cmd/go/testdata/script/env_write.txt
+++ b/src/cmd/go/testdata/script/env_write.txt
@@ -179,3 +179,9 @@
 stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "~/test"'
 ! go env -w GOMODCACHE=./test
 stderr 'go env -w: GOMODCACHE entry is relative; must be absolute path: "./test"'
+
+# go env -w checks validity of GOEXPERIMENT
+env GOEXPERIMENT=
+! go env -w GOEXPERIMENT=badexp
+stderr 'unknown GOEXPERIMENT badexp'
+go env -w GOEXPERIMENT=fieldtrack
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index b8c3cd9..d99afa3 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -4333,8 +4333,10 @@
 		if p.To.Reg == REG_RSP && isADDSop(p.As) {
 			c.ctxt.Diag("illegal destination register: %v\n", p)
 		}
+		lsl0 := LSL0_64
 		if isADDWop(p.As) || isANDWop(p.As) {
 			o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
+			lsl0 = LSL0_32
 		} else {
 			o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
 		}
@@ -4350,7 +4352,7 @@
 		if p.To.Reg == REGSP || r == REGSP {
 			o2 = c.opxrrr(p, p.As, false)
 			o2 |= REGTMP & 31 << 16
-			o2 |= LSL0_64
+			o2 |= uint32(lsl0)
 		} else {
 			o2 = c.oprrr(p, p.As)
 			o2 |= REGTMP & 31 << 16 /* shift is 0 */
diff --git a/src/cmd/link/internal/ld/ld_test.go b/src/cmd/link/internal/ld/ld_test.go
index ca76463..3702a4d 100644
--- a/src/cmd/link/internal/ld/ld_test.go
+++ b/src/cmd/link/internal/ld/ld_test.go
@@ -174,6 +174,8 @@
 		t.Skip("skipping windows amd64/386 only test")
 	}
 
+	testenv.MustHaveCGO(t)
+
 	t.Run("aslr", func(t *testing.T) {
 		testWindowsBuildmodeCSharedASLR(t, true)
 	})
diff --git a/src/crypto/x509/parser.go b/src/crypto/x509/parser.go
index 3d51ddd..f085162 100644
--- a/src/crypto/x509/parser.go
+++ b/src/crypto/x509/parser.go
@@ -734,10 +734,12 @@
 				if !val.ReadASN1(&akid, cryptobyte_asn1.SEQUENCE) {
 					return errors.New("x509: invalid authority key identifier")
 				}
-				if !akid.ReadASN1(&akid, cryptobyte_asn1.Tag(0).ContextSpecific()) {
-					return errors.New("x509: invalid authority key identifier")
+				if akid.PeekASN1Tag(cryptobyte_asn1.Tag(0).ContextSpecific()) {
+					if !akid.ReadASN1(&akid, cryptobyte_asn1.Tag(0).ContextSpecific()) {
+						return errors.New("x509: invalid authority key identifier")
+					}
+					out.AuthorityKeyId = akid
 				}
-				out.AuthorityKeyId = akid
 			case 37:
 				out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value)
 				if err != nil {
diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go
index 802bce0..a4053ab 100644
--- a/src/crypto/x509/x509_test.go
+++ b/src/crypto/x509/x509_test.go
@@ -3174,3 +3174,45 @@
 		}
 	}
 }
+
+const optionalAuthKeyIDPEM = `-----BEGIN CERTIFICATE-----
+MIIFEjCCBHugAwIBAgICAQwwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh
+bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu
+Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g
+QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe
+BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MzkxNloX
+DTI0MDYyOTE3MzkxNlowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVs
+ZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAy
+IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0A
+MIIBCAKCAQEAtzLI/ulxpgSFrQwRZN/OTe/IAxiHP6Gr+zymn/DDodrU2G4rU5D7
+JKQ+hPCe6F/s5SdE9SimP3ve4CrwyK9TL57KBQGTHo9mHDmnTfpatnMEJWbrd3/n
+WcZKmSUUVOsmx/N/GdUwcI+vsEYq/63rKe3Xn6oEh6PU+YmlNF/bQ5GCNtlmPLG4
+uYL9nDo+EMg77wZlZnqbGRg9/3FRPDAuX749d3OyXQZswyNWmiuFJpIcpwKz5D8N
+rwh5grg2Peqc0zWzvGnK9cyd6P1kjReAM25eSl2ZyR6HtJ0awNVuEzUjXt+bXz3v
+1vd2wuo+u3gNHEJnawTY+Nbab4vyRKABqwIBA6OCAfMwggHvMB0GA1UdDgQWBBS/
+X7fRzt0fhvRbVazc1xDCDqmI5zCB0gYDVR0jBIHKMIHHoYHBpIG+MIG7MSQwIgYD
+VQQHExtWYWxpQ2VydCBWYWxpZGF0aW9uIE5ldHdvcmsxFzAVBgNVBAoTDlZhbGlD
+ZXJ0LCBJbmMuMTUwMwYDVQQLEyxWYWxpQ2VydCBDbGFzcyAyIFBvbGljeSBWYWxp
+ZGF0aW9uIEF1dGhvcml0eTEhMB8GA1UEAxMYaHR0cDovL3d3dy52YWxpY2VydC5j
+b20vMSAwHgYJKoZIhvcNAQkBFhFpbmZvQHZhbGljZXJ0LmNvbYIBATAPBgNVHRMB
+Af8EBTADAQH/MDkGCCsGAQUFBwEBBC0wKzApBggrBgEFBQcwAYYdaHR0cDovL29j
+c3Auc3RhcmZpZWxkdGVjaC5jb20wSgYDVR0fBEMwQTA/oD2gO4Y5aHR0cDovL2Nl
+cnRpZmljYXRlcy5zdGFyZmllbGR0ZWNoLmNvbS9yZXBvc2l0b3J5L3Jvb3QuY3Js
+MFEGA1UdIARKMEgwRgYEVR0gADA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY2VydGlm
+aWNhdGVzLnN0YXJmaWVsZHRlY2guY29tL3JlcG9zaXRvcnkwDgYDVR0PAQH/BAQD
+AgEGMA0GCSqGSIb3DQEBBQUAA4GBAKVi8afCXSWlcD284ipxs33kDTcdVWptobCr
+mADkhWBKIMuh8D1195TaQ39oXCUIuNJ9MxB73HZn8bjhU3zhxoNbKXuNSm8uf0So
+GkVrMgfHeMpkksK0hAzc3S1fTbvdiuo43NlmouxBulVtWmQ9twPMHOKRUJ7jCUSV
+FxdzPcwl
+-----END CERTIFICATE-----`
+
+func TestAuthKeyIdOptional(t *testing.T) {
+	b, _ := pem.Decode([]byte(optionalAuthKeyIDPEM))
+	if b == nil {
+		t.Fatalf("couldn't decode test certificate")
+	}
+	_, err := ParseCertificate(b.Bytes)
+	if err != nil {
+		t.Fatalf("ParseCertificate to failed to parse certificate with optional authority key identifier fields: %s", err)
+	}
+}
diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go
index 503d0a6..d86a77a 100644
--- a/src/go/types/stdlib_test.go
+++ b/src/go/types/stdlib_test.go
@@ -26,9 +26,15 @@
 	. "go/types"
 )
 
+// The cmd/*/internal packages may have been deleted as part of a binary
+// release. Import from source instead.
+//
+// (See https://golang.org/issue/43232 and
+// https://github.com/golang/build/blob/df58bbac082bc87c4a3cdfe336d1ffe60bbaa916/cmd/release/release.go#L533-L545.)
+//
 // Use the same importer for all std lib tests to
 // avoid repeated importing of the same packages.
-var stdLibImporter = importer.Default()
+var stdLibImporter = importer.ForCompiler(token.NewFileSet(), "source", nil)
 
 func TestStdlib(t *testing.T) {
 	testenv.MustHaveGoBuild(t)
diff --git a/src/go/types/testdata/check/issues.src b/src/go/types/testdata/check/issues.src
index b023154..ef17373 100644
--- a/src/go/types/testdata/check/issues.src
+++ b/src/go/types/testdata/check/issues.src
@@ -6,7 +6,7 @@
 
 import (
 	"fmt"
-	syn "cmd/compile/internal/syntax"
+	syn "regexp/syntax"
 	t1 "text/template"
 	t2 "html/template"
 )
@@ -329,10 +329,10 @@
 func issue28281g() (... /* ERROR can only use ... with final parameter */ TT)
 
 // Issue #26234: Make various field/method lookup errors easier to read by matching cmd/compile's output
-func issue26234a(f *syn.File) {
+func issue26234a(f *syn.Prog) {
 	// The error message below should refer to the actual package name (syntax)
 	// not the local package name (syn).
-	f.foo /* ERROR f\.foo undefined \(type \*syntax\.File has no field or method foo\) */
+	f.foo /* ERROR f\.foo undefined \(type \*syntax\.Prog has no field or method foo\) */
 }
 
 type T struct {
@@ -357,7 +357,7 @@
 	var _ T = 0 // ERROR cannot use 0 \(untyped int constant\) as T
 
 	// There is only one package with name syntax imported, only use the (global) package name in error messages.
-	var _ *syn.File = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.File
+	var _ *syn.Prog = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.Prog
 
 	// Because both t1 and t2 have the same global package name (template),
 	// qualify packages with full path name in this case.
diff --git a/src/image/geom.go b/src/image/geom.go
index 78e9e49..e71aa61 100644
--- a/src/image/geom.go
+++ b/src/image/geom.go
@@ -246,6 +246,14 @@
 	return color.Transparent
 }
 
+// RGBA64At implements the RGBA64Image interface.
+func (r Rectangle) RGBA64At(x, y int) color.RGBA64 {
+	if (Point{x, y}).In(r) {
+		return color.RGBA64{0xffff, 0xffff, 0xffff, 0xffff}
+	}
+	return color.RGBA64{}
+}
+
 // Bounds implements the Image interface.
 func (r Rectangle) Bounds() Rectangle {
 	return r
diff --git a/src/image/gif/reader.go b/src/image/gif/reader.go
index e580ab0..9e8268c 100644
--- a/src/image/gif/reader.go
+++ b/src/image/gif/reader.go
@@ -116,7 +116,7 @@
 // consumed when checking that the blockReader is exhausted.
 //
 // To avoid the allocation of a bufio.Reader for the lzw Reader, blockReader
-// implements io.ReadByte and buffers blocks into the decoder's "tmp" buffer.
+// implements io.ByteReader and buffers blocks into the decoder's "tmp" buffer.
 type blockReader struct {
 	d    *decoder
 	i, j uint8 // d.tmp[i:j] contains the buffered bytes
diff --git a/src/image/image_test.go b/src/image/image_test.go
index c64b610..7f41bcb 100644
--- a/src/image/image_test.go
+++ b/src/image/image_test.go
@@ -213,7 +213,9 @@
 		NewPaletted(r, palette.Plan9),
 		NewRGBA(r),
 		NewRGBA64(r),
+		NewUniform(color.RGBA64{}),
 		NewYCbCr(r, YCbCrSubsampleRatio444),
+		r,
 	}
 	for _, tc := range testCases {
 		switch tc := tc.(type) {
@@ -226,6 +228,9 @@
 		// means that setting one pixel can modify neighboring pixels. They
 		// don't have Set or SetRGBA64 methods because that side effect could
 		// be surprising. Here, we just memset the channel buffers instead.
+		//
+		// The Uniform and Rectangle types are also special-cased, as they
+		// don't have a Set or SetRGBA64 method.
 		case interface {
 			SetRGBA64(x, y int, c color.RGBA64)
 		}:
@@ -237,11 +242,18 @@
 			memset(tc.YCbCr.Cr, 0x99)
 			memset(tc.A, 0xAA)
 
+		case *Uniform:
+			tc.C = color.RGBA64{0x7FFF, 0x3FFF, 0x0000, 0x7FFF}
+
 		case *YCbCr:
 			memset(tc.Y, 0x77)
 			memset(tc.Cb, 0x88)
 			memset(tc.Cr, 0x99)
 
+		case Rectangle:
+			// No-op. Rectangle pixels' colors are immutable. They're always
+			// color.Opaque.
+
 		default:
 			t.Errorf("could not initialize pixels for %T", tc)
 			continue
diff --git a/src/image/names.go b/src/image/names.go
index 8595a35..17b0658 100644
--- a/src/image/names.go
+++ b/src/image/names.go
@@ -41,6 +41,11 @@
 
 func (c *Uniform) At(x, y int) color.Color { return c.C }
 
+func (c *Uniform) RGBA64At(x, y int) color.RGBA64 {
+	r, g, b, a := c.C.RGBA()
+	return color.RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
+}
+
 // Opaque scans the entire image and reports whether it is fully opaque.
 func (c *Uniform) Opaque() bool {
 	_, _, _, a := c.C.RGBA()
diff --git a/src/internal/buildcfg/exp.go b/src/internal/buildcfg/exp.go
index e87b622..6e8bf30 100644
--- a/src/internal/buildcfg/exp.go
+++ b/src/internal/buildcfg/exp.go
@@ -6,7 +6,6 @@
 
 import (
 	"fmt"
-	"os"
 	"reflect"
 	"strings"
 
@@ -18,19 +17,19 @@
 //
 // (This is not necessarily the set of experiments the compiler itself
 // was built with.)
-var Experiment goexperiment.Flags = parseExperiments(GOARCH)
-
-var regabiSupported = GOARCH == "amd64" || GOARCH == "arm64"
-var regabiDeveloping = false
-
+//
 // experimentBaseline specifies the experiment flags that are enabled by
 // default in the current toolchain. This is, in effect, the "control"
 // configuration and any variation from this is an experiment.
-var experimentBaseline = goexperiment.Flags{
-	RegabiWrappers: regabiSupported,
-	RegabiReflect:  regabiSupported,
-	RegabiArgs:     regabiSupported,
-}
+var Experiment, experimentBaseline = func() (goexperiment.Flags, goexperiment.Flags) {
+	flags, baseline, err := ParseGOEXPERIMENT(GOOS, GOARCH, envOr("GOEXPERIMENT", defaultGOEXPERIMENT))
+	if err != nil {
+		Error = err
+	}
+	return flags, baseline
+}()
+
+const DefaultGOEXPERIMENT = defaultGOEXPERIMENT
 
 // FramePointerEnabled enables the use of platform conventions for
 // saving frame pointers.
@@ -41,16 +40,27 @@
 // Note: must agree with runtime.framepointer_enabled.
 var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64"
 
-func parseExperiments(goarch string) goexperiment.Flags {
+// ParseGOEXPERIMENT parses a (GOOS, GOARCH, GOEXPERIMENT)
+// configuration tuple and returns the enabled and baseline experiment
+// flag sets.
+//
+// TODO(mdempsky): Move to internal/goexperiment.
+func ParseGOEXPERIMENT(goos, goarch, goexp string) (flags, baseline goexperiment.Flags, err error) {
+	regabiSupported := goarch == "amd64" || goarch == "arm64"
+
+	baseline = goexperiment.Flags{
+		RegabiWrappers: regabiSupported,
+		RegabiReflect:  regabiSupported,
+		RegabiArgs:     regabiSupported,
+	}
+
 	// Start with the statically enabled set of experiments.
-	flags := experimentBaseline
+	flags = baseline
 
 	// Pick up any changes to the baseline configuration from the
 	// GOEXPERIMENT environment. This can be set at make.bash time
 	// and overridden at build time.
-	env := envOr("GOEXPERIMENT", defaultGOEXPERIMENT)
-
-	if env != "" {
+	if goexp != "" {
 		// Create a map of known experiment names.
 		names := make(map[string]func(bool))
 		rv := reflect.ValueOf(&flags).Elem()
@@ -71,7 +81,7 @@
 		}
 
 		// Parse names.
-		for _, f := range strings.Split(env, ",") {
+		for _, f := range strings.Split(goexp, ",") {
 			if f == "" {
 				continue
 			}
@@ -88,8 +98,8 @@
 			}
 			set, ok := names[f]
 			if !ok {
-				fmt.Printf("unknown experiment %s\n", f)
-				os.Exit(2)
+				err = fmt.Errorf("unknown GOEXPERIMENT %s", f)
+				return
 			}
 			set(val)
 		}
@@ -107,9 +117,9 @@
 	}
 	// Check regabi dependencies.
 	if flags.RegabiArgs && !(flags.RegabiWrappers && flags.RegabiReflect) {
-		Error = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabireflect")
+		err = fmt.Errorf("GOEXPERIMENT regabiargs requires regabiwrappers,regabireflect")
 	}
-	return flags
+	return
 }
 
 // expList returns the list of lower-cased experiment names for
@@ -165,6 +175,10 @@
 // UpdateExperiments updates the Experiment global based on a new GOARCH value.
 // This is only required for cmd/go, which can change GOARCH after
 // program startup due to use of "go env -w".
-func UpdateExperiments(goarch string) {
-	Experiment = parseExperiments(goarch)
+func UpdateExperiments(goos, goarch, goexperiment string) {
+	var err error
+	Experiment, experimentBaseline, err = ParseGOEXPERIMENT(goos, goarch, goexperiment)
+	if err != nil {
+		Error = err
+	}
 }
diff --git a/src/math/big/int.go b/src/math/big/int.go
index 65f3248..7647346 100644
--- a/src/math/big/int.go
+++ b/src/math/big/int.go
@@ -425,7 +425,7 @@
 	return z.setFromScanner(strings.NewReader(s), base)
 }
 
-// setFromScanner implements SetString given an io.BytesScanner.
+// setFromScanner implements SetString given an io.ByteScanner.
 // For documentation see comments of SetString.
 func (z *Int) setFromScanner(r io.ByteScanner, base int) (*Int, bool) {
 	if _, _, err := z.scan(r, base); err != nil {
diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
index a59be7f..d69107a 100644
--- a/src/net/dnsclient_unix_test.go
+++ b/src/net/dnsclient_unix_test.go
@@ -1921,12 +1921,12 @@
 		t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
 	}
 
-	_, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org")
-	if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected {
+	_, _, err = r.LookupSRV(context.Background(), "hdr", "tcp", "golang.org.")
+	if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
 		t.Errorf("Resolver.LookupSRV returned unexpected error, got %q, want %q", err, expected)
 	}
-	_, _, err = LookupSRV("hdr", "tcp", "golang.org")
-	if expected := "lookup golang.org: SRV header name is invalid"; err == nil || err.Error() != expected {
+	_, _, err = LookupSRV("hdr", "tcp", "golang.org.")
+	if expected := "lookup golang.org.: SRV header name is invalid"; err == nil || err.Error() != expected {
 		t.Errorf("LookupSRV returned unexpected error, got %q, want %q", err, expected)
 	}
 
diff --git a/src/os/example_test.go b/src/os/example_test.go
index 3adce51..e8554b0 100644
--- a/src/os/example_test.go
+++ b/src/os/example_test.go
@@ -5,6 +5,7 @@
 package os_test
 
 import (
+	"errors"
 	"fmt"
 	"io/fs"
 	"log"
@@ -71,9 +72,9 @@
 	}
 }
 
-func ExampleIsNotExist() {
+func ExampleErrNotExist() {
 	filename := "a-nonexistent-file"
-	if _, err := os.Stat(filename); os.IsNotExist(err) {
+	if _, err := os.Stat(filename); errors.Is(err, fs.ErrNotExist) {
 		fmt.Println("file does not exist")
 	}
 	// Output:
diff --git a/src/path/filepath/path_test.go b/src/path/filepath/path_test.go
index cd107b6..bc5509b 100644
--- a/src/path/filepath/path_test.go
+++ b/src/path/filepath/path_test.go
@@ -1469,11 +1469,16 @@
 	// Try different numbers of "..".
 	for _, i := range []int{c, c + 1, c + 2} {
 		check := strings.Join([]string{evalTmpDir, strings.Join(dd[:i], string(os.PathSeparator)), evalTmpDir[len(vol)+1:], "b", "file"}, string(os.PathSeparator))
-		if resolved, err := filepath.EvalSymlinks(check); err != nil {
+		resolved, err := filepath.EvalSymlinks(check)
+		switch {
+		case runtime.GOOS == "darwin" && errors.Is(err, fs.ErrNotExist):
+			// On darwin, the temp dir is sometimes cleaned up mid-test (issue 37910).
+			testenv.SkipFlaky(t, 37910)
+		case err != nil:
 			t.Errorf("EvalSymlinks(%q) failed: %v", check, err)
-		} else if !strings.HasSuffix(resolved, wantSuffix) {
+		case !strings.HasSuffix(resolved, wantSuffix):
 			t.Errorf("EvalSymlinks(%q) = %q does not end with %q", check, resolved, wantSuffix)
-		} else {
+		default:
 			t.Logf("EvalSymlinks(%q) = %q", check, resolved)
 		}
 	}
diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go
index 34eec02..479878e 100644
--- a/src/runtime/cgocall.go
+++ b/src/runtime/cgocall.go
@@ -111,6 +111,8 @@
 	return as.retval
 }
 
+var ncgocall uint64 // number of cgo calls in total for dead m
+
 // Call from Go to C.
 //
 // This must be nosplit because it's used for syscalls on some
diff --git a/src/runtime/checkptr.go b/src/runtime/checkptr.go
index 59891a06..d429508 100644
--- a/src/runtime/checkptr.go
+++ b/src/runtime/checkptr.go
@@ -16,11 +16,30 @@
 	}
 
 	// Check that (*[n]elem)(p) doesn't straddle multiple heap objects.
-	if size := n * elem.size; size > 1 && checkptrBase(p) != checkptrBase(add(p, size-1)) {
+	// TODO(mdempsky): Fix #46938 so we don't need to worry about overflow here.
+	if checkptrStraddles(p, n*elem.size) {
 		throw("checkptr: converted pointer straddles multiple allocations")
 	}
 }
 
+// checkptrStraddles reports whether the first size-bytes of memory
+// addressed by ptr is known to straddle more than one Go allocation.
+func checkptrStraddles(ptr unsafe.Pointer, size uintptr) bool {
+	if size <= 1 {
+		return false
+	}
+
+	end := add(ptr, size-1)
+	if uintptr(end) < uintptr(ptr) {
+		return true
+	}
+
+	// TODO(mdempsky): Detect when [ptr, end] contains Go allocations,
+	// but neither ptr nor end point into one themselves.
+
+	return checkptrBase(ptr) != checkptrBase(end)
+}
+
 func checkptrArithmetic(p unsafe.Pointer, originals []unsafe.Pointer) {
 	if 0 < uintptr(p) && uintptr(p) < minLegalPointer {
 		throw("checkptr: pointer arithmetic computed bad pointer value")
diff --git a/src/runtime/checkptr_test.go b/src/runtime/checkptr_test.go
index 194cc12..2a5c364 100644
--- a/src/runtime/checkptr_test.go
+++ b/src/runtime/checkptr_test.go
@@ -30,6 +30,8 @@
 		{"CheckPtrArithmetic2", "fatal error: checkptr: pointer arithmetic result points to invalid allocation\n"},
 		{"CheckPtrSize", "fatal error: checkptr: converted pointer straddles multiple allocations\n"},
 		{"CheckPtrSmall", "fatal error: checkptr: pointer arithmetic computed bad pointer value\n"},
+		{"CheckPtrSliceOK", ""},
+		{"CheckPtrSliceFail", "fatal error: checkptr: unsafe.Slice result straddles multiple allocations\n"},
 	}
 
 	for _, tc := range testCases {
diff --git a/src/runtime/debug.go b/src/runtime/debug.go
index f411b22..82deefa 100644
--- a/src/runtime/debug.go
+++ b/src/runtime/debug.go
@@ -45,7 +45,7 @@
 
 // NumCgoCall returns the number of cgo calls made by the current process.
 func NumCgoCall() int64 {
-	var n int64
+	var n = int64(atomic.Load64(&ncgocall))
 	for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
 		n += int64(mp.ncgocall)
 	}
diff --git a/src/runtime/internal/atomic/atomic_amd64.s b/src/runtime/internal/atomic/atomic_amd64.s
index 57cd59d..d21514b 100644
--- a/src/runtime/internal/atomic/atomic_amd64.s
+++ b/src/runtime/internal/atomic/atomic_amd64.s
@@ -37,7 +37,7 @@
 
 // bool	·Cas64(uint64 *val, uint64 old, uint64 new)
 // Atomically:
-//	if(*val == *old){
+//	if(*val == old){
 //		*val = new;
 //		return 1;
 //	} else {
diff --git a/src/runtime/internal/atomic/atomic_arm64.s b/src/runtime/internal/atomic/atomic_arm64.s
index e9467af..5f77d92 100644
--- a/src/runtime/internal/atomic/atomic_arm64.s
+++ b/src/runtime/internal/atomic/atomic_arm64.s
@@ -192,7 +192,7 @@
 
 // bool ·Cas64(uint64 *ptr, uint64 old, uint64 new)
 // Atomically:
-//      if(*val == *old){
+//      if(*val == old){
 //              *val = new;
 //              return 1;
 //      } else {
diff --git a/src/runtime/internal/atomic/atomic_mips64x.s b/src/runtime/internal/atomic/atomic_mips64x.s
index fba668f..fedfc4a 100644
--- a/src/runtime/internal/atomic/atomic_mips64x.s
+++ b/src/runtime/internal/atomic/atomic_mips64x.s
@@ -37,7 +37,7 @@
 
 // bool	cas64(uint64 *ptr, uint64 old, uint64 new)
 // Atomically:
-//	if(*val == *old){
+//	if(*val == old){
 //		*val = new;
 //		return 1;
 //	} else {
diff --git a/src/runtime/internal/atomic/atomic_ppc64x.s b/src/runtime/internal/atomic/atomic_ppc64x.s
index dca26cb..226b3b6 100644
--- a/src/runtime/internal/atomic/atomic_ppc64x.s
+++ b/src/runtime/internal/atomic/atomic_ppc64x.s
@@ -107,7 +107,7 @@
 
 // bool	·Cas64(uint64 *ptr, uint64 old, uint64 new)
 // Atomically:
-//	if(*val == *old){
+//	if(*val == old){
 //		*val = new;
 //		return 1;
 //	} else {
diff --git a/src/runtime/internal/atomic/atomic_riscv64.s b/src/runtime/internal/atomic/atomic_riscv64.s
index ec05302..21d5adc 100644
--- a/src/runtime/internal/atomic/atomic_riscv64.s
+++ b/src/runtime/internal/atomic/atomic_riscv64.s
@@ -30,8 +30,9 @@
 
 #include "textflag.h"
 
+// func Cas(ptr *uint64, old, new uint64) bool
 // Atomically:
-//      if(*val == *old){
+//      if(*val == old){
 //              *val = new;
 //              return 1;
 //      } else {
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index f13f7d2..4dc1811 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -1510,6 +1510,8 @@
 	}
 	unlock(&sched.lock)
 
+	atomic.Xadd64(&ncgocall, int64(m.ncgocall))
+
 	// Release the P.
 	handoffp(releasep())
 	// After this point we must not have write barriers.
diff --git a/src/runtime/race/syso_test.go b/src/runtime/race/syso_test.go
index cbce5a8..f509573 100644
--- a/src/runtime/race/syso_test.go
+++ b/src/runtime/race/syso_test.go
@@ -2,14 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build !android && !js && !ppc64le
-// +build !android,!js,!ppc64le
-
-// Note: we don't run on Android or ppc64 because if there is any non-race test
-// file in this package, the OS tries to link the .syso file into the
-// test (even when we're not in race mode), which fails. I'm not sure
-// why, but easiest to just punt - as long as a single builder runs
-// this test, we're good.
+//go:build race
+// +build race
 
 package race
 
diff --git a/src/runtime/slice.go b/src/runtime/slice.go
index 66e3aff..e8267be 100644
--- a/src/runtime/slice.go
+++ b/src/runtime/slice.go
@@ -114,19 +114,37 @@
 	return makeslice(et, len, cap)
 }
 
-func unsafeslice(et *_type, len int) {
+func unsafeslice(et *_type, ptr unsafe.Pointer, len int) {
+	if len == 0 {
+		return
+	}
+
+	if ptr == nil {
+		panic(errorString("unsafe.Slice: ptr is nil and len is not zero"))
+	}
+
 	mem, overflow := math.MulUintptr(et.size, uintptr(len))
 	if overflow || mem > maxAlloc || len < 0 {
 		panicunsafeslicelen()
 	}
 }
 
-func unsafeslice64(et *_type, len64 int64) {
+func unsafeslice64(et *_type, ptr unsafe.Pointer, len64 int64) {
 	len := int(len64)
 	if int64(len) != len64 {
 		panicunsafeslicelen()
 	}
-	unsafeslice(et, len)
+	unsafeslice(et, ptr, len)
+}
+
+func unsafeslicecheckptr(et *_type, ptr unsafe.Pointer, len64 int64) {
+	unsafeslice64(et, ptr, len64)
+
+	// Check that underlying array doesn't straddle multiple heap objects.
+	// unsafeslice64 has already checked for overflow.
+	if checkptrStraddles(ptr, uintptr(len64)*et.size) {
+		throw("checkptr: unsafe.Slice result straddles multiple allocations")
+	}
 }
 
 func panicunsafeslicelen() {
diff --git a/src/runtime/testdata/testprog/checkptr.go b/src/runtime/testdata/testprog/checkptr.go
index e0a2794..f76b64a 100644
--- a/src/runtime/testdata/testprog/checkptr.go
+++ b/src/runtime/testdata/testprog/checkptr.go
@@ -13,6 +13,8 @@
 	register("CheckPtrArithmetic2", CheckPtrArithmetic2)
 	register("CheckPtrSize", CheckPtrSize)
 	register("CheckPtrSmall", CheckPtrSmall)
+	register("CheckPtrSliceOK", CheckPtrSliceOK)
+	register("CheckPtrSliceFail", CheckPtrSliceFail)
 }
 
 func CheckPtrAlignmentNoPtr() {
@@ -49,3 +51,14 @@
 func CheckPtrSmall() {
 	sink2 = unsafe.Pointer(uintptr(1))
 }
+
+func CheckPtrSliceOK() {
+	p := new([4]int64)
+	sink2 = unsafe.Slice(&p[1], 3)
+}
+
+func CheckPtrSliceFail() {
+	p := new(int64)
+	sink2 = p
+	sink2 = unsafe.Slice(p, 100)
+}
diff --git a/src/unsafe/unsafe.go b/src/unsafe/unsafe.go
index ecbd28c..eaf72c9 100644
--- a/src/unsafe/unsafe.go
+++ b/src/unsafe/unsafe.go
@@ -221,8 +221,11 @@
 //
 //	(*[len]ArbitraryType)(unsafe.Pointer(ptr))[:]
 //
+// As a special case, if ptr is nil and len is zero, Slice returns nil.
+//
 // The len argument must be of integer type or an untyped constant.
 // A constant len argument must be non-negative and representable by a value of type int;
 // if it is an untyped constant it is given type int.
-// If ptr is nil or len is negative at run time, a run-time panic occurs.
+// At run time, if len is negative, or if ptr is nil and len is not zero,
+// a run-time panic occurs.
 func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
diff --git a/test/fixedbugs/issue46957.go b/test/fixedbugs/issue46957.go
new file mode 100644
index 0000000..f3ed3c3
--- /dev/null
+++ b/test/fixedbugs/issue46957.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2021 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 main
+
+func f(a int, b ...int) {}
+
+func main() {
+	f(nil...) // ERROR "not enough arguments in call to f$"
+}
diff --git a/test/unsafebuiltins.go b/test/unsafebuiltins.go
index c10f808..4c940aa 100644
--- a/test/unsafebuiltins.go
+++ b/test/unsafebuiltins.go
@@ -30,8 +30,11 @@
 		assert(len(s) == len(p))
 		assert(cap(s) == len(p))
 
-		// nil pointer
-		mustPanic(func() { _ = unsafe.Slice((*int)(nil), 0) })
+		// nil pointer with zero length returns nil
+		assert(unsafe.Slice((*int)(nil), 0) == nil)
+
+		// nil pointer with positive length panics
+		mustPanic(func() { _ = unsafe.Slice((*int)(nil), 1) })
 
 		// negative length
 		var neg int = -1