[dev.cmdgo] all: merge master (5e6a7e9) into dev.cmdgo

Merge List:

+ 2021-08-26 5e6a7e9b86 embed: remove reference to global variables in docs
+ 2021-08-26 166b691b65 cmd/compile/internal/types2: remove need for instance (struct)
+ 2021-08-26 d6bdae33e9 cmd/compile/internal/types2: address some TODOs (cleanup)
+ 2021-08-26 770df2e18d crypto/tls: fix typo in PreferServerCipherSuites comment
+ 2021-08-26 a6ff433d6a cmd/go: pass -gcflags after other flags generated by the go command
+ 2021-08-25 4f2620285d cmd/compile/internal/types2: fix type set printing and add test
+ 2021-08-25 0ac64f6d70 cmd/compile/internal/types2: rename IsMethodSet to IsConstraint (cleanup)
+ 2021-08-25 4068fb6c21 cmd/compile: always accept 1.18 syntax but complain if not 1.18
+ 2021-08-25 bf0bc4122f go/types, types2: don't re-evaluate context string for each function argument (optimization)
+ 2021-08-25 4158e88f64 cmd/compile/internal/syntax: fix position of type parameter field
+ 2021-08-25 647bef6c59 go/types: implement NewTypeList and use it instead of composite literals
+ 2021-08-25 6cf1d5d0fa cmd/compile: generic SSA rules for simplifying 2 and 3 operand integer arithmetic expressions
+ 2021-08-25 5baf60d472 bytes, strings: optimize Trim for single byte cutsets
+ 2021-08-25 3d667671ad cmd/compile: fix function contains no TParam in generic function
+ 2021-08-25 4f2ebfe34b cmd/compile: allow embed into any byte slice type
+ 2021-08-25 d2f002cb39 time/format: avoid growslice in time.String()/time.GoString()
+ 2021-08-25 08d4cc20ca cmd/compile: fix stencil call expression.
+ 2021-08-25 099b819085 cmd/compile: fix CheckSize() calculation for -G=3 and stencils
+ 2021-08-25 e1fcf8857e test: add test that caused gofrontend compiler crash
+ 2021-08-25 d37b8dedf7 test: add test case that gofrontend miscompiled
+ 2021-08-25 41b99dab0f os/user: don't skip TestLookupGroup if supported
+ 2021-08-25 de1c934b97 cmd/compile: fix checkptr false positive for (*[Big]T)(ptr)[:n:n] pattern
+ 2021-08-24 54cdef1f10 reflect: add MapIter.SetKey and MapIter.SetValue
+ 2021-08-24 5d863f89fe cmd/compile: simplify bad conversion check

Change-Id: I29ab927f0e47f44d82f9307c642900f75f4f678f
diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go
index ce52649..cd859d0 100644
--- a/src/bytes/bytes.go
+++ b/src/bytes/bytes.go
@@ -888,11 +888,6 @@
 }
 
 func makeCutsetFunc(cutset string) func(r rune) bool {
-	if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
-		return func(r rune) bool {
-			return r == rune(cutset[0])
-		}
-	}
 	if as, isASCII := makeASCIISet(cutset); isASCII {
 		return func(r rune) bool {
 			return r < utf8.RuneSelf && as.contains(byte(r))
@@ -911,21 +906,44 @@
 // Trim returns a subslice of s by slicing off all leading and
 // trailing UTF-8-encoded code points contained in cutset.
 func Trim(s []byte, cutset string) []byte {
+	if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
+		return trimLeftByte(trimRightByte(s, cutset[0]), cutset[0])
+	}
 	return TrimFunc(s, makeCutsetFunc(cutset))
 }
 
 // TrimLeft returns a subslice of s by slicing off all leading
 // UTF-8-encoded code points contained in cutset.
 func TrimLeft(s []byte, cutset string) []byte {
+	if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
+		return trimLeftByte(s, cutset[0])
+	}
 	return TrimLeftFunc(s, makeCutsetFunc(cutset))
 }
 
+func trimLeftByte(s []byte, c byte) []byte {
+	for len(s) > 0 && s[0] == c {
+		s = s[1:]
+	}
+	return s
+}
+
 // TrimRight returns a subslice of s by slicing off all trailing
 // UTF-8-encoded code points that are contained in cutset.
 func TrimRight(s []byte, cutset string) []byte {
+	if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
+		return trimRightByte(s, cutset[0])
+	}
 	return TrimRightFunc(s, makeCutsetFunc(cutset))
 }
 
+func trimRightByte(s []byte, c byte) []byte {
+	for len(s) > 0 && s[len(s)-1] == c {
+		s = s[:len(s)-1]
+	}
+	return s
+}
+
 // TrimSpace returns a subslice of s by slicing off all leading and
 // trailing white space, as defined by Unicode.
 func TrimSpace(s []byte) []byte {
diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go
index 544ee46..850b2ed 100644
--- a/src/bytes/bytes_test.go
+++ b/src/bytes/bytes_test.go
@@ -1251,7 +1251,9 @@
 	{"TrimLeft", "abba", "ab", ""},
 	{"TrimRight", "abba", "ab", ""},
 	{"TrimLeft", "abba", "a", "bba"},
+	{"TrimLeft", "abba", "b", "abba"},
 	{"TrimRight", "abba", "a", "abb"},
+	{"TrimRight", "abba", "b", "abba"},
 	{"Trim", "<tag>", "<>", "tag"},
 	{"Trim", "* listitem", " *", "listitem"},
 	{"Trim", `"quote"`, `"`, "quote"},
@@ -1963,6 +1965,13 @@
 	}
 }
 
+func BenchmarkTrimByte(b *testing.B) {
+	x := []byte("  the quick brown fox   ")
+	for i := 0; i < b.N; i++ {
+		Trim(x, " ")
+	}
+}
+
 func BenchmarkIndexPeriodic(b *testing.B) {
 	key := []byte{1, 1}
 	for _, skip := range [...]int{2, 4, 8, 16, 32, 64} {
diff --git a/src/cmd/compile/internal/ir/expr.go b/src/cmd/compile/internal/ir/expr.go
index f526d98..41de6bd 100644
--- a/src/cmd/compile/internal/ir/expr.go
+++ b/src/cmd/compile/internal/ir/expr.go
@@ -570,10 +570,11 @@
 // A SliceExpr is a slice expression X[Low:High] or X[Low:High:Max].
 type SliceExpr struct {
 	miniExpr
-	X    Node
-	Low  Node
-	High Node
-	Max  Node
+	X            Node
+	Low          Node
+	High         Node
+	Max          Node
+	CheckPtrCall *CallExpr
 }
 
 func NewSliceExpr(pos src.XPos, op Op, x, low, high, max Node) *SliceExpr {
diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go
index 2b67a91..e1b485b 100644
--- a/src/cmd/compile/internal/noder/noder.go
+++ b/src/cmd/compile/internal/noder/noder.go
@@ -35,7 +35,7 @@
 	supportsGenerics := base.Flag.G != 0 || buildcfg.Experiment.Unified
 
 	mode := syntax.CheckBranches
-	if supportsGenerics && types.AllowsGoVersion(types.LocalPkg, 1, 18) {
+	if supportsGenerics {
 		mode |= syntax.AllowGenerics
 	}
 
diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go
index 602e88c..b3ff4b8 100644
--- a/src/cmd/compile/internal/noder/stencil.go
+++ b/src/cmd/compile/internal/noder/stencil.go
@@ -732,21 +732,15 @@
 	g.instTypeList = append(g.instTypeList, subst.ts.InstTypeList...)
 
 	if doubleCheck {
-		okConvs := map[ir.Node]bool{}
 		ir.Visit(newf, func(n ir.Node) {
-			if n.Op() == ir.OIDATA {
-				// IDATA(OCONVIFACE(x)) is ok, as we don't use the type of x.
-				// TODO: use some other op besides OCONVIFACE. ONEW might work
-				// (with appropriate direct vs. indirect interface cases).
-				okConvs[n.(*ir.UnaryExpr).X] = true
+			if n.Op() != ir.OCONVIFACE {
+				return
 			}
-			if n.Op() == ir.OCONVIFACE && !okConvs[n] {
-				c := n.(*ir.ConvExpr)
-				if c.X.Type().HasShape() {
-					ir.Dump("BAD FUNCTION", newf)
-					ir.Dump("BAD CONVERSION", c)
-					base.Fatalf("converting shape type to interface")
-				}
+			c := n.(*ir.ConvExpr)
+			if c.X.Type().HasShape() {
+				ir.Dump("BAD FUNCTION", newf)
+				ir.Dump("BAD CONVERSION", c)
+				base.Fatalf("converting shape type to interface")
 			}
 		})
 	}
@@ -1054,6 +1048,13 @@
 			case ir.OCLOSURE:
 				transformCall(call)
 
+			case ir.ODEREF, ir.OINDEX, ir.OINDEXMAP, ir.ORECV:
+				// Transform a call that was delayed because of the
+				// use of typeparam inside an expression that required
+				// a pointer dereference, array indexing, map indexing,
+				// or channel receive to compute function value.
+				transformCall(call)
+
 			case ir.OFUNCINST:
 				// A call with an OFUNCINST will get transformed
 				// in stencil() once we have created & attached the
diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go
index 541ed68..c9f7c2b 100644
--- a/src/cmd/compile/internal/noder/types.go
+++ b/src/cmd/compile/internal/noder/types.go
@@ -30,21 +30,11 @@
 // typ converts a types2.Type to a types.Type, including caching of previously
 // translated types.
 func (g *irgen) typ(typ types2.Type) *types.Type {
+	// Defer the CheckSize calls until we have fully-defined a
+	// (possibly-recursive) top-level type.
+	types.DeferCheckSize()
 	res := g.typ1(typ)
-
-	// Calculate the size for all concrete types seen by the frontend. The old
-	// typechecker calls CheckSize() a lot, and we want to eliminate calling
-	// it eventually, so we should do it here instead. We only call it for
-	// top-level types (i.e. we do it here rather in typ1), to make sure that
-	// recursive types have been fully constructed before we call CheckSize.
-	if res != nil && !res.IsUntyped() && !res.IsFuncArgStruct() && !res.HasTParam() {
-		types.CheckSize(res)
-		if res.IsPtr() {
-			// Pointers always have their size set, even though their element
-			// may not have its size set.
-			types.CheckSize(res.Elem())
-		}
-	}
+	types.ResumeCheckSize()
 	return res
 }
 
@@ -59,6 +49,12 @@
 	res, ok := g.typs[typ]
 	if !ok {
 		res = g.typ0(typ)
+		// Calculate the size for all concrete types seen by the frontend.
+		// This is the replacement for the CheckSize() calls in the types1
+		// typechecker. These will be deferred until the top-level g.typ().
+		if res != nil && !res.IsUntyped() && !res.IsFuncArgStruct() && !res.HasTParam() {
+			types.CheckSize(res)
+		}
 		g.typs[typ] = res
 	}
 	return res
diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules
index 5cbc70c..e7ee3d0 100644
--- a/src/cmd/compile/internal/ssa/gen/generic.rules
+++ b/src/cmd/compile/internal/ssa/gen/generic.rules
@@ -590,6 +590,10 @@
 // simplifications often used for lengths.  e.g. len(s[i:i+5])==5
 (Sub(64|32|16|8) (Add(64|32|16|8) x y) x) => y
 (Sub(64|32|16|8) (Add(64|32|16|8) x y) y) => x
+(Sub(64|32|16|8) (Sub(64|32|16|8) x y) x) => (Neg(64|32|16|8) y)
+(Sub(64|32|16|8) x (Add(64|32|16|8) x y)) => (Neg(64|32|16|8) y)
+(Add(64|32|16|8) x (Sub(64|32|16|8) y x)) => y
+(Add(64|32|16|8) x (Add(64|32|16|8) y (Sub(64|32|16|8) z x))) => (Add(64|32|16|8) y z)
 
 // basic phi simplifications
 (Phi (Const8  [c]) (Const8  [c])) => (Const8  [c])
diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go
index 5225820..e2f9e3e 100644
--- a/src/cmd/compile/internal/ssa/rewritegeneric.go
+++ b/src/cmd/compile/internal/ssa/rewritegeneric.go
@@ -533,6 +533,52 @@
 		}
 		break
 	}
+	// match: (Add16 x (Sub16 y x))
+	// result: y
+	for {
+		for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+			x := v_0
+			if v_1.Op != OpSub16 {
+				continue
+			}
+			_ = v_1.Args[1]
+			y := v_1.Args[0]
+			if x != v_1.Args[1] {
+				continue
+			}
+			v.copyOf(y)
+			return true
+		}
+		break
+	}
+	// match: (Add16 x (Add16 y (Sub16 z x)))
+	// result: (Add16 y z)
+	for {
+		for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+			x := v_0
+			if v_1.Op != OpAdd16 {
+				continue
+			}
+			_ = v_1.Args[1]
+			v_1_0 := v_1.Args[0]
+			v_1_1 := v_1.Args[1]
+			for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+				y := v_1_0
+				if v_1_1.Op != OpSub16 {
+					continue
+				}
+				_ = v_1_1.Args[1]
+				z := v_1_1.Args[0]
+				if x != v_1_1.Args[1] {
+					continue
+				}
+				v.reset(OpAdd16)
+				v.AddArg2(y, z)
+				return true
+			}
+		}
+		break
+	}
 	// match: (Add16 (Add16 i:(Const16 <t>) z) x)
 	// cond: (z.Op != OpConst16 && x.Op != OpConst16)
 	// result: (Add16 i (Add16 <t> z x))
@@ -732,6 +778,52 @@
 		}
 		break
 	}
