Merge List:
+ 2021-05-18
690a8c3fb1 make.bash: fix misuse of continue
+ 2021-05-18
8b0901fd32 doc/go1.17: fix typo "avoding" -> "avoiding"
+ 2021-05-18
5e191f8f48 time: rewrite the documentation for layout strings
+ 2021-05-17
bfe3573d58 go/token: correct the interval notation used in some panic messages
+ 2021-05-17
a2c07a9a1a all: update golang.org/x/net to latest
+ 2021-05-17
b9b2bed893 syscall: some containers may fail syscall.TestSetuidEtc
+ 2021-05-17
b1aff42900 cmd/go: don't print 'go get' deprecation notices in the main module
+ 2021-05-17
bade680867 runtime/cgo: fix crosscall2 on ppc64x
+ 2021-05-15
ce92a2023c cmd/go: error out of 'go mod tidy' if the go version is newer than supported
+ 2021-05-14
02699f810a runtime: mark osyield nosplit on OpenBSD
+ 2021-05-14
3d324f127d net/http: prevent infinite wait during TestMissingStatusNoPanic
+ 2021-05-14
0eb38f2b16 cmd/go/internal/load: override Package.Root in module mode
+ 2021-05-14
a938e52986 cmd/go: fix a portability issue in the cd script command
+ 2021-05-14
d137b74539 cmd/go: fix spacing in help text of -overlay flag
+ 2021-05-14
c925e1546e cmd/internal/obj/arm64: disable AL and NV for some condition operation instructions
+ 2021-05-14
12d383c7c7 debug/macho: fix a typo in macho.go
+ 2021-05-14
3a0453514a all: fix spelling
+ 2021-05-13
b4833f7c06 cmd/link: always mark runtime.unreachableMethod symbol
+ 2021-05-13
92c189f211 cmd/link: resolve ABI alias for runtime.unreachableMethod
+ 2021-05-13
7a7624a3fa cmd/go: permit .tbd files as a linker flag
+ 2021-05-13
cde2d857fe cmd/go: be less strict about go version syntax in dependency go.mod files
+ 2021-05-13
2a61b3c590 regexp: fix repeat of preferred empty match
+ 2021-05-13
fd4631e24f cmd/compile/internal/dwarfgen: fix DWARF param DIE ordering
+ 2021-05-13
a63cded5e4 debug/dwarf: delay array type fixup to handle type cycles
+ 2021-05-13
0fa2302ee5 cmd/vendor: update golang.org/x/sys to latest
+ 2021-05-13
2c76a6f7f8 all: add //go:build lines to assembly files
+ 2021-05-12
6db7480f59 cmd/go/internal/modload: in updateLazyRoots, do not require the main module explicitly
+ 2021-05-12
f93b951f33 cmd/compile/abi-internal.md: fix table format
+ 2021-05-12
3b321a9d12 cmd/compile: add arch-specific inlining for runtime.memmove
+ 2021-05-12
07ff596404 runtime/internal/atomic: add LSE atomics instructions to arm64
+ 2021-05-12
03886707f9 runtime: fix handling of SPWRITE functions in traceback
+ 2021-05-12
e03383a2e2 cmd/link: check mmap error
+ 2021-05-12
af0f8c149e cmd/link: don't cast end address to int32
+ 2021-05-12
485474d204 cmd/go/testdata/script: fix test failing on nocgo builders
+ 2021-05-12
1a0ea1a08b runtime: fix typo in proc.go
+ 2021-05-11
9995c6b50a cmd/go: ignore implicit imports when the -find flag is set
Change-Id: I843fe029b8ac09424a83e8a4e8bdcc86edd40603
-branch: master
+branch: dev.typeparams
+parent-branch: master
// A SelectorExpr is a selector expression X.Sel.
type SelectorExpr struct {
miniExpr
- X Node
- Sel *types.Sym
+ X Node
+ // Sel is the name of the field or method being selected, without (in the
+ // case of methods) any preceding type specifier. If the field/method is
+ // exported, than the Sym uses the local package regardless of the package
+ // of the containing type.
+ Sel *types.Sym
+ // The actual selected field - may not be filled in until typechecking.
Selection *types.Field
Prealloc *Name // preallocated storage for OCALLPART, if any
}
recvType2 = recvType2Base
// method is the generic method associated with the gen type
method := g.obj(types2.AsNamed(recvType2).Method(last))
- n = ir.NewSelectorExpr(pos, ir.OCALLPART, x, method.Sym())
+ n = ir.NewSelectorExpr(pos, ir.OCALLPART, x, typecheck.Lookup(expr.Sel.Value))
n.(*ir.SelectorExpr).Selection = types.NewField(pos, method.Sym(), method.Type())
n.(*ir.SelectorExpr).Selection.Nname = method
typed(method.Type(), n)
call := n.(*ir.CallExpr)
inst := call.X.(*ir.InstExpr)
st := g.getInstantiationForNode(inst)
- // Replace the OFUNCINST with a direct reference to the
- // new stenciled function
- call.X = st.Nname
if inst.X.Op() == ir.OCALLPART {
- // When we create an instantiation of a method
- // call, we make it a function. So, move the
- // receiver to be the first arg of the function
- // call.
- withRecv := make([]ir.Node, len(call.Args)+1)
- dot := inst.X.(*ir.SelectorExpr)
- withRecv[0] = dot.X
- copy(withRecv[1:], call.Args)
- call.Args = withRecv
+ // Replace the OFUNCINST with the selector
+ // expression, and update the selector expression
+ // to refer to the new stenciled function.
+ call.X = inst.X
+ se := call.X.(*ir.SelectorExpr)
+ se.Selection = types.NewField(se.Pos(), se.Sel, st.Type())
+ se.Selection.Nname = st.Nname
+ se.SetOp(ir.ODOTMETH)
+ se.SetType(st.Type())
+ } else {
+ // Replace the OFUNCINST with a direct reference to the
+ // new stenciled function
+ call.X = st.Nname
}
// Transform the Call now, which changes OCALL
// to OCALLFUNC and does typecheckaste/assignconvfn.
// EditChildren rather than Visit), where we actually change the
// OFUNCINST node to an ONAME for the instantiated function.
// EditChildren is more expensive than Visit, so we only do this
- // in the infrequent case of an OFUNCINSt without a corresponding
+ // in the infrequent case of an OFUNCINST without a corresponding
// call.
if foundFuncInst {
var edit func(ir.Node) ir.Node
edit = func(x ir.Node) ir.Node {
if x.Op() == ir.OFUNCINST {
- st := g.getInstantiationForNode(x.(*ir.InstExpr))
- return st.Nname
+ // inst.X is either a function name node
+ // or a selector expression for a method.
+ inst := x.(*ir.InstExpr)
+ st := g.getInstantiationForNode(inst)
+ modified = true
+ if inst.X.Op() == ir.ONAME {
+ return st.Nname
+ }
+ assert(inst.X.Op() == ir.OCALLPART)
+
+ // Return a new selector expression referring
+ // to the newly stenciled function.
+ oldse := inst.X.(*ir.SelectorExpr)
+ newse := ir.NewSelectorExpr(oldse.Pos(), ir.OCALLPART, oldse.X, oldse.Sel)
+ newse.Selection = types.NewField(oldse.Pos(), st.Sym(), st.Type())
+ newse.Selection.Nname = st
+ typed(inst.Type(), newse)
+ return newse
}
ir.EditChildren(x, edit)
return x
baseSym := typ.Sym().Pkg.Lookup(genericTypeName(typ.Sym()))
baseType := baseSym.Def.(*ir.Name).Type()
for j, m := range typ.Methods().Slice() {
- name := m.Nname.(*ir.Name)
targs := make([]ir.Node, len(typ.RParams()))
for k, targ := range typ.RParams() {
targs[k] = ir.TypeNode(targ)
}
baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
- name.Func = g.getInstantiation(baseNname, targs, true)
+ f := g.getInstantiation(baseNname, targs, true)
+ m.Nname = f.Nname
}
}
g.instTypeList = nil
newf.Dcl[i] = subst.node(n).(*ir.Name)
}
- // Ugly: we have to insert the Name nodes of the parameters/results into
+ // Replace the types in the function signature.
+ // Ugly: also, we have to insert the Name nodes of the parameters/results into
// the function type. The current function type has no Nname fields set,
// because it came via conversion from the types2 type.
oldt := nameNode.Type()
- // We also transform a generic method type to the corresponding
- // instantiated function type where the receiver is the first parameter.
- newt := types.NewSignature(oldt.Pkg(), nil, nil,
- subst.fields(ir.PPARAM, append(oldt.Recvs().FieldSlice(), oldt.Params().FieldSlice()...), newf.Dcl),
- subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), newf.Dcl))
+ dcl := newf.Dcl
+ var newrecv *types.Field
+ if oldt.Recv() != nil {
+ newrecv = subst.fields(ir.PPARAM, oldt.Recvs().FieldSlice(), dcl)[0]
+ if newrecv.Nname != nil {
+ // If we found the receiver in the dcl list, then skip it
+ // when we scan for the remaining params below.
+ assert(newrecv.Nname == dcl[0])
+ dcl = dcl[1:]
+ }
+ }
+ newt := types.NewSignature(oldt.Pkg(), newrecv, nil,
+ subst.fields(ir.PPARAM, oldt.Params().FieldSlice(), dcl),
+ subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), dcl))
newf.Nname.SetType(newt)
ir.MarkFunc(newf.Nname)
return types.NewInterface(g.tpkg(typ), append(embeddeds, methods...))
case *types2.TypeParam:
- tp := types.NewTypeParam(g.tpkg(typ))
// Save the name of the type parameter in the sym of the type.
// Include the types2 subscript in the sym name
sym := g.pkg(typ.Obj().Pkg()).Lookup(types2.TypeString(typ, func(*types2.Package) string { return "" }))
- tp.SetSym(sym)
+ tp := types.NewTypeParam(sym, typ.Index())
// Set g.typs[typ] in case the bound methods reference typ.
g.typs[typ] = tp
- // TODO(danscales): we don't currently need to use the bounds
- // anywhere, so eventually we can probably remove.
bound := g.typ1(typ.Bound())
- *tp.Methods() = *bound.Methods()
+ tp.SetBound(bound)
return tp
case *types2.Tuple:
// TARRAY: *Array
// TSLICE: Slice
// TSSA: string
- // TTYPEPARAM: *Interface (though we may not need to store/use the Interface info)
+ // TTYPEPARAM: *Typeparam
Extra interface{}
// Width is the width of this Type in bytes.
pkg *Pkg
}
+// Typeparam contains Type fields specific to typeparam types.
+type Typeparam struct {
+ index int // type parameter index in source order, starting at 0
+ bound *Type
+}
+
// Ptr contains Type fields specific to pointer types.
type Ptr struct {
Elem *Type // element type
case TRESULTS:
t.Extra = new(Results)
case TTYPEPARAM:
- t.Extra = new(Interface)
+ t.Extra = new(Typeparam)
}
return t
}
case TARRAY:
x := *t.Extra.(*Array)
nt.Extra = &x
+ case TTYPEPARAM:
+ base.Fatalf("typeparam types cannot be copied")
case TTUPLE, TSSA, TRESULTS:
base.Fatalf("ssa types cannot be copied")
}
return t
}
-// NewTypeParam returns a new type param.
-func NewTypeParam(pkg *Pkg) *Type {
+// NewTypeParam returns a new type param with the specified sym (package and name)
+// and specified index within the typeparam list.
+func NewTypeParam(sym *Sym, index int) *Type {
t := New(TTYPEPARAM)
- t.Extra.(*Interface).pkg = pkg
+ t.sym = sym
+ t.Extra.(*Typeparam).index = index
t.SetHasTParam(true)
return t
}
+// Index returns the index of the type param within its param list.
+func (t *Type) Index() int {
+ t.wantEtype(TTYPEPARAM)
+ return t.Extra.(*Typeparam).index
+}
+
+// SetBound sets the bound of a typeparam.
+func (t *Type) SetBound(bound *Type) {
+ t.wantEtype(TTYPEPARAM)
+ t.Extra.(*Typeparam).bound = bound
+}
+
+// Bound returns the bound of a typeparam.
+func (t *Type) Bound() *Type {
+ t.wantEtype(TTYPEPARAM)
+ return t.Extra.(*Typeparam).bound
+}
+
const BOGUS_FUNARG_OFFSET = -1000000000
func unzeroFieldOffsets(f []*Field) {
}
for _, test := range tests {
- ResetId() // avoid renumbering of type parameter ids when adding tests
info := Info{Types: make(map[syntax.Expr]TypeAndValue)}
var name string
if strings.HasPrefix(test.src, brokenPkg) {
pkg *Package
*Info
version version // accepted language version
+ nextID uint64 // unique Id for type parameters (first valid Id is 1)
objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info
impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
posMap map[*Interface][]syntax.Pos // maps interface types to lists of embedded interface positions
// Note: This is a uint32 rather than a uint64 because the
// respective 64 bit atomic instructions are not available
// on all platforms.
-var lastId uint32
+var lastID uint32
-// nextId returns a value increasing monotonically by 1 with
+// nextID returns a value increasing monotonically by 1 with
// each call, starting with 1. It may be called concurrently.
-func nextId() uint64 { return uint64(atomic.AddUint32(&lastId, 1)) }
+func nextID() uint64 { return uint64(atomic.AddUint32(&lastID, 1)) }
// A TypeParam represents a type parameter type.
type TypeParam struct {
// NewTypeParam returns a new TypeParam.
func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam {
assert(bound != nil)
- typ := &TypeParam{check: check, id: nextId(), obj: obj, index: index, bound: bound}
+ // Always increment lastID, even if it is not used.
+ id := nextID()
+ if check != nil {
+ check.nextID++
+ id = check.nextID
+ }
+ typ := &TypeParam{check: check, id: id, obj: obj, index: index, bound: bound}
if obj.typ == nil {
obj.typ = typ
}
return typ
}
+// Index returns the index of the type param within its param list.
+func (t *TypeParam) Index() int {
+ return t.index
+}
+
func (t *TypeParam) Bound() *Interface {
iface := asInterface(t.bound)
// use the type bound position if we have one
package types2
-import "sync/atomic"
-
func init() {
acceptMethodTypeParams = true
}
-// Upon calling ResetId, nextId starts with 1 again.
-// It may be called concurrently. This is only needed
-// for tests where we may want to have a consistent
-// numbering for each individual test case.
-func ResetId() { atomic.StoreUint32(&lastId, 0) }
+// Debug is set if types2 is built with debug mode enabled.
+const Debug = debug
empty = false
}
}
- if t.allMethods == nil || len(t.methods) > len(t.allMethods) {
+ if debug && (t.allMethods == nil || len(t.methods) > len(t.allMethods)) {
if !empty {
buf.WriteByte(' ')
}
var nopos syntax.Pos
func TestIncompleteInterfaces(t *testing.T) {
+ if !Debug {
+ t.Skip("requires type checker to be compiled with debug = true")
+ }
+
sig := NewSignature(nil, nil, nil, false)
m := NewFunc(nopos, nil, "m", sig)
for _, test := range []struct {
--- /dev/null
+// Code generated by "stringer -type Kind"; DO NOT EDIT.
+
+package constant
+
+import "strconv"
+
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[Unknown-0]
+ _ = x[Bool-1]
+ _ = x[String-2]
+ _ = x[Int-3]
+ _ = x[Float-4]
+ _ = x[Complex-5]
+}
+
+const _Kind_name = "UnknownBoolStringIntFloatComplex"
+
+var _Kind_index = [...]uint8{0, 7, 11, 17, 20, 25, 32}
+
+func (i Kind) String() string {
+ if i < 0 || i >= Kind(len(_Kind_index)-1) {
+ return "Kind(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _Kind_name[_Kind_index[i]:_Kind_index[i+1]]
+}
"unicode/utf8"
)
+//go:generate stringer -type Kind
+
// Kind specifies the kind of value represented by a Value.
type Kind int
package runtime
+import "internal/abi"
+
//go:nosplit
//go:nowritebarrierrec
func setsig(i uint32, fn uintptr) {
sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK | _SA_RESTART
sa.sa_mask = sigset_all
if fn == funcPC(sighandler) {
- fn = funcPC(sigtramp)
+ fn = abi.FuncPCABI0(sigtramp)
}
sa.sa_handler = fn
sigaction(i, &sa, nil)
package runtime
+import "internal/abi"
+
func cgoSigtramp()
//go:nosplit
sa.sa_mask = sigset_all
if fn == funcPC(sighandler) {
if iscgo {
- fn = funcPC(cgoSigtramp)
+ fn = abi.FuncPCABI0(cgoSigtramp)
} else {
- fn = funcPC(sigtramp)
+ fn = abi.FuncPCABI0(sigtramp)
}
}
sa.sa_handler = fn
--- /dev/null
+// 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
+
+import (
+ "fmt"
+)
+
+type s[T any] struct {
+ a T
+}
+func (x s[T]) f() T {
+ return x.a
+}
+func main() {
+ x := s[int]{a:7}
+ f := x.f
+ if got, want := f(), 7; got != want {
+ panic(fmt.Sprintf("got %d, want %d", got, want))
+ }
+}