+	// match: (Add32 x (Sub32 y x))
+	// result: y
+	for {
+		for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+			x := v_0
+			if v_1.Op != OpSub32 {
+				continue
+			}
+			_ = v_1.Args[1]
+			y := v_1.Args[0]
+			if x != v_1.Args[1] {
+				continue
+			}
+			v.copyOf(y)
+			return true
+		}
+		break
+	}
+	// match: (Add32 x (Add32 y (Sub32 z x)))
+	// result: (Add32 y z)
+	for {
+		for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+			x := v_0
+			if v_1.Op != OpAdd32 {
+				continue
+			}
+			_ = v_1.Args[1]
+			v_1_0 := v_1.Args[0]
+			v_1_1 := v_1.Args[1]
+			for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+				y := v_1_0
+				if v_1_1.Op != OpSub32 {
+					continue
+				}
+				_ = v_1_1.Args[1]
+				z := v_1_1.Args[0]
+				if x != v_1_1.Args[1] {
+					continue
+				}
+				v.reset(OpAdd32)
+				v.AddArg2(y, z)
+				return true
+			}
+		}
+		break
+	}
 	// match: (Add32 (Add32 i:(Const32 <t>) z) x)
 	// cond: (z.Op != OpConst32 && x.Op != OpConst32)
 	// result: (Add32 i (Add32 <t> z x))
@@ -958,6 +1050,52 @@
 		}
 		break
 	}
+	// match: (Add64 x (Sub64 y x))
+	// result: y
+	for {
+		for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+			x := v_0
+			if v_1.Op != OpSub64 {
+				continue
+			}
+			_ = v_1.Args[1]
+			y := v_1.Args[0]
+			if x != v_1.Args[1] {
+				continue
+			}
+			v.copyOf(y)
+			return true
+		}
+		break
+	}
+	// match: (Add64 x (Add64 y (Sub64 z x)))
+	// result: (Add64 y z)
+	for {
+		for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+			x := v_0
+			if v_1.Op != OpAdd64 {
+				continue
+			}
+			_ = v_1.Args[1]
+			v_1_0 := v_1.Args[0]
+			v_1_1 := v_1.Args[1]
+			for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+				y := v_1_0
+				if v_1_1.Op != OpSub64 {
+					continue
+				}
+				_ = v_1_1.Args[1]
+				z := v_1_1.Args[0]
+				if x != v_1_1.Args[1] {
+					continue
+				}
+				v.reset(OpAdd64)
+				v.AddArg2(y, z)
+				return true
+			}
+		}
+		break
+	}
 	// match: (Add64 (Add64 i:(Const64 <t>) z) x)
 	// cond: (z.Op != OpConst64 && x.Op != OpConst64)
 	// result: (Add64 i (Add64 <t> z x))
@@ -1184,6 +1322,52 @@
 		}
 		break
 	}
+	// match: (Add8 x (Sub8 y x))
+	// result: y
+	for {
+		for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+			x := v_0
+			if v_1.Op != OpSub8 {
+				continue
+			}
+			_ = v_1.Args[1]
+			y := v_1.Args[0]
+			if x != v_1.Args[1] {
+				continue
+			}
+			v.copyOf(y)
+			return true
+		}
+		break
+	}
+	// match: (Add8 x (Add8 y (Sub8 z x)))
+	// result: (Add8 y z)
+	for {
+		for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
+			x := v_0
+			if v_1.Op != OpAdd8 {
+				continue
+			}
+			_ = v_1.Args[1]
+			v_1_0 := v_1.Args[0]
+			v_1_1 := v_1.Args[1]
+			for _i1 := 0; _i1 <= 1; _i1, v_1_0, v_1_1 = _i1+1, v_1_1, v_1_0 {
+				y := v_1_0
+				if v_1_1.Op != OpSub8 {
+					continue
+				}
+				_ = v_1_1.Args[1]
+				z := v_1_1.Args[0]
+				if x != v_1_1.Args[1] {
+					continue
+				}
+				v.reset(OpAdd8)
+				v.AddArg2(y, z)
+				return true
+			}
+		}
+		break
+	}
 	// match: (Add8 (Add8 i:(Const8 <t>) z) x)
 	// cond: (z.Op != OpConst8 && x.Op != OpConst8)
 	// result: (Add8 i (Add8 <t> z x))
@@ -22590,6 +22774,42 @@
 		}
 		break
 	}
+	// match: (Sub16 (Sub16 x y) x)
+	// result: (Neg16 y)
+	for {
+		if v_0.Op != OpSub16 {
+			break
+		}
+		y := v_0.Args[1]
+		x := v_0.Args[0]
+		if x != v_1 {
+			break
+		}
+		v.reset(OpNeg16)
+		v.AddArg(y)
+		return true
+	}
+	// match: (Sub16 x (Add16 x y))
+	// result: (Neg16 y)
+	for {
+		x := v_0
+		if v_1.Op != OpAdd16 {
+			break
+		}
+		_ = v_1.Args[1]
+		v_1_0 := v_1.Args[0]
+		v_1_1 := v_1.Args[1]
+		for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+			if x != v_1_0 {
+				continue
+			}
+			y := v_1_1
+			v.reset(OpNeg16)
+			v.AddArg(y)
+			return true
+		}
+		break
+	}
 	// match: (Sub16 x (Sub16 i:(Const16 <t>) z))
 	// cond: (z.Op != OpConst16 && x.Op != OpConst16)
 	// result: (Sub16 (Add16 <t> x z) i)
@@ -22869,6 +23089,42 @@
 		}
 		break
 	}
+	// match: (Sub32 (Sub32 x y) x)
+	// result: (Neg32 y)
+	for {
+		if v_0.Op != OpSub32 {
+			break
+		}
+		y := v_0.Args[1]
+		x := v_0.Args[0]
+		if x != v_1 {
+			break
+		}
+		v.reset(OpNeg32)
+		v.AddArg(y)
+		return true
+	}
+	// match: (Sub32 x (Add32 x y))
+	// result: (Neg32 y)
+	for {
+		x := v_0
+		if v_1.Op != OpAdd32 {
+			break
+		}
+		_ = v_1.Args[1]
+		v_1_0 := v_1.Args[0]
+		v_1_1 := v_1.Args[1]
+		for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+			if x != v_1_0 {
+				continue
+			}
+			y := v_1_1
+			v.reset(OpNeg32)
+			v.AddArg(y)
+			return true
+		}
+		break
+	}
 	// match: (Sub32 x (Sub32 i:(Const32 <t>) z))
 	// cond: (z.Op != OpConst32 && x.Op != OpConst32)
 	// result: (Sub32 (Add32 <t> x z) i)
@@ -23172,6 +23428,42 @@
 		}
 		break
 	}
+	// match: (Sub64 (Sub64 x y) x)
+	// result: (Neg64 y)
+	for {
+		if v_0.Op != OpSub64 {
+			break
+		}
+		y := v_0.Args[1]
+		x := v_0.Args[0]
+		if x != v_1 {
+			break
+		}
+		v.reset(OpNeg64)
+		v.AddArg(y)
+		return true
+	}
+	// match: (Sub64 x (Add64 x y))
+	// result: (Neg64 y)
+	for {
+		x := v_0
+		if v_1.Op != OpAdd64 {
+			break
+		}
+		_ = v_1.Args[1]
+		v_1_0 := v_1.Args[0]
+		v_1_1 := v_1.Args[1]
+		for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+			if x != v_1_0 {
+				continue
+			}
+			y := v_1_1
+			v.reset(OpNeg64)
+			v.AddArg(y)
+			return true
+		}
+		break
+	}
 	// match: (Sub64 x (Sub64 i:(Const64 <t>) z))
 	// cond: (z.Op != OpConst64 && x.Op != OpConst64)
 	// result: (Sub64 (Add64 <t> x z) i)
@@ -23475,6 +23767,42 @@
 		}
 		break
 	}
+	// match: (Sub8 (Sub8 x y) x)
+	// result: (Neg8 y)
+	for {
+		if v_0.Op != OpSub8 {
+			break
+		}
+		y := v_0.Args[1]
+		x := v_0.Args[0]
+		if x != v_1 {
+			break
+		}
+		v.reset(OpNeg8)
+		v.AddArg(y)
+		return true
+	}
+	// match: (Sub8 x (Add8 x y))
+	// result: (Neg8 y)
+	for {
+		x := v_0
+		if v_1.Op != OpAdd8 {
+			break
+		}
+		_ = v_1.Args[1]
+		v_1_0 := v_1.Args[0]
+		v_1_1 := v_1.Args[1]
+		for _i0 := 0; _i0 <= 1; _i0, v_1_0, v_1_1 = _i0+1, v_1_1, v_1_0 {
+			if x != v_1_0 {
+				continue
+			}
+			y := v_1_1
+			v.reset(OpNeg8)
+			v.AddArg(y)
+			return true
+		}
+		break
+	}
 	// match: (Sub8 x (Sub8 i:(Const8 <t>) z))
 	// cond: (z.Op != OpConst8 && x.Op != OpConst8)
 	// result: (Sub8 (Add8 <t> x z) i)
diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go
index 39d3b20..0a48f6b 100644
--- a/src/cmd/compile/internal/ssagen/ssa.go
+++ b/src/cmd/compile/internal/ssagen/ssa.go
@@ -3090,6 +3090,9 @@
 			k = s.expr(n.Max)
 		}
 		p, l, c := s.slice(v, i, j, k, n.Bounded())
+		if n.CheckPtrCall != nil {
+			s.stmt(n.CheckPtrCall)
+		}
 		return s.newValue3(ssa.OpSliceMake, n.Type(), p, l, c)
 
 	case ir.OSLICESTR:
diff --git a/src/cmd/compile/internal/staticdata/embed.go b/src/cmd/compile/internal/staticdata/embed.go
index 0730d34..627c98b 100644
--- a/src/cmd/compile/internal/staticdata/embed.go
+++ b/src/cmd/compile/internal/staticdata/embed.go
@@ -73,7 +73,7 @@
 	if typ.Kind() == types.TSTRING {
 		return embedString
 	}
-	if typ.Sym() == nil && typ.IsSlice() && typ.Elem().Kind() == types.TUINT8 {
+	if typ.IsSlice() && typ.Elem().Kind() == types.TUINT8 {
 		return embedBytes
 	}
 	return embedUnknown
diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go
index c477ddd..fd97279 100644
--- a/src/cmd/compile/internal/syntax/parser.go
+++ b/src/cmd/compile/internal/syntax/parser.go
@@ -1840,7 +1840,11 @@
 	}
 
 	f := new(Field)
-	f.pos = p.pos()
+	if name != nil {
+		f.pos = name.pos
+	} else {
+		f.pos = p.pos()
+	}
 
 	if p.tok == _Name || name != nil {
 		if name == nil {
diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go
index 7ae10ef..8d05356 100644
--- a/src/cmd/compile/internal/typecheck/subr.go
+++ b/src/cmd/compile/internal/typecheck/subr.go
@@ -1003,6 +1003,15 @@
 // result is t; otherwise the result is a new type. It deals with recursive types
 // by using TFORW types and finding partially or fully created types via sym.Def.
 func (ts *Tsubster) Typ(t *types.Type) *types.Type {
+	// Defer the CheckSize calls until we have fully-defined
+	// (possibly-recursive) top-level type.
+	types.DeferCheckSize()
+	r := ts.typ1(t)
+	types.ResumeCheckSize()
+	return r
+}
+
+func (ts *Tsubster) typ1(t *types.Type) *types.Type {
 	if !t.HasTParam() && t.Kind() != types.TFUNC {
 		// Note: function types need to be copied regardless, as the
 		// types of closures may contain declarations that need
@@ -1042,12 +1051,13 @@
 	var targsChanged bool
 	var forw *types.Type
 
-	if t.Sym() != nil {
+	if t.Sym() != nil && t.HasTParam() {
+		// Need to test for t.HasTParam() again because of special TFUNC case above.
 		// Translate the type params for this type according to
 		// the tparam/targs mapping from subst.
 		neededTargs = make([]*types.Type, len(t.RParams()))
 		for i, rparam := range t.RParams() {
-			neededTargs[i] = ts.Typ(rparam)
+			neededTargs[i] = ts.typ1(rparam)
 			if !types.Identical(neededTargs[i], rparam) {
 				targsChanged = true
 			}
@@ -1085,26 +1095,26 @@
 		}
 		// Substitute the underlying typeparam (e.g. T in P[T], see
 		// the example describing type P[T] above).
-		newt = ts.Typ(t.Underlying())
+		newt = ts.typ1(t.Underlying())
 		assert(newt != t)
 
 	case types.TARRAY:
 		elem := t.Elem()
-		newelem := ts.Typ(elem)
+		newelem := ts.typ1(elem)
 		if newelem != elem || targsChanged {
 			newt = types.NewArray(newelem, t.NumElem())
 		}
 
 	case types.TPTR:
 		elem := t.Elem()
-		newelem := ts.Typ(elem)
+		newelem := ts.typ1(elem)
 		if newelem != elem || targsChanged {
 			newt = types.NewPtr(newelem)
 		}
 
 	case types.TSLICE:
 		elem := t.Elem()
-		newelem := ts.Typ(elem)
+		newelem := ts.typ1(elem)
 		if newelem != elem || targsChanged {
 			newt = types.NewSlice(newelem)
 		}
@@ -1159,22 +1169,17 @@
 		}
 
 	case types.TMAP:
-		newkey := ts.Typ(t.Key())
-		newval := ts.Typ(t.Elem())
+		newkey := ts.typ1(t.Key())
+		newval := ts.typ1(t.Elem())
 		if newkey != t.Key() || newval != t.Elem() || targsChanged {
 			newt = types.NewMap(newkey, newval)
 		}
 
 	case types.TCHAN:
 		elem := t.Elem()
-		newelem := ts.Typ(elem)
+		newelem := ts.typ1(elem)
 		if newelem != elem || targsChanged {
 			newt = types.NewChan(newelem, t.ChanDir())
-			if !newt.HasTParam() {
-				// TODO(danscales): not sure why I have to do this
-				// only for channels.....
-				types.CheckSize(newt)
-			}
 		}
 	case types.TFORW:
 		if ts.SubstForwFunc != nil {
@@ -1194,7 +1199,7 @@
 		for i := 0; i < nt; i++ {
 			term, tilde := t.Term(i)
 			tildes[i] = tilde
-			newterms[i] = ts.Typ(term)
+			newterms[i] = ts.typ1(term)
 			if newterms[i] != term {
 				changed = true
 			}
@@ -1212,24 +1217,24 @@
 		return t
 	}
 
-	if t.Sym() == nil && t.Kind() != types.TINTER {
-		// Not a named type or interface type, so there was no forwarding type
-		// and there are no methods to substitute.
-		assert(t.Methods().Len() == 0)
-		return newt
-	}
-
 	if forw != nil {
 		forw.SetUnderlying(newt)
 		newt = forw
 	}
 
+	if !newt.HasTParam() {
+		// Calculate the size of any new types created. These will be
+		// deferred until the top-level ts.Typ() or g.typ() (if this is
+		// called from g.fillinMethods()).
+		types.CheckSize(newt)
+	}
+
 	if t.Kind() != types.TINTER && t.Methods().Len() > 0 {
 		// Fill in the method info for the new type.
 		var newfields []*types.Field
 		newfields = make([]*types.Field, t.Methods().Len())
 		for i, f := range t.Methods().Slice() {
-			t2 := ts.Typ(f.Type)
+			t2 := ts.typ1(f.Type)
 			oldsym := f.Nname.Sym()
 			newsym := MakeFuncInstSym(oldsym, ts.Targs, true)
 			var nname *ir.Name
@@ -1272,7 +1277,7 @@
 		newfields = make([]*types.Field, t.NumFields())
 	}
 	for i, f := range t.Fields().Slice() {
-		t2 := ts.Typ(f.Type)
+		t2 := ts.typ1(f.Type)
 		if (t2 != f.Type || f.Nname != nil) && newfields == nil {
 			newfields = make([]*types.Field, t.NumFields())
 			for j := 0; j < i; j++ {
@@ -1325,7 +1330,7 @@
 	}
 	var newfields []*types.Field
 	for i, f := range t.Methods().Slice() {
-		t2 := ts.Typ(f.Type)
+		t2 := ts.typ1(f.Type)
 		if (t2 != f.Type || f.Nname != nil) && newfields == nil {
 			newfields = make([]*types.Field, t.Methods().Len())
 			for j := 0; j < i; j++ {
diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go
index 538fdc0..0b062b4 100644
--- a/src/cmd/compile/internal/types2/call.go
+++ b/src/cmd/compile/internal/types2/call.go
@@ -15,6 +15,10 @@
 // funcInst type-checks a function instantiation inst and returns the result in x.
 // The operand x must be the evaluation of inst.X and its type must be a signature.
 func (check *Checker) funcInst(x *operand, inst *syntax.IndexExpr) {
+	if !check.allowVersion(check.pkg, 1, 18) {
+		check.softErrorf(inst.Pos(), "function instantiation requires go1.18 or later")
+	}
+
 	xlist := unpackExpr(inst.Index)
 	targs := check.typeList(xlist)
 	if targs == nil {
@@ -318,6 +322,13 @@
 
 	// infer type arguments and instantiate signature if necessary
 	if sig.TParams().Len() > 0 {
+		if !check.allowVersion(check.pkg, 1, 18) {
+			if iexpr, _ := call.Fun.(*syntax.IndexExpr); iexpr != nil {
+				check.softErrorf(iexpr.Pos(), "function instantiation requires go1.18 or later")
+			} else {
+				check.softErrorf(call.Pos(), "implicit function instantiation requires go1.18 or later")
+			}
+		}
 		// TODO(gri) provide position information for targs so we can feed
 		//           it to the instantiate call for better error reporting
 		targs := check.infer(call.Pos(), sig.TParams().list(), targs, sigParams, args, true)
@@ -341,8 +352,11 @@
 	}
 
 	// check arguments
-	for i, a := range args {
-		check.assignment(a, sigParams.vars[i].typ, check.sprintf("argument to %s", call.Fun))
+	if len(args) > 0 {
+		context := check.sprintf("argument to %s", call.Fun)
+		for i, a := range args {
+			check.assignment(a, sigParams.vars[i].typ, context)
+		}
 	}
 
 	return
diff --git a/src/cmd/compile/internal/types2/check_test.go b/src/cmd/compile/internal/types2/check_test.go
index 41b0c54..bc68e76 100644
--- a/src/cmd/compile/internal/types2/check_test.go
+++ b/src/cmd/compile/internal/types2/check_test.go
@@ -20,9 +20,6 @@
 //		_ = x /* ERROR "not declared" */ + 1
 //	}
 
-// TODO(gri) Also collect strict mode errors of the form /* STRICT ... */
-//           and test against strict mode.
-
 package types2_test
 
 import (
diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go
index 342e109..d7a3354 100644
--- a/src/cmd/compile/internal/types2/decl.go
+++ b/src/cmd/compile/internal/types2/decl.go
@@ -514,11 +514,26 @@
 	check.initVars(lhs, []syntax.Expr{init}, nopos)
 }
 
+// isImportedConstraint reports whether typ is an imported type constraint.
+func (check *Checker) isImportedConstraint(typ Type) bool {
+	named, _ := typ.(*Named)
+	if named == nil || named.obj.pkg == check.pkg || named.obj.pkg == nil {
+		return false
+	}
+	u, _ := named.under().(*Interface)
+	return u != nil && u.IsConstraint()
+}
+
 func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named) {
 	assert(obj.typ == nil)
 
+	var rhs Type
 	check.later(func() {
 		check.validType(obj.typ, nil)
+		// If typ is local, an error was already reported where typ is specified/defined.
+		if check.isImportedConstraint(rhs) && !check.allowVersion(check.pkg, 1, 18) {
+			check.errorf(tdecl.Type.Pos(), "using type constraint %s requires go1.18 or later", rhs)
+		}
 	})
 
 	alias := tdecl.Alias
@@ -540,7 +555,8 @@
 		}
 
 		obj.typ = Typ[Invalid]
-		obj.typ = check.anyType(tdecl.Type)
+		rhs = check.anyType(tdecl.Type)
+		obj.typ = rhs
 		return
 	}
 
@@ -555,8 +571,9 @@
 	}
 
 	// determine underlying type of named
-	named.fromRHS = check.definedType(tdecl.Type, named)
-	assert(named.fromRHS != nil)
+	rhs = check.definedType(tdecl.Type, named)
+	assert(rhs != nil)
+	named.fromRHS = rhs
 	// The underlying type of named may be itself a named type that is
 	// incomplete:
 	//
diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go
index d108093..86a8444 100644
--- a/src/cmd/compile/internal/types2/expr.go
+++ b/src/cmd/compile/internal/types2/expr.go
@@ -127,9 +127,7 @@
 }
 
 // opName returns the name of an operation, or the empty string.
-// For now, only operations that might overflow are handled.
-// TODO(gri) Expand this to a general mechanism giving names to
-//           nodes?
+// Only operations that might overflow are handled.
 func opName(e *syntax.Operation) string {
 	op := int(e.Op)
 	if e.Y == nil {
diff --git a/src/cmd/compile/internal/types2/hilbert_test.go b/src/cmd/compile/internal/types2/hilbert_test.go
index 9f9dad6..03fea4f 100644
--- a/src/cmd/compile/internal/types2/hilbert_test.go
+++ b/src/cmd/compile/internal/types2/hilbert_test.go
@@ -29,8 +29,7 @@
 	}
 
 	// parse source
-	// TODO(gri) get rid of []bytes to string conversion below
-	f, err := parseSrc("hilbert.go", string(src))
+	f, err := syntax.Parse(syntax.NewFileBase("hilbert.go"), bytes.NewReader(src), nil, nil, 0)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go
index 8bea63e..f9cde24 100644
--- a/src/cmd/compile/internal/types2/instantiate.go
+++ b/src/cmd/compile/internal/types2/instantiate.go
@@ -122,27 +122,26 @@
 // instance creates a type or function instance using the given original type
 // typ and arguments targs. For Named types the resulting instance will be
 // unexpanded.
-func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) (res Type) {
-	// TODO(gri) What is better here: work with TypeParams, or work with TypeNames?
+func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) Type {
 	switch t := typ.(type) {
 	case *Named:
 		h := instantiatedHash(t, targs)
 		if check != nil {
-			// typ may already have been instantiated with identical type arguments. In
-			// that case, re-use the existing instance.
+			// typ may already have been instantiated with identical type arguments.
+			// In that case, re-use the existing instance.
 			if named := check.typMap[h]; named != nil {
 				return named
 			}
 		}
-
 		tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil)
 		named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded
 		named.targs = NewTypeList(targs)
-		named.instance = &instance{pos}
+		named.instPos = &pos
 		if check != nil {
 			check.typMap[h] = named
 		}
-		res = named
+		return named
+
 	case *Signature:
 		tparams := t.TParams()
 		if !check.validateTArgLen(pos, tparams.Len(), len(targs)) {
@@ -151,30 +150,22 @@
 		if tparams.Len() == 0 {
 			return typ // nothing to do (minor optimization)
 		}
-		defer func() {
-			// If we had an unexpected failure somewhere don't panic below when
-			// asserting res.(*Signature). Check for *Signature in case Typ[Invalid]
-			// is returned.
-			if _, ok := res.(*Signature); !ok {
-				return
-			}
-			// If the signature doesn't use its type parameters, subst
-			// will not make a copy. In that case, make a copy now (so
-			// we can set tparams to nil w/o causing side-effects).
-			if t == res {
-				copy := *t
-				res = &copy
-			}
-			// After instantiating a generic signature, it is not generic
-			// anymore; we need to set tparams to nil.
-			res.(*Signature).tparams = nil
-		}()
-		res = check.subst(pos, typ, makeSubstMap(tparams.list(), targs), nil)
-	default:
-		// only types and functions can be generic
-		panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
+		sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), nil).(*Signature)
+		// If the signature doesn't use its type parameters, subst
+		// will not make a copy. In that case, make a copy now (so
+		// we can set tparams to nil w/o causing side-effects).
+		if sig == t {
+			copy := *sig
+			sig = &copy
+		}
+		// After instantiating a generic signature, it is not generic
+		// anymore; we need to set tparams to nil.
+		sig.tparams = nil
+		return sig
 	}
-	return res
+
+	// only types and functions can be generic
+	panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
 }
 
 // validateTArgLen verifies that the length of targs and tparams matches,
diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go
index ccd3de0..e57158d 100644
--- a/src/cmd/compile/internal/types2/interface.go
+++ b/src/cmd/compile/internal/types2/interface.go
@@ -98,7 +98,7 @@
 func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() }
 
 // IsConstraint reports whether interface t is not just a method set.
-func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() }
+func (t *Interface) IsConstraint() bool { return t.typeSet().IsConstraint() }
 
 func (t *Interface) Underlying() Type { return t }
 func (t *Interface) String() string   { return TypeString(t, nil) }
diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go
index a3a2595..b4074aa 100644
--- a/src/cmd/compile/internal/types2/named.go
+++ b/src/cmd/compile/internal/types2/named.go
@@ -9,8 +9,6 @@
 	"sync"
 )
 
-// TODO(gri) Clean up Named struct below; specifically the fromRHS field (can we use underlying?).
-
 // A Named represents a named (defined) type.
 type Named struct {
 	check      *Checker
@@ -19,7 +17,7 @@
 	orig       *Named      // original, uninstantiated type
 	fromRHS    Type        // type (on RHS of declaration) this *Named type is derived from (for cycle reporting)
 	underlying Type        // possibly a *Named during setup; never a *Named once set up completely
-	instance   *instance   // position information for lazy instantiation, or nil
+	instPos    *syntax.Pos // position information for lazy instantiation, or nil
 	tparams    *TParamList // type parameters, or nil
 	targs      *TypeList   // type arguments (after instantiation), or nil
 	methods    []*Func     // methods declared for this type (not the method set of this type); signatures are type-checked lazily
@@ -242,24 +240,16 @@
 	}
 }
 
-// instance holds position information for use in lazy instantiation.
-//
-// TODO(rfindley): instance is probably unnecessary now. See if it can be
-// eliminated.
-type instance struct {
-	pos syntax.Pos // position of type instantiation; for error reporting only
-}
-
 // expand ensures that the underlying type of n is instantiated.
 // The underlying type will be Typ[Invalid] if there was an error.
 func (n *Named) expand(typMap map[string]*Named) *Named {
-	if n.instance != nil {
+	if n.instPos != nil {
 		// n must be loaded before instantiation, in order to have accurate
 		// tparams. This is done implicitly by the call to n.TParams, but making it
 		// explicit is harmless: load is idempotent.
 		n.load()
 		var u Type
-		if n.check.validateTArgLen(n.instance.pos, n.tparams.Len(), n.targs.Len()) {
+		if n.check.validateTArgLen(*n.instPos, n.tparams.Len(), n.targs.Len()) {
 			if typMap == nil {
 				if n.check != nil {
 					typMap = n.check.typMap
@@ -272,13 +262,13 @@
 					typMap = map[string]*Named{h: n}
 				}
 			}
-			u = n.check.subst(n.instance.pos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), typMap)
+			u = n.check.subst(*n.instPos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), typMap)
 		} else {
 			u = Typ[Invalid]
 		}
 		n.underlying = u
 		n.fromRHS = u
-		n.instance = nil
+		n.instPos = nil
 	}
 	return n
 }
diff --git a/src/cmd/compile/internal/types2/resolver.go b/src/cmd/compile/internal/types2/resolver.go
index 018a20c..34fbc3d 100644
--- a/src/cmd/compile/internal/types2/resolver.go
+++ b/src/cmd/compile/internal/types2/resolver.go
@@ -412,52 +412,60 @@
 				}
 
 			case *syntax.TypeDecl:
+				if len(s.TParamList) != 0 && !check.allowVersion(pkg, 1, 18) {
+					check.softErrorf(s.TParamList[0], "type parameters require go1.18 or later")
+				}
 				obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Value, nil)
 				check.declarePkgObj(s.Name, obj, &declInfo{file: fileScope, tdecl: s})
 
 			case *syntax.FuncDecl:
-				d := s // TODO(gri) get rid of this
-				name := d.Name.Value
-				obj := NewFunc(d.Name.Pos(), pkg, name, nil)
-				if d.Recv == nil {
+				name := s.Name.Value
+				obj := NewFunc(s.Name.Pos(), pkg, name, nil)
+				hasTParamError := false // avoid duplicate type parameter errors
+				if s.Recv == nil {
 					// regular function
 					if name == "init" || name == "main" && pkg.name == "main" {
-						if d.TParamList != nil {
-							check.softErrorf(d, "func %s must have no type parameters", name)
+						if len(s.TParamList) != 0 {
+							check.softErrorf(s.TParamList[0], "func %s must have no type parameters", name)
+							hasTParamError = true
 						}
-						if t := d.Type; len(t.ParamList) != 0 || len(t.ResultList) != 0 {
-							check.softErrorf(d, "func %s must have no arguments and no return values", name)
+						if t := s.Type; len(t.ParamList) != 0 || len(t.ResultList) != 0 {
+							check.softErrorf(s, "func %s must have no arguments and no return values", name)
 						}
 					}
 					// don't declare init functions in the package scope - they are invisible
 					if name == "init" {
 						obj.parent = pkg.scope
-						check.recordDef(d.Name, obj)
+						check.recordDef(s.Name, obj)
 						// init functions must have a body
-						if d.Body == nil {
+						if s.Body == nil {
 							// TODO(gri) make this error message consistent with the others above
 							check.softErrorf(obj.pos, "missing function body")
 						}
 					} else {
-						check.declare(pkg.scope, d.Name, obj, nopos)
+						check.declare(pkg.scope, s.Name, obj, nopos)
 					}
 				} else {
 					// method
 					// d.Recv != nil
-					if !acceptMethodTypeParams && len(d.TParamList) != 0 {
+					if !acceptMethodTypeParams && len(s.TParamList) != 0 {
 						//check.error(d.TParamList.Pos(), invalidAST + "method must have no type parameters")
-						check.error(d, invalidAST+"method must have no type parameters")
+						check.error(s.TParamList[0], invalidAST+"method must have no type parameters")
+						hasTParamError = true
 					}
-					ptr, recv, _ := check.unpackRecv(d.Recv.Type, false)
+					ptr, recv, _ := check.unpackRecv(s.Recv.Type, false)
 					// (Methods with invalid receiver cannot be associated to a type, and
 					// methods with blank _ names are never found; no need to collect any
 					// of them. They will still be type-checked with all the other functions.)
 					if recv != nil && name != "_" {
 						methods = append(methods, methodInfo{obj, ptr, recv})
 					}
-					check.recordDef(d.Name, obj)
+					check.recordDef(s.Name, obj)
 				}
-				info := &declInfo{file: fileScope, fdecl: d}
+				if len(s.TParamList) != 0 && !check.allowVersion(pkg, 1, 18) && !hasTParamError {
+					check.softErrorf(s.TParamList[0], "type parameters require go1.18 or later")
+				}
+				info := &declInfo{file: fileScope, fdecl: s}
 				// Methods are not package-level objects but we still track them in the
 				// object map so that we can handle them like regular functions (if the
 				// receiver is invalid); also we need their fdecl info when associating
diff --git a/src/cmd/compile/internal/types2/self_test.go b/src/cmd/compile/internal/types2/self_test.go
index 4722fec..e0d2e1b 100644
--- a/src/cmd/compile/internal/types2/self_test.go
+++ b/src/cmd/compile/internal/types2/self_test.go
@@ -24,12 +24,7 @@
 	conf := Config{Importer: defaultImporter()}
 	_, err = conf.Check("cmd/compile/internal/types2", files, nil)
 	if err != nil {
-		// Importing go/constant doesn't work in the
-		// build dashboard environment. Don't report an error
-		// for now so that the build remains green.
-		// TODO(gri) fix this
-		t.Log(err) // replace w/ t.Fatal eventually
-		return
+		t.Fatal(err)
 	}
 }
 
diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go
index f1bf60a..d28e7b8 100644
--- a/src/cmd/compile/internal/types2/signature.go
+++ b/src/cmd/compile/internal/types2/signature.go
@@ -150,12 +150,7 @@
 					// bound is (possibly) parameterized in the context of the
 					// receiver type declaration. Substitute parameters for the
 					// current context.
-					// TODO(gri) should we assume now that bounds always exist?
-					//           (no bound == empty interface)
-					if bound != nil {
-						bound = check.subst(tpar.obj.pos, bound, smap, nil)
-						tpar.bound = bound
-					}
+					tpar.bound = check.subst(tpar.obj.pos, bound, smap, nil)
 				}
 			}
 		}
diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go
index 7865c2d..8cfdf92 100644
--- a/src/cmd/compile/internal/types2/stmt.go
+++ b/src/cmd/compile/internal/types2/stmt.go
@@ -52,11 +52,6 @@
 		check.error(body.Rbrace, "missing return")
 	}
 
-	// TODO(gri) Should we make it an error to declare generic functions
-	//           where the type parameters are not used?
-	// 12/19/2018: Probably not - it can make sense to have an API with
-	//           all functions uniformly sharing the same type parameters.
-
 	// spec: "Implementation restriction: A compiler may make it illegal to
 	// declare a variable inside a function body if the variable is never used."
 	check.usage(sig.scope)
@@ -422,7 +417,6 @@
 		check.assignVar(lhs[0], &x)
 
 	case *syntax.CallStmt:
-		// TODO(gri) get rid of this conversion to string
 		kind := "go"
 		if s.Tok == syntax.Defer {
 			kind = "defer"
diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go
index 918e5f3..ff8dd13 100644
--- a/src/cmd/compile/internal/types2/subst.go
+++ b/src/cmd/compile/internal/types2/subst.go
@@ -38,7 +38,7 @@
 // subst returns the type typ with its type parameters tpars replaced by the
 // corresponding type arguments targs, recursively. subst doesn't modify the
 // incoming type. If a substitution took place, the result type is different
-// from from the incoming type.
+// from the incoming type.
 //
 // If the given typMap is non-nil, it is used in lieu of check.typMap.
 func (check *Checker) subst(pos syntax.Pos, typ Type, smap substMap, typMap map[string]*Named) Type {
diff --git a/src/cmd/compile/internal/types2/testdata/check/decls0.src b/src/cmd/compile/internal/types2/testdata/check/decls0.src
index f051a4f..09e5d5c 100644
--- a/src/cmd/compile/internal/types2/testdata/check/decls0.src
+++ b/src/cmd/compile/internal/types2/testdata/check/decls0.src
@@ -146,7 +146,7 @@
 		m1(I5)
 	}
 	I6 interface {
-		S0 /* ERROR "not an interface" */
+		S0 /* ERROR "non-interface type S0" */
 	}
 	I7 interface {
 		I1
diff --git a/src/cmd/compile/internal/types2/testdata/check/issues.src b/src/cmd/compile/internal/types2/testdata/check/issues.src
index 692ed37..d83a95a 100644
--- a/src/cmd/compile/internal/types2/testdata/check/issues.src
+++ b/src/cmd/compile/internal/types2/testdata/check/issues.src
@@ -79,11 +79,11 @@
 // Check that embedding a non-interface type in an interface results in a good error message.
 func issue10979() {
 	type _ interface {
-		int /* ERROR int is not an interface */
+		int /* ERROR non-interface type int */
 	}
 	type T struct{}
 	type _ interface {
-		T /* ERROR T is not an interface */
+		T /* ERROR non-interface type T */
 	}
 	type _ interface {
 		nosuchtype /* ERROR undeclared name: nosuchtype */
@@ -280,7 +280,7 @@
 }
 
 type issue25301c interface {
-	notE // ERROR struct\{\} is not an interface
+	notE // ERROR non-interface type struct\{\}
 }
 
 type notE = struct{}
diff --git a/src/cmd/compile/internal/types2/testdata/check/main.go2 b/src/cmd/compile/internal/types2/testdata/check/main.go2
index b7ddeaa..395e3bf 100644
--- a/src/cmd/compile/internal/types2/testdata/check/main.go2
+++ b/src/cmd/compile/internal/types2/testdata/check/main.go2
@@ -4,4 +4,4 @@
 
 package main
 
-func /* ERROR "func main must have no type parameters" */ main[T any]() {}
+func main [T /* ERROR "func main must have no type parameters" */ any]() {}
diff --git a/src/cmd/compile/internal/types2/testdata/check/tinference.go2 b/src/cmd/compile/internal/types2/testdata/check/tinference.go2
index 0afb77c..2409fef 100644
--- a/src/cmd/compile/internal/types2/testdata/check/tinference.go2
+++ b/src/cmd/compile/internal/types2/testdata/check/tinference.go2
@@ -15,7 +15,7 @@
 // 	f("a", "b", "c", "d")
 // 	f0("a", "b", "c", "d")
 // }
-// 
+//
 // func f1[A any, B interface{~A}](A, B)
 // func _() {
 // 	f := f1[int]
@@ -60,9 +60,7 @@
 	var _ string = x
 }
 
-// TODO(gri) Need to flag invalid recursive constraints. At the
-// moment these cause infinite recursions and stack overflow.
-// func f7[A interface{type B}, B interface{~A}]()
+func f7[A interface{*B}, B interface{~*A}]() {}
 
 // More realistic examples
 
diff --git a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2 b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
index 1ad80b1..765d561 100644
--- a/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
+++ b/src/cmd/compile/internal/types2/testdata/check/typeparams.go2
@@ -304,8 +304,8 @@
 // init functions cannot have type parameters
 
 func init() {}
-func init[/* ERROR func init must have no type parameters */ _ any]() {}
-func init[/* ERROR func init must have no type parameters */ P any]() {}
+func init[_ /* ERROR func init must have no type parameters */ any]() {}
+func init[P /* ERROR func init must have no type parameters */ any]() {}
 
 type T struct {}
 
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2
new file mode 100644
index 0000000..5334695
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue47818.go2
@@ -0,0 +1,59 @@
+// 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.
+
+// Parser accepts type parameters but the type checker
+// needs to report any operations that are not permitted
+// before Go 1.18.
+
+package go1_17
+
+type T[P /* ERROR type parameters require go1\.18 or later */ any] struct{}
+
+// for init (and main, but we're not in package main) we should only get one error
+func init[P /* ERROR func init must have no type parameters */ any]()   {}
+func main[P /* ERROR type parameters require go1\.18 or later */ any]() {}
+
+func f[P /* ERROR type parameters require go1\.18 or later */ any](x P) {
+	var _ T[ /* ERROR type instantiation requires go1\.18 or later */ int]
+	var _ (T[ /* ERROR type instantiation requires go1\.18 or later */ int])
+	_ = T[ /* ERROR type instantiation requires go1\.18 or later */ int]{}
+	_ = T[ /* ERROR type instantiation requires go1\.18 or later */ int](struct{}{})
+}
+
+func (T[ /* ERROR type instantiation requires go1\.18 or later */ P]) g(x int) {
+	f[ /* ERROR function instantiation requires go1\.18 or later */ int](0)     // explicit instantiation
+	(f[ /* ERROR function instantiation requires go1\.18 or later */ int])(0)   // parentheses (different code path)
+	f( /* ERROR implicit function instantiation requires go1\.18 or later */ x) // implicit instantiation
+}
+
+type C1 interface {
+	comparable // ERROR undeclared name: comparable \(requires version go1\.18 or later\)
+}
+
+type C2 interface {
+	comparable // ERROR undeclared name: comparable \(requires version go1\.18 or later\)
+	int        // ERROR embedding non-interface type int requires go1\.18 or later
+	~ /* ERROR embedding interface element ~int requires go1\.18 or later */ int
+	int /* ERROR embedding interface element int\|~string requires go1\.18 or later */ | ~string
+}
+
+type _ interface {
+	// errors for these were reported with their declaration
+	C1
+	C2
+}
+
+type (
+	_ comparable // ERROR undeclared name: comparable \(requires version go1\.18 or later\)
+	// errors for these were reported with their declaration
+	_ C1
+	_ C2
+
+	_ = comparable // ERROR undeclared name: comparable \(requires version go1\.18 or later\)
+	// errors for these were reported with their declaration
+	_ = C1
+	_ = C2
+)
+
+// TODO(gri) need test cases for imported constraint types (see also issue #47967)
\ No newline at end of file
diff --git a/src/cmd/compile/internal/types2/tuple.go b/src/cmd/compile/internal/types2/tuple.go
index a3946be..1356aae 100644
--- a/src/cmd/compile/internal/types2/tuple.go
+++ b/src/cmd/compile/internal/types2/tuple.go
@@ -16,8 +16,6 @@
 	if len(x) > 0 {
 		return &Tuple{vars: x}
 	}
-	// TODO(gri) Don't represent empty tuples with a (*Tuple)(nil) pointer;
-	//           it's too subtle and causes problems.
 	return nil
 }
 
diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go
index 4b8642a..ca5ecdc 100644
--- a/src/cmd/compile/internal/types2/type.go
+++ b/src/cmd/compile/internal/types2/type.go
@@ -34,7 +34,6 @@
 // under must only be called when a type is known
 // to be fully set up.
 func under(t Type) Type {
-	// TODO(gri) is this correct for *Union?
 	if n := asNamed(t); n != nil {
 		return n.under()
 	}
diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go
index 14596b6..ae39f26 100644
--- a/src/cmd/compile/internal/types2/typeset.go
+++ b/src/cmd/compile/internal/types2/typeset.go
@@ -30,10 +30,8 @@
 	return !s.comparable && len(s.methods) == 0 && s.terms.isAll()
 }
 
-// TODO(gri) IsMethodSet is not a great name for this predicate. Find a better one.
-
-// IsMethodSet reports whether the type set s is described by a single set of methods.
-func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isAll() }
+// IsConstraint reports whether type set s is not just a set of methods.
+func (s *_TypeSet) IsConstraint() bool { return s.comparable || !s.terms.isAll() }
 
 // IsComparable reports whether each type in the set is comparable.
 func (s *_TypeSet) IsComparable() bool {
@@ -79,26 +77,24 @@
 	var buf bytes.Buffer
 	buf.WriteByte('{')
 	if s.comparable {
-		buf.WriteString(" comparable")
+		buf.WriteString("comparable")
 		if hasMethods || hasTerms {
-			buf.WriteByte(';')
+			buf.WriteString("; ")
 		}
 	}
 	for i, m := range s.methods {
 		if i > 0 {
-			buf.WriteByte(';')
+			buf.WriteString("; ")
 		}
-		buf.WriteByte(' ')
 		buf.WriteString(m.String())
 	}
 	if hasMethods && hasTerms {
-		buf.WriteByte(';')
+		buf.WriteString("; ")
 	}
 	if hasTerms {
 		buf.WriteString(s.terms.String())
 	}
-	buf.WriteString(" }") // there was at least one method or term
-
+	buf.WriteString("}")
 	return buf.String()
 }
 
@@ -271,6 +267,11 @@
 		switch u := under(typ).(type) {
 		case *Interface:
 			tset := computeInterfaceTypeSet(check, pos, u)
+			// If typ is local, an error was already reported where typ is specified/defined.
+			if check != nil && check.isImportedConstraint(typ) && !check.allowVersion(check.pkg, 1, 18) {
+				check.errorf(pos, "embedding constraint interface %s requires go1.18 or later", typ)
+				continue
+			}
 			if tset.comparable {
 				ityp.tset.comparable = true
 			}
@@ -279,6 +280,10 @@
 			}
 			terms = tset.terms
 		case *Union:
+			if check != nil && !check.allowVersion(check.pkg, 1, 18) {
+				check.errorf(pos, "embedding interface element %s requires go1.18 or later", u)
+				continue
+			}
 			tset := computeUnionTypeSet(check, pos, u)
 			if tset == &invalidTypeSet {
 				continue // ignore invalid unions
@@ -293,7 +298,7 @@
 				continue
 			}
 			if check != nil && !check.allowVersion(check.pkg, 1, 18) {
-				check.errorf(pos, "%s is not an interface", typ)
+				check.errorf(pos, "embedding non-interface type %s requires go1.18 or later", typ)
 				continue
 			}
 			terms = termlist{{false, typ}}
diff --git a/src/cmd/compile/internal/types2/typeset_test.go b/src/cmd/compile/internal/types2/typeset_test.go
index 0e14d52..7f7cc06 100644
--- a/src/cmd/compile/internal/types2/typeset_test.go
+++ b/src/cmd/compile/internal/types2/typeset_test.go
@@ -4,7 +4,11 @@
 
 package types2
 
-import "testing"
+import (
+	"cmd/compile/internal/syntax"
+	"strings"
+	"testing"
+)
 
 func TestInvalidTypeSet(t *testing.T) {
 	if !invalidTypeSet.IsEmpty() {
@@ -12,4 +16,65 @@
 	}
 }
 
+func TestTypeSetString(t *testing.T) {
+	for body, want := range map[string]string{
+		"{}":            "𝓤",
+		"{int}":         "{int}",
+		"{~int}":        "{~int}",
+		"{int|string}":  "{int ∪ string}",
+		"{int; string}": "∅",
+
+		"{comparable}":              "{comparable}",
+		"{comparable; int}":         "{comparable; int}",
+		"{~int; comparable}":        "{comparable; ~int}",
+		"{int|string; comparable}":  "{comparable; int ∪ string}",
+		"{comparable; int; string}": "∅",
+
+		"{m()}":                         "{func (p.T).m()}",
+		"{m1(); m2() int }":             "{func (p.T).m1(); func (p.T).m2() int}",
+		"{error}":                       "{func (error).Error() string}",
+		"{m(); comparable}":             "{comparable; func (p.T).m()}",
+		"{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}",
+
+		"{E}; type E interface{}":           "𝓤",
+		"{E}; type E interface{int;string}": "∅",
+		"{E}; type E interface{comparable}": "{comparable}",
+	} {
+		// parse
+		errh := func(error) {} // dummy error handler so that parsing continues in presence of errors
+		src := "package p; type T interface" + body
+		file, err := syntax.Parse(nil, strings.NewReader(src), errh, nil, syntax.AllowGenerics)
+		if err != nil {
+			t.Fatalf("%s: %v (invalid test case)", body, err)
+		}
+
+		// type check
+		var conf Config
+		pkg, err := conf.Check(file.PkgName.Value, []*syntax.File{file}, nil)
+		if err != nil {
+			t.Fatalf("%s: %v (invalid test case)", body, err)
+		}
+
+		// lookup T
+		obj := pkg.scope.Lookup("T")
+		if obj == nil {
+			t.Fatalf("%s: T not found (invalid test case)", body)
+		}
+		T, ok := under(obj.Type()).(*Interface)
+		if !ok {
+			t.Fatalf("%s: %v is not an interface (invalid test case)", body, obj)
+		}
+
+		// verify test case
+		got := T.typeSet().String()
+		if got != want {
+			t.Errorf("%s: got %s; want %s", body, got, want)
+		}
+	}
+}
+
 // TODO(gri) add more tests
diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go
index 2c34d03..1775fc6 100644
--- a/src/cmd/compile/internal/types2/typestring.go
+++ b/src/cmd/compile/internal/types2/typestring.go
@@ -195,7 +195,7 @@
 		}
 
 	case *Named:
-		if t.instance != nil {
+		if t.instPos != nil {
 			buf.WriteByte(instanceMarker)
 		}
 		writeTypeName(buf, t.obj, qf)
@@ -279,6 +279,7 @@
 
 func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) {
 	if obj == nil {
+		assert(instanceHashing == 0) // we need an object for instance hashing
 		buf.WriteString("<Named w/o object>")
 		return
 	}
diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go
index 241c6d35..6938648 100644
--- a/src/cmd/compile/internal/types2/typexpr.go
+++ b/src/cmd/compile/internal/types2/typexpr.go
@@ -38,14 +38,12 @@
 		}
 		return
 	case universeAny, universeComparable:
+		// complain if necessary but keep going
 		if !check.allowVersion(check.pkg, 1, 18) {
-			check.errorf(e, "undeclared name: %s (requires version go1.18 or later)", e.Value)
-			return
-		}
-		// If we allow "any" for general use, this if-statement can be removed (issue #33232).
-		if obj == universeAny {
-			check.error(e, "cannot use any outside constraint position")
-			return
+			check.softErrorf(e, "undeclared name: %s (requires version go1.18 or later)", e.Value)
+		} else if obj == universeAny {
+			// If we allow "any" for general use, this if-statement can be removed (issue #33232).
+			check.softErrorf(e, "cannot use any outside constraint position")
 		}
 	}
 	check.recordUse(e, obj)
@@ -153,7 +151,7 @@
 	check.later(func() {
 		if t := asInterface(typ); t != nil {
 			tset := computeInterfaceTypeSet(check, pos, t) // TODO(gri) is this the correct position?
-			if !tset.IsMethodSet() {
+			if tset.IsConstraint() {
 				if tset.comparable {
 					check.softErrorf(pos, "interface is (or embeds) comparable")
 				} else {
@@ -274,6 +272,9 @@
 		}
 
 	case *syntax.IndexExpr:
+		if !check.allowVersion(check.pkg, 1, 18) {
+			check.softErrorf(e.Pos(), "type instantiation requires go1.18 or later")
+		}
 		return check.instantiatedType(e.X, unpackExpr(e.Index), def)
 
 	case *syntax.ParenExpr:
diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go
index d4fbebc..72542e7 100644
--- a/src/cmd/compile/internal/types2/unify.go
+++ b/src/cmd/compile/internal/types2/unify.go
@@ -433,9 +433,6 @@
 			xargs := x.targs.list()
 			yargs := y.targs.list()
 
-			// TODO(gri) This is not always correct: two types may have the same names
-			//           in the same package if one of them is nested in a function.
-			//           Extremely unlikely but we need an always correct solution.
 			if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name {
 				assert(len(xargs) == len(yargs))
 				for i, x := range xargs {
diff --git a/src/cmd/compile/internal/walk/convert.go b/src/cmd/compile/internal/walk/convert.go
index 27a07ce..f724ca7 100644
--- a/src/cmd/compile/internal/walk/convert.go
+++ b/src/cmd/compile/internal/walk/convert.go
@@ -413,11 +413,15 @@
 	return n
 }
 
-func walkCheckPtrAlignment(n *ir.ConvExpr, init *ir.Nodes, count ir.Node) ir.Node {
+func walkCheckPtrAlignment(n *ir.ConvExpr, init *ir.Nodes, se *ir.SliceExpr) ir.Node {
 	if !n.Type().IsPtr() {
 		base.Fatalf("expected pointer type: %v", n.Type())
 	}
 	elem := n.Type().Elem()
+	var count ir.Node
+	if se != nil {
+		count = se.Max
+	}
 	if count != nil {
 		if !elem.IsArray() {
 			base.Fatalf("expected array type: %v", elem)
@@ -435,7 +439,12 @@
 	}
 
 	n.X = cheapExpr(n.X, init)
-	init.Append(mkcall("checkptrAlignment", nil, init, typecheck.ConvNop(n.X, types.Types[types.TUNSAFEPTR]), reflectdata.TypePtr(elem), typecheck.Conv(count, types.Types[types.TUINTPTR])))
+	checkPtrCall := mkcall("checkptrAlignment", nil, init, typecheck.ConvNop(n.X, types.Types[types.TUNSAFEPTR]), reflectdata.TypePtr(elem), typecheck.Conv(count, types.Types[types.TUINTPTR]))
+	if se != nil {
+		se.CheckPtrCall = checkPtrCall
+	} else {
+		init.Append(checkPtrCall)
+	}
 	return n
 }
 
diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go
index 26e2254..c049981 100644
--- a/src/cmd/compile/internal/walk/expr.go
+++ b/src/cmd/compile/internal/walk/expr.go
@@ -824,7 +824,7 @@
 	n.High = walkExpr(n.High, init)
 	n.Max = walkExpr(n.Max, init)
 	if checkSlice {
-		n.X = walkCheckPtrAlignment(n.X.(*ir.ConvExpr), init, n.Max)
+		n.X = walkCheckPtrAlignment(n.X.(*ir.ConvExpr), init, n)
 	}
 
 	if n.Op().IsSlice3() {
diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go
index eee8adc..1cce5d4 100644
--- a/src/cmd/go/internal/work/gc.go
+++ b/src/cmd/go/internal/work/gc.go
@@ -75,7 +75,7 @@
 	}
 
 	pkgpath := pkgPath(a)
-	gcargs := []string{"-p", pkgpath}
+	gcflags := []string{"-p", pkgpath}
 	if p.Module != nil {
 		v := p.Module.GoVersion
 		if v == "" {
@@ -94,11 +94,11 @@
 			v = "1.16"
 		}
 		if allowedVersion(v) {
-			gcargs = append(gcargs, "-lang=go"+v)
+			gcflags = append(gcflags, "-lang=go"+v)
 		}
 	}
 	if p.Standard {
-		gcargs = append(gcargs, "-std")
+		gcflags = append(gcflags, "-std")
 	}
 	_, compilingRuntime := runtimePackages[p.ImportPath]
 	compilingRuntime = compilingRuntime && p.Standard
@@ -106,7 +106,7 @@
 		// runtime compiles with a special gc flag to check for
 		// memory allocations that are invalid in the runtime package,
 		// and to implement some special compiler pragmas.
-		gcargs = append(gcargs, "-+")
+		gcflags = append(gcflags, "-+")
 	}
 
 	// If we're giving the compiler the entire package (no C etc files), tell it that,
@@ -125,25 +125,25 @@
 		}
 	}
 	if extFiles == 0 {
-		gcargs = append(gcargs, "-complete")
+		gcflags = append(gcflags, "-complete")
 	}
 	if cfg.BuildContext.InstallSuffix != "" {
-		gcargs = append(gcargs, "-installsuffix", cfg.BuildContext.InstallSuffix)
+		gcflags = append(gcflags, "-installsuffix", cfg.BuildContext.InstallSuffix)
 	}
 	if a.buildID != "" {
-		gcargs = append(gcargs, "-buildid", a.buildID)
+		gcflags = append(gcflags, "-buildid", a.buildID)
 	}
 	if p.Internal.OmitDebug || cfg.Goos == "plan9" || cfg.Goarch == "wasm" {
-		gcargs = append(gcargs, "-dwarf=false")
+		gcflags = append(gcflags, "-dwarf=false")
 	}
 	if strings.HasPrefix(runtimeVersion, "go1") && !strings.Contains(os.Args[0], "go_bootstrap") {
-		gcargs = append(gcargs, "-goversion", runtimeVersion)
+		gcflags = append(gcflags, "-goversion", runtimeVersion)
 	}
 	if symabis != "" {
-		gcargs = append(gcargs, "-symabis", symabis)
+		gcflags = append(gcflags, "-symabis", symabis)
 	}
 
-	gcflags := str.StringList(forcedGcflags, p.Internal.Gcflags)
+	gcflags = append(gcflags, str.StringList(forcedGcflags, p.Internal.Gcflags)...)
 	if compilingRuntime {
 		// Remove -N, if present.
 		// It is not possible to build the runtime with no optimizations,
@@ -157,7 +157,7 @@
 		}
 	}
 
-	args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), gcflags, gcargs}
+	args := []interface{}{cfg.BuildToolexec, base.Tool("compile"), "-o", ofile, "-trimpath", a.trimpath(), gcflags}
 	if p.Internal.LocalPrefix != "" {
 		// Workaround #43883.
 		args = append(args, "-D", p.Internal.LocalPrefix)
diff --git a/src/cmd/go/testdata/script/build_gcflags_order.txt b/src/cmd/go/testdata/script/build_gcflags_order.txt
new file mode 100644
index 0000000..0ffe157
--- /dev/null
+++ b/src/cmd/go/testdata/script/build_gcflags_order.txt
@@ -0,0 +1,20 @@
+# Tests golang.org/issue/47682
+# Flags specified with -gcflags should appear after other flags generated by cmd/go.
+
+cd m
+go build -n -gcflags=-lang=go1.17
+stderr ' -lang=go1.16.* -lang=go1.17'
+
+-- m/go.mod --
+module example.com
+
+go 1.16
+
+-- m/main.go --
+package main
+
+func main() {
+    var s = []int{1, 2, 3}
+    var pa = (*[2]int)(s[1:])
+    println(pa[1])
+}
diff --git a/src/cmd/go/testdata/script/build_runtime_gcflags.txt b/src/cmd/go/testdata/script/build_runtime_gcflags.txt
index da1b65f..c87e480 100644
--- a/src/cmd/go/testdata/script/build_runtime_gcflags.txt
+++ b/src/cmd/go/testdata/script/build_runtime_gcflags.txt
@@ -8,4 +8,4 @@
 # Verify the standard library (specifically runtime/internal/atomic) can be
 # built with -gcflags when -n is given. See golang.org/issue/29346.
 go build -n -gcflags=all='-l' std
-stderr 'compile.* -l .* runtime/internal/atomic'
+stderr 'compile.* runtime/internal/atomic .* -l'
diff --git a/src/cmd/go/testdata/script/gcflags_patterns.txt b/src/cmd/go/testdata/script/gcflags_patterns.txt
index f23cece..e9521c2 100644
--- a/src/cmd/go/testdata/script/gcflags_patterns.txt
+++ b/src/cmd/go/testdata/script/gcflags_patterns.txt
@@ -7,28 +7,28 @@
 
 # -gcflags=-e applies to named packages, not dependencies
 go build -n -v -gcflags=-e z1 z2
-stderr 'compile.* -e.* -p z1'
-stderr 'compile.* -e.* -p z2'
+stderr 'compile.* -p z1.* -e'
+stderr 'compile.* -p z2.* -e'
 stderr 'compile.* -p y'
-! stderr 'compile.* -e.* -p [^z]'
+! stderr 'compile.* -p [^z].* -e'
 
 # -gcflags can specify package=flags, and can be repeated; last match wins
 go build -n -v -gcflags=-e -gcflags=z1=-N z1 z2
-stderr 'compile.* -N.* -p z1'
-! stderr 'compile.* -e.* -p z1'
-! stderr 'compile.* -N.* -p z2'
-stderr 'compile.* -e.* -p z2'
+stderr 'compile.* -p z1.* -N'
+! stderr 'compile.* -p z1.* -e'
+! stderr 'compile.* -p z2.* -N'
+stderr 'compile.* -p z2.* -e'
 stderr 'compile.* -p y'
-! stderr 'compile.* -e.* -p [^z]'
-! stderr 'compile.* -N.* -p [^z]'
+! stderr 'compile.* -p [^z].* -e'
+! stderr 'compile.* -p [^z].* -N'
 
 # -gcflags can have arbitrary spaces around the flags
 go build -n -v -gcflags='  z1 =  	-e 	' z1
-stderr 'compile.* -e.* -p z1'
+stderr 'compile.* -p z1.* -e'
 
 # -gcflags='all=-e' should apply to all packages, even with go test
 go test -c -n -gcflags='all=-e' z1
-stderr 'compile.* -e.* -p z3 '
+stderr 'compile.* -p z3.* -e '
 
 # this particular -gcflags argument made the compiler crash
 ! go build -gcflags=-d=ssa/ z1
diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go
index d561e61..610a516 100644
--- a/src/crypto/tls/common.go
+++ b/src/crypto/tls/common.go
@@ -659,7 +659,7 @@
 	// cipher suite based on logic that takes into account inferred client
 	// hardware, server hardware, and security.
 	//
-	// Deprected: PreferServerCipherSuites is ignored.
+	// Deprecated: PreferServerCipherSuites is ignored.
 	PreferServerCipherSuites bool
 
 	// SessionTicketsDisabled may be set to true to disable session ticket and
diff --git a/src/embed/embed.go b/src/embed/embed.go
index 851cc21..5dcd7f2 100644
--- a/src/embed/embed.go
+++ b/src/embed/embed.go
@@ -83,8 +83,7 @@
 //
 // The //go:embed directive can be used with both exported and unexported variables,
 // depending on whether the package wants to make the data available to other packages.
-// It can only be used with global variables at package scope,
-// not with local variables.
+// It can only be used with variables at package scope, not with local variables.
 //
 // Patterns must not match files outside the package's module, such as ‘.git/*’ or symbolic links.
 // Matches for empty directories are ignored. After that, each pattern in a //go:embed line
diff --git a/src/embed/internal/embedtest/embed_test.go b/src/embed/internal/embedtest/embed_test.go
index 2d50f5e..b41359f 100644
--- a/src/embed/internal/embedtest/embed_test.go
+++ b/src/embed/internal/embedtest/embed_test.go
@@ -129,3 +129,43 @@
 		t.Errorf("in uninitialized embed.FS, . is not a directory")
 	}
 }
+
+var (
+	//go:embed "testdata/hello.txt"
+	helloT []T
+	//go:embed "testdata/hello.txt"
+	helloUint8 []uint8
+	//go:embed "testdata/hello.txt"
+	helloEUint8 []EmbedUint8
+	//go:embed "testdata/hello.txt"
+	helloBytes EmbedBytes
+	//go:embed "testdata/hello.txt"
+	helloString EmbedString
+)
+
+type T byte
+type EmbedUint8 uint8
+type EmbedBytes []byte
+type EmbedString string
+
+// golang.org/issue/47735
+func TestAliases(t *testing.T) {
+	all := testDirAll
+	want, e := all.ReadFile("testdata/hello.txt")
+	if e != nil {
+		t.Fatal("ReadFile:", e)
+	}
+	check := func(g interface{}) {
+		got := reflect.ValueOf(g)
+		for i := 0; i < got.Len(); i++ {
+			if byte(got.Index(i).Uint()) != want[i] {
+				t.Fatalf("got %v want %v", got.Bytes(), want)
+			}
+		}
+	}
+	check(helloT)
+	check(helloUint8)
+	check(helloEUint8)
+	check(helloBytes)
+	check(helloString)
+}
diff --git a/src/go/types/call.go b/src/go/types/call.go
index 87eeef4..fdecafb 100644
--- a/src/go/types/call.go
+++ b/src/go/types/call.go
@@ -347,8 +347,11 @@
 	}
 
 	// check arguments
-	for i, a := range args {
-		check.assignment(a, sigParams.vars[i].typ, check.sprintf("argument to %s", call.Fun))
+	if len(args) > 0 {
+		context := check.sprintf("argument to %s", call.Fun)
+		for i, a := range args {
+			check.assignment(a, sigParams.vars[i].typ, context)
+		}
 	}
 
 	return
diff --git a/src/go/types/check.go b/src/go/types/check.go
index 909bf8d..ab3a388 100644
--- a/src/go/types/check.go
+++ b/src/go/types/check.go
@@ -407,7 +407,7 @@
 	assert(call != nil)
 	assert(sig != nil)
 	if m := check.Inferred; m != nil {
-		m[call] = Inferred{&TypeList{targs}, sig}
+		m[call] = Inferred{NewTypeList(targs), sig}
 	}
 }
 
diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go
index 3ee09b7..5f691d5 100644
--- a/src/go/types/instantiate.go
+++ b/src/go/types/instantiate.go
@@ -131,7 +131,7 @@
 
 		tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil)
 		named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded
-		named.targs = &TypeList{targs}
+		named.targs = NewTypeList(targs)
 		named.instance = &instance{pos}
 		if check != nil {
 			check.typMap[h] = named
diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go
index 2f4ef9d..d4055bb 100644
--- a/src/go/types/predicates.go
+++ b/src/go/types/predicates.go
@@ -312,16 +312,14 @@
 				return false
 			}
 
-			if nargs := len(xargs); nargs > 0 {
+			if len(xargs) > 0 {
 				// Instances are identical if their original type and type arguments
 				// are identical.
 				if !Identical(x.orig, y.orig) {
 					return false
 				}
-				for i := 0; i < nargs; i++ {
-					xa := xargs[i]
-					ya := yargs[i]
-					if !Identical(xa, ya) {
+				for i, xa := range xargs {
+					if !Identical(xa, yargs[i]) {
 						return false
 					}
 				}
diff --git a/src/go/types/subst.go b/src/go/types/subst.go
index 8b8d6fb..1c53cda 100644
--- a/src/go/types/subst.go
+++ b/src/go/types/subst.go
@@ -233,7 +233,7 @@
 		// It's ok to provide a nil *Checker because the newly created type
 		// doesn't need to be (lazily) expanded; it's expanded below.
 		named := (*Checker)(nil).newNamed(tname, t.orig, nil, t.tparams, t.methods) // t is loaded, so tparams and methods are available
-		named.targs = &TypeList{newTArgs}
+		named.targs = NewTypeList(newTArgs)
 		subst.typMap[h] = named
 		t.expand(subst.typMap) // must happen after typMap update to avoid infinite recursion
 
diff --git a/src/go/types/typelists.go b/src/go/types/typelists.go
index a818140..ef8ea1f 100644
--- a/src/go/types/typelists.go
+++ b/src/go/types/typelists.go
@@ -27,6 +27,14 @@
 // TypeList holds a list of types.
 type TypeList struct{ types []Type }
 
+// NewTypeList returns a new TypeList with the types in list.
+func NewTypeList(list []Type) *TypeList {
+	if len(list) == 0 {
+		return nil
+	}
+	return &TypeList{list}
+}
+
 // Len returns the number of types in the list.
 // It is safe to call on a nil receiver.
 func (l *TypeList) Len() int { return len(l.list()) }
diff --git a/src/os/user/lookup_plan9.go b/src/os/user/lookup_plan9.go
index 51caf55..0793936 100644
--- a/src/os/user/lookup_plan9.go
+++ b/src/os/user/lookup_plan9.go
@@ -20,6 +20,7 @@
 func init() {
 	userImplemented = false
 	groupImplemented = false
+	groupListImplemented = false
 }
 
 func current() (*User, error) {
diff --git a/src/os/user/lookup_stubs.go b/src/os/user/lookup_stubs.go
index c975a11..d8e3d48 100644
--- a/src/os/user/lookup_stubs.go
+++ b/src/os/user/lookup_stubs.go
@@ -16,7 +16,7 @@
 )
 
 func init() {
-	groupImplemented = false
+	groupListImplemented = false
 }
 
 func current() (*User, error) {
diff --git a/src/os/user/lookup_unix.go b/src/os/user/lookup_unix.go
index 97c611f..dffea4a 100644
--- a/src/os/user/lookup_unix.go
+++ b/src/os/user/lookup_unix.go
@@ -18,13 +18,15 @@
 	"strings"
 )
 
-const groupFile = "/etc/group"
-const userFile = "/etc/passwd"
+const (
+	groupFile = "/etc/group"
+	userFile  = "/etc/passwd"
+)
 
 var colon = []byte{':'}
 
 func init() {
-	groupImplemented = false
+	groupListImplemented = false
 }
 
 // lineFunc returns a value, an error, or (nil, nil) to skip the row.
diff --git a/src/os/user/user.go b/src/os/user/user.go
index c1b8101..4e1b5b3 100644
--- a/src/os/user/user.go
+++ b/src/os/user/user.go
@@ -20,9 +20,12 @@
 	"strconv"
 )
 
+// These may be set to false in init() for a particular platform and/or
+// build flags to let the tests know to skip tests of some features.
 var (
-	userImplemented  = true // set to false by lookup_stubs.go's init
-	groupImplemented = true // set to false by lookup_stubs.go's init
+	userImplemented      = true
+	groupImplemented     = true
+	groupListImplemented = true
 )
 
 // User represents a user account.
diff --git a/src/os/user/user_test.go b/src/os/user/user_test.go
index 1112c78..d8a465e 100644
--- a/src/os/user/user_test.go
+++ b/src/os/user/user_test.go
@@ -119,8 +119,15 @@
 	}
 }
 
+func checkGroupList(t *testing.T) {
+	t.Helper()
+	if !groupListImplemented {
+		t.Skip("user: group list not implemented; skipping test")
+	}
+}
+
 func TestGroupIds(t *testing.T) {
-	checkGroup(t)
+	checkGroupList(t)
 	if runtime.GOOS == "aix" {
 		t.Skip("skipping GroupIds, see golang.org/issue/30563")
 	}
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index df79f05..40ac6a9 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -336,6 +336,47 @@
 	}
 }
 
+func TestMapIterSet(t *testing.T) {
+	m := make(map[string]interface{}, len(valueTests))
+	for _, tt := range valueTests {
+		m[tt.s] = tt.i
+	}
+	v := ValueOf(m)
+
+	k := New(v.Type().Key()).Elem()
+	e := New(v.Type().Elem()).Elem()
+
+	iter := v.MapRange()
+	for iter.Next() {
+		iter.SetKey(k)
+		iter.SetValue(e)
+		want := m[k.String()]
+		got := e.Interface()
+		if got != want {
+			t.Errorf("%q: want (%T) %v, got (%T) %v", k.String(), want, want, got, got)
+		}
+		if setkey, key := valueToString(k), valueToString(iter.Key()); setkey != key {
+			t.Errorf("MapIter.Key() = %q, MapIter.SetKey() = %q", key, setkey)
+		}
+		if setval, val := valueToString(e), valueToString(iter.Value()); setval != val {
+			t.Errorf("MapIter.Value() = %q, MapIter.SetValue() = %q", val, setval)
+		}
+	}
+
+	got := int(testing.AllocsPerRun(10, func() {
+		iter := v.MapRange()
+		for iter.Next() {
+			iter.SetKey(k)
+			iter.SetValue(e)
+		}
+	}))
+	// Making a *MapIter and making an hiter both allocate.
+	// Those should be the only two allocations.
+	if got != 2 {
+		t.Errorf("wanted 2 allocs, got %d", got)
+	}
+}
+
 func TestCanSetField(t *testing.T) {
 	type embed struct{ x, X int }
 	type Embed struct{ x, X int }
diff --git a/src/reflect/value.go b/src/reflect/value.go
index de01f13..a8274cc 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -1578,13 +1578,40 @@
 	if it.it == nil {
 		panic("MapIter.Key called before Next")
 	}
-	if mapiterkey(it.it) == nil {
+	iterkey := mapiterkey(it.it)
+	if iterkey == nil {
 		panic("MapIter.Key called on exhausted iterator")
 	}
 
 	t := (*mapType)(unsafe.Pointer(it.m.typ))
 	ktype := t.key
-	return copyVal(ktype, it.m.flag.ro()|flag(ktype.Kind()), mapiterkey(it.it))
+	return copyVal(ktype, it.m.flag.ro()|flag(ktype.Kind()), iterkey)
+}
+
+// SetKey assigns dst to the key of the iterator's current map entry.
+// It is equivalent to dst.Set(it.Key()), but it avoids allocating a new Value.
+// As in Go, the key must be assignable to dst's type.
+func (it *MapIter) SetKey(dst Value) {
+	if it.it == nil {
+		panic("MapIter.SetKey called before Next")
+	}
+	iterkey := mapiterkey(it.it)
+	if iterkey == nil {
+		panic("MapIter.SetKey called on exhausted iterator")
+	}
+
+	dst.mustBeAssignable()
+	var target unsafe.Pointer
+	if dst.kind() == Interface {
+		target = dst.ptr
+	}
+
+	t := (*mapType)(unsafe.Pointer(it.m.typ))
+	ktype := t.key
+
+	key := Value{ktype, iterkey, it.m.flag | flag(ktype.Kind())}
+	key = key.assignTo("reflect.MapIter.SetKey", dst.typ, target)
+	typedmemmove(dst.typ, dst.ptr, key.ptr)
 }
 
 // Value returns the value of the iterator's current map entry.
@@ -1592,13 +1619,40 @@
 	if it.it == nil {
 		panic("MapIter.Value called before Next")
 	}
-	if mapiterkey(it.it) == nil {
+	iterelem := mapiterelem(it.it)
+	if iterelem == nil {
 		panic("MapIter.Value called on exhausted iterator")
 	}
 
 	t := (*mapType)(unsafe.Pointer(it.m.typ))
 	vtype := t.elem
-	return copyVal(vtype, it.m.flag.ro()|flag(vtype.Kind()), mapiterelem(it.it))
+	return copyVal(vtype, it.m.flag.ro()|flag(vtype.Kind()), iterelem)
+}
+
+// SetValue assigns dst to the value of the iterator's current map entry.
+// It is equivalent to dst.Set(it.Value()), but it avoids allocating a new Value.
+// As in Go, the value must be assignable to dst's type.
+func (it *MapIter) SetValue(dst Value) {
+	if it.it == nil {
+		panic("MapIter.SetValue called before Next")
+	}
+	iterelem := mapiterelem(it.it)
+	if iterelem == nil {
+		panic("MapIter.SetValue called on exhausted iterator")
+	}
+
+	dst.mustBeAssignable()
+	var target unsafe.Pointer
+	if dst.kind() == Interface {
+		target = dst.ptr
+	}
+
+	t := (*mapType)(unsafe.Pointer(it.m.typ))
+	vtype := t.elem
+
+	elem := Value{vtype, iterelem, it.m.flag | flag(vtype.Kind())}
+	elem = elem.assignTo("reflect.MapIter.SetValue", dst.typ, target)
+	typedmemmove(dst.typ, dst.ptr, elem.ptr)
 }
 
 // Next advances the map iterator and reports whether there is another
diff --git a/src/strings/strings.go b/src/strings/strings.go
index b429735..0df8d2e 100644
--- a/src/strings/strings.go
+++ b/src/strings/strings.go
@@ -818,11 +818,6 @@
 }
 
 func makeCutsetFunc(cutset string) func(rune) bool {
-	if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
-		return func(r rune) bool {
-			return r == rune(cutset[0])
-		}
-	}
 	if as, isASCII := makeASCIISet(cutset); isASCII {
 		return func(r rune) bool {
 			return r < utf8.RuneSelf && as.contains(byte(r))
@@ -837,6 +832,9 @@
 	if s == "" || cutset == "" {
 		return s
 	}
+	if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
+		return trimLeftByte(trimRightByte(s, cutset[0]), cutset[0])
+	}
 	return TrimFunc(s, makeCutsetFunc(cutset))
 }
 
@@ -848,9 +846,19 @@
 	if s == "" || cutset == "" {
 		return s
 	}
+	if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
+		return trimLeftByte(s, cutset[0])
+	}
 	return TrimLeftFunc(s, makeCutsetFunc(cutset))
 }
 
+func trimLeftByte(s string, c byte) string {
+	for len(s) > 0 && s[0] == c {
+		s = s[1:]
+	}
+	return s
+}
+
 // TrimRight returns a slice of the string s, with all trailing
 // Unicode code points contained in cutset removed.
 //
@@ -859,9 +867,19 @@
 	if s == "" || cutset == "" {
 		return s
 	}
+	if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
+		return trimRightByte(s, cutset[0])
+	}
 	return TrimRightFunc(s, makeCutsetFunc(cutset))
 }
 
+func trimRightByte(s string, c byte) string {
+	for len(s) > 0 && s[len(s)-1] == c {
+		s = s[:len(s)-1]
+	}
+	return s
+}
+
 // TrimSpace returns a slice of the string s, with all leading
 // and trailing white space removed, as defined by Unicode.
 func TrimSpace(s string) string {
diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go
index 09e5b27..edc6c20 100644
--- a/src/strings/strings_test.go
+++ b/src/strings/strings_test.go
@@ -808,7 +808,9 @@
 	{"TrimLeft", "abba", "ab", ""},
 	{"TrimRight", "abba", "ab", ""},
 	{"TrimLeft", "abba", "a", "bba"},
+	{"TrimLeft", "abba", "b", "abba"},
 	{"TrimRight", "abba", "a", "abb"},
+	{"TrimRight", "abba", "b", "abba"},
 	{"Trim", "<tag>", "<>", "tag"},
 	{"Trim", "* listitem", " *", "listitem"},
 	{"Trim", `"quote"`, `"`, "quote"},
@@ -1860,6 +1862,13 @@
 	}
 }
 
+func BenchmarkTrimByte(b *testing.B) {
+	x := "  the quick brown fox   "
+	for i := 0; i < b.N; i++ {
+		Trim(x, " ")
+	}
+}
+
 func BenchmarkIndexPeriodic(b *testing.B) {
 	key := "aa"
 	for _, skip := range [...]int{2, 4, 8, 16, 32, 64} {
diff --git a/src/time/format.go b/src/time/format.go
index f4b4f48..7ae89c5 100644
--- a/src/time/format.go
+++ b/src/time/format.go
@@ -479,7 +479,7 @@
 		}
 		m1, m2 := m2/1e9, m2%1e9
 		m0, m1 := m1/1e9, m1%1e9
-		var buf []byte
+		buf := make([]byte, 0, 24)
 		buf = append(buf, " m="...)
 		buf = append(buf, sign)
 		wid := 0
@@ -498,7 +498,8 @@
 // GoString implements fmt.GoStringer and formats t to be printed in Go source
 // code.
 func (t Time) GoString() string {
-	buf := []byte("time.Date(")
+	buf := make([]byte, 0, 70)
+	buf = append(buf, "time.Date("...)
 	buf = appendInt(buf, t.Year(), 0)
 	month := t.Month()
 	if January <= month && month <= December {
diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go
index eb0f338..eb95416 100644
--- a/test/codegen/arithmetic.go
+++ b/test/codegen/arithmetic.go
@@ -84,6 +84,30 @@
 	return c
 }
 
+func SubSubNegSimplify(a, b int) int {
+	// amd64:"NEGQ"
+	r := (a - b) - a
+	return r
+}
+
+func SubAddSimplify(a, b int) int {
+	// amd64:-"SUBQ",-"ADDQ"
+	r := a + (b - a)
+	return r
+}
+
+func SubAddNegSimplify(a, b int) int {
+	// amd64:"NEGQ",-"ADDQ",-"SUBQ"
+	r := a - (b + a)
+	return r
+}
+
+func AddAddSubSimplify(a, b, c int) int {
+	// amd64:-"SUBQ"
+	r := a + (b + (c - a))
+	return r
+}
+
 // -------------------- //
 //    Multiplication    //
 // -------------------- //
diff --git a/test/fixedbugs/gcc101994.go b/test/fixedbugs/gcc101994.go
new file mode 100644
index 0000000..6e1e2b8
--- /dev/null
+++ b/test/fixedbugs/gcc101994.go
@@ -0,0 +1,16 @@
+// compile
+
+// 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.
+
+// https://gcc.gnu.org/PR101994
+// gccgo compiler crash with zero-sized result.
+
+package p
+
+type Empty struct{}
+
+func F() (int, Empty) {
+	return 0, Empty{}
+}
diff --git a/test/fixedbugs/issue10975.go b/test/fixedbugs/issue10975.go
index 876ea58..a58ccce 100644
--- a/test/fixedbugs/issue10975.go
+++ b/test/fixedbugs/issue10975.go
@@ -10,7 +10,7 @@
 package main
 
 type I interface {
-	int // ERROR "interface contains embedded non-interface|not an interface"
+	int // ERROR "interface contains embedded non-interface|embedding non-interface type"
 }
 
 func New() I {
diff --git a/test/fixedbugs/issue46938.go b/test/fixedbugs/issue46938.go
new file mode 100644
index 0000000..87532d4
--- /dev/null
+++ b/test/fixedbugs/issue46938.go
@@ -0,0 +1,29 @@
+// run -gcflags="-d=checkptr"
+
+// 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
+
+import (
+	"strings"
+	"unsafe"
+)
+
+func main() {
+	defer func() {
+		err := recover()
+		if err == nil {
+			panic("expected panic")
+		}
+		if got := err.(error).Error(); !strings.Contains(got, "slice bounds out of range") {
+			panic("expected panic slice out of bound, got " + got)
+		}
+	}()
+	s := make([]int64, 100)
+	p := unsafe.Pointer(&s[0])
+	n := 1000
+
+	_ = (*[10]int64)(p)[:n:n]
+}
diff --git a/test/fixedbugs/issue47771.go b/test/fixedbugs/issue47771.go
new file mode 100644
index 0000000..a434bff
--- /dev/null
+++ b/test/fixedbugs/issue47771.go
@@ -0,0 +1,19 @@
+// run
+
+// 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.
+
+// gofrontend miscompiled some cases of append(s, make(typ, ln)...).
+
+package main
+
+var g int
+
+func main() {
+	a := []*int{&g, &g, &g, &g}
+	a = append(a[:0], make([]*int, len(a) - 1)...)
+	if len(a) != 3 || a[0] != nil || a[1] != nil || a[2] != nil {
+		panic(a)
+	}
+}
diff --git a/test/typeparam/issue47878.go b/test/typeparam/issue47878.go
new file mode 100644
index 0000000..cb1043a
--- /dev/null
+++ b/test/typeparam/issue47878.go
@@ -0,0 +1,46 @@
+// compile -G=3
+
+// 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
+
+type Src1[T any] func() Src1[T]
+
+func (s *Src1[T]) Next() {
+	*s = (*s)()
+}
+
+type Src2[T any] []func() Src2[T]
+
+func (s Src2[T]) Next() {
+	_ = s[0]()
+}
+
+type Src3[T comparable] map[T]func() Src3[T]
+
+func (s Src3[T]) Next() {
+	var a T
+	_ = s[a]()
+}
+
+type Src4[T any] chan func() T
+
+func (s Src4[T]) Next() {
+	_ = (<-s)()
+}
+
+func main() {
+	var src1 Src1[int]
+	src1.Next()
+
+	var src2 Src2[int]
+	src2.Next()
+
+	var src3 Src3[string]
+	src3.Next()
+
+	var src4 Src4[int]
+	src4.Next()
+}
diff --git a/test/typeparam/issue47901.go b/test/typeparam/issue47901.go
new file mode 100644
index 0000000..cd07973
--- /dev/null
+++ b/test/typeparam/issue47901.go
@@ -0,0 +1,21 @@
+// run -gcflags=-G=3
+
+// 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
+
+type Chan[T any] chan Chan[T]
+
+func (ch Chan[T]) recv() Chan[T] {
+	return <-ch
+}
+
+func main() {
+	ch := Chan[int](make(chan Chan[int]))
+	go func() {
+		ch <- make(Chan[int])
+	}()
+	ch.recv()
+}
diff --git a/test/typeparam/issue47929.go b/test/typeparam/issue47929.go
new file mode 100644
index 0000000..a5636f2
--- /dev/null
+++ b/test/typeparam/issue47929.go
@@ -0,0 +1,29 @@
+// compile -G=3 -p=p
+
+// 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 v4
+
+var sink interface{}
+
+//go:noinline
+func Do(result, body interface{}) {
+	sink = &result
+}
+
+func DataAction(result DataActionResponse, body DataActionRequest) {
+	Do(&result, body)
+}
+
+type DataActionRequest struct {
+	Action *interface{}
+}
+
+type DataActionResponse struct {
+	ValidationErrors *ValidationError
+}
+
+type ValidationError struct {
+}
diff --git a/test/typeparam/issue47948.go b/test/typeparam/issue47948.go
new file mode 100644
index 0000000..8e5df81
--- /dev/null
+++ b/test/typeparam/issue47948.go
@@ -0,0 +1,18 @@
+// compile -G=3
+
+// 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
+
+type fun func()
+
+func F[T any]() {
+	_ = fun(func() {
+
+	})
+}
+func main() {
+	F[int]()
+}