mirror of
https://github.com/golang/go
synced 2024-11-27 03:21:18 -07:00
[dev.typeparams] cmd/compile: move to new export version, keep reading previous version
I added constants for the previous export versions, and for the final generics export version. I also added a const for the current export version. We can increment the current export version for unstable changes in dev.typeparams, and eventally set it back to the generics version (2) before release. Added the same constants in typecheck/iexport.go, importer/iimport.go, and gcimporter/iimport.go, must be kept in sync. Put in the needed conditionals to be able to read old versions. Added new export/import test listimp.dir. Change-Id: I166d17d943e07951aa752562e952b067704aeeca Reviewed-on: https://go-review.googlesource.com/c/go/+/319931 Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
15ad61aff5
commit
7b3ee6102d
@ -1,4 +1,3 @@
|
|||||||
// UNREVIEWED
|
|
||||||
// Copyright 2018 The Go Authors. All rights reserved.
|
// Copyright 2018 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
@ -42,6 +41,16 @@ func (r *intReader) uint64() uint64 {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep this in sync with constants in iexport.go.
|
||||||
|
const (
|
||||||
|
iexportVersionGo1_11 = 0
|
||||||
|
iexportVersionPosCol = 1
|
||||||
|
iexportVersionGenerics = 2
|
||||||
|
|
||||||
|
// Start of the unstable series of versions, remove "+ n" before release.
|
||||||
|
iexportVersionCurrent = iexportVersionGenerics + 1
|
||||||
|
)
|
||||||
|
|
||||||
const predeclReserved = 32
|
const predeclReserved = 32
|
||||||
|
|
||||||
type itag uint64
|
type itag uint64
|
||||||
@ -68,7 +77,7 @@ const io_SeekCurrent = 1 // io.SeekCurrent (not defined in Go 1.4)
|
|||||||
// If the export data version is not recognized or the format is otherwise
|
// If the export data version is not recognized or the format is otherwise
|
||||||
// compromised, an error is returned.
|
// compromised, an error is returned.
|
||||||
func iImportData(imports map[string]*types2.Package, data []byte, path string) (_ int, pkg *types2.Package, err error) {
|
func iImportData(imports map[string]*types2.Package, data []byte, path string) (_ int, pkg *types2.Package, err error) {
|
||||||
const currentVersion = 1
|
const currentVersion = iexportVersionCurrent
|
||||||
version := int64(-1)
|
version := int64(-1)
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
@ -84,9 +93,13 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) (
|
|||||||
|
|
||||||
version = int64(r.uint64())
|
version = int64(r.uint64())
|
||||||
switch version {
|
switch version {
|
||||||
case currentVersion, 0:
|
case currentVersion, iexportVersionPosCol, iexportVersionGo1_11:
|
||||||
default:
|
default:
|
||||||
errorf("unknown iexport format version %d", version)
|
if version > iexportVersionGenerics {
|
||||||
|
errorf("unstable iexport format version %d, just rebuild compiler and std library", version)
|
||||||
|
} else {
|
||||||
|
errorf("unknown iexport format version %d", version)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sLen := int64(r.uint64())
|
sLen := int64(r.uint64())
|
||||||
@ -98,8 +111,9 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) (
|
|||||||
r.Seek(sLen+dLen, io_SeekCurrent)
|
r.Seek(sLen+dLen, io_SeekCurrent)
|
||||||
|
|
||||||
p := iimporter{
|
p := iimporter{
|
||||||
ipath: path,
|
exportVersion: version,
|
||||||
version: int(version),
|
ipath: path,
|
||||||
|
version: int(version),
|
||||||
|
|
||||||
stringData: stringData,
|
stringData: stringData,
|
||||||
stringCache: make(map[uint64]string),
|
stringCache: make(map[uint64]string),
|
||||||
@ -178,8 +192,9 @@ func iImportData(imports map[string]*types2.Package, data []byte, path string) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
type iimporter struct {
|
type iimporter struct {
|
||||||
ipath string
|
exportVersion int64
|
||||||
version int
|
ipath string
|
||||||
|
version int
|
||||||
|
|
||||||
stringData []byte
|
stringData []byte
|
||||||
stringCache map[uint64]string
|
stringCache map[uint64]string
|
||||||
@ -294,14 +309,20 @@ func (r *importReader) obj(name string) {
|
|||||||
r.declare(types2.NewConst(pos, r.currPkg, name, typ, val))
|
r.declare(types2.NewConst(pos, r.currPkg, name, typ, val))
|
||||||
|
|
||||||
case 'F':
|
case 'F':
|
||||||
tparams := r.tparamList()
|
var tparams []*types2.TypeName
|
||||||
|
if r.p.exportVersion >= iexportVersionGenerics {
|
||||||
|
tparams = r.tparamList()
|
||||||
|
}
|
||||||
sig := r.signature(nil)
|
sig := r.signature(nil)
|
||||||
sig.SetTParams(tparams)
|
sig.SetTParams(tparams)
|
||||||
|
|
||||||
r.declare(types2.NewFunc(pos, r.currPkg, name, sig))
|
r.declare(types2.NewFunc(pos, r.currPkg, name, sig))
|
||||||
|
|
||||||
case 'T':
|
case 'T':
|
||||||
tparams := r.tparamList()
|
var tparams []*types2.TypeName
|
||||||
|
if r.p.exportVersion >= iexportVersionGenerics {
|
||||||
|
tparams = r.tparamList()
|
||||||
|
}
|
||||||
|
|
||||||
// Types can be recursive. We need to setup a stub
|
// Types can be recursive. We need to setup a stub
|
||||||
// declaration before recursing.
|
// declaration before recursing.
|
||||||
@ -592,6 +613,9 @@ func (r *importReader) doType(base *types2.Named) types2.Type {
|
|||||||
return typ
|
return typ
|
||||||
|
|
||||||
case typeParamType:
|
case typeParamType:
|
||||||
|
if r.p.exportVersion < iexportVersionGenerics {
|
||||||
|
errorf("unexpected type param type")
|
||||||
|
}
|
||||||
r.currPkg = r.pkg()
|
r.currPkg = r.pkg()
|
||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
name := r.string()
|
name := r.string()
|
||||||
@ -622,6 +646,9 @@ func (r *importReader) doType(base *types2.Named) types2.Type {
|
|||||||
return t
|
return t
|
||||||
|
|
||||||
case instType:
|
case instType:
|
||||||
|
if r.p.exportVersion < iexportVersionGenerics {
|
||||||
|
errorf("unexpected instantiation type")
|
||||||
|
}
|
||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
len := r.uint64()
|
len := r.uint64()
|
||||||
targs := make([]types2.Type, len)
|
targs := make([]types2.Type, len)
|
||||||
|
@ -223,9 +223,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Current indexed export format version. Increase with each format change.
|
// Current indexed export format version. Increase with each format change.
|
||||||
// 1: added column details to Pos
|
|
||||||
// 0: Go1.11 encoding
|
// 0: Go1.11 encoding
|
||||||
const iexportVersion = 1
|
// 1: added column details to Pos
|
||||||
|
// 2: added information for generic function/types (currently unstable)
|
||||||
|
const (
|
||||||
|
iexportVersionGo1_11 = 0
|
||||||
|
iexportVersionPosCol = 1
|
||||||
|
iexportVersionGenerics = 2
|
||||||
|
|
||||||
|
// Start of the unstable series of versions, remove "+ n" before release.
|
||||||
|
iexportVersionCurrent = iexportVersionGenerics + 1
|
||||||
|
)
|
||||||
|
|
||||||
// predeclReserved is the number of type offsets reserved for types
|
// predeclReserved is the number of type offsets reserved for types
|
||||||
// implicitly declared in the universe block.
|
// implicitly declared in the universe block.
|
||||||
@ -297,7 +305,7 @@ func WriteExports(out *bufio.Writer) {
|
|||||||
// Assemble header.
|
// Assemble header.
|
||||||
var hdr intWriter
|
var hdr intWriter
|
||||||
hdr.WriteByte('i')
|
hdr.WriteByte('i')
|
||||||
hdr.uint64(iexportVersion)
|
hdr.uint64(iexportVersionCurrent)
|
||||||
hdr.uint64(uint64(p.strings.Len()))
|
hdr.uint64(uint64(p.strings.Len()))
|
||||||
hdr.uint64(dataLen)
|
hdr.uint64(dataLen)
|
||||||
|
|
||||||
|
@ -121,8 +121,14 @@ func ReadImports(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintT
|
|||||||
ird := &intReader{in, pkg}
|
ird := &intReader{in, pkg}
|
||||||
|
|
||||||
version := ird.uint64()
|
version := ird.uint64()
|
||||||
if version != iexportVersion {
|
switch version {
|
||||||
base.Errorf("import %q: unknown export format version %d", pkg.Path, version)
|
case iexportVersionCurrent, iexportVersionPosCol, iexportVersionGo1_11:
|
||||||
|
default:
|
||||||
|
if version > iexportVersionGenerics {
|
||||||
|
base.Errorf("import %q: unstable export format version %d, just recompile", pkg.Path, version)
|
||||||
|
} else {
|
||||||
|
base.Errorf("import %q: unknown export format version %d", pkg.Path, version)
|
||||||
|
}
|
||||||
base.ErrorExit()
|
base.ErrorExit()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +149,8 @@ func ReadImports(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintT
|
|||||||
in.MustSeek(int64(sLen+dLen), os.SEEK_CUR)
|
in.MustSeek(int64(sLen+dLen), os.SEEK_CUR)
|
||||||
|
|
||||||
p := &iimporter{
|
p := &iimporter{
|
||||||
ipkg: pkg,
|
exportVersion: version,
|
||||||
|
ipkg: pkg,
|
||||||
|
|
||||||
pkgCache: map[uint64]*types.Pkg{},
|
pkgCache: map[uint64]*types.Pkg{},
|
||||||
posBaseCache: map[uint64]*src.PosBase{},
|
posBaseCache: map[uint64]*src.PosBase{},
|
||||||
@ -212,7 +219,8 @@ func ReadImports(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintT
|
|||||||
}
|
}
|
||||||
|
|
||||||
type iimporter struct {
|
type iimporter struct {
|
||||||
ipkg *types.Pkg
|
exportVersion uint64
|
||||||
|
ipkg *types.Pkg
|
||||||
|
|
||||||
pkgCache map[uint64]*types.Pkg
|
pkgCache map[uint64]*types.Pkg
|
||||||
posBaseCache map[uint64]*src.PosBase
|
posBaseCache map[uint64]*src.PosBase
|
||||||
@ -314,7 +322,10 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name {
|
|||||||
return n
|
return n
|
||||||
|
|
||||||
case 'F':
|
case 'F':
|
||||||
tparams := r.tparamList()
|
var tparams []*types.Field
|
||||||
|
if r.p.exportVersion >= iexportVersionGenerics {
|
||||||
|
tparams = r.tparamList()
|
||||||
|
}
|
||||||
typ := r.signature(nil, tparams)
|
typ := r.signature(nil, tparams)
|
||||||
|
|
||||||
n := importfunc(r.p.ipkg, pos, sym, typ)
|
n := importfunc(r.p.ipkg, pos, sym, typ)
|
||||||
@ -322,7 +333,10 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name {
|
|||||||
return n
|
return n
|
||||||
|
|
||||||
case 'T':
|
case 'T':
|
||||||
rparams := r.typeList()
|
var rparams []*types.Type
|
||||||
|
if r.p.exportVersion >= iexportVersionGenerics {
|
||||||
|
rparams = r.typeList()
|
||||||
|
}
|
||||||
|
|
||||||
// Types can be recursive. We need to setup a stub
|
// Types can be recursive. We need to setup a stub
|
||||||
// declaration before recursing.
|
// declaration before recursing.
|
||||||
@ -738,6 +752,9 @@ func (r *importReader) typ1() *types.Type {
|
|||||||
return t
|
return t
|
||||||
|
|
||||||
case typeParamType:
|
case typeParamType:
|
||||||
|
if r.p.exportVersion < iexportVersionGenerics {
|
||||||
|
base.Fatalf("unexpected type param type")
|
||||||
|
}
|
||||||
r.setPkg()
|
r.setPkg()
|
||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
name := r.string()
|
name := r.string()
|
||||||
@ -761,6 +778,9 @@ func (r *importReader) typ1() *types.Type {
|
|||||||
return t
|
return t
|
||||||
|
|
||||||
case instType:
|
case instType:
|
||||||
|
if r.p.exportVersion < iexportVersionGenerics {
|
||||||
|
base.Fatalf("unexpected instantiation type")
|
||||||
|
}
|
||||||
pos := r.pos()
|
pos := r.pos()
|
||||||
len := r.uint64()
|
len := r.uint64()
|
||||||
targs := make([]*types.Type, len)
|
targs := make([]*types.Type, len)
|
||||||
|
@ -139,7 +139,7 @@ func TestVersionHandling(t *testing.T) {
|
|||||||
|
|
||||||
// This package only handles gc export data.
|
// This package only handles gc export data.
|
||||||
// Disable test until we put in the new export version.
|
// Disable test until we put in the new export version.
|
||||||
if true || runtime.Compiler != "gc" {
|
if runtime.Compiler != "gc" {
|
||||||
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,16 @@ func (r *intReader) uint64() uint64 {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep this in sync with constants in iexport.go.
|
||||||
|
const (
|
||||||
|
iexportVersionGo1_11 = 0
|
||||||
|
iexportVersionPosCol = 1
|
||||||
|
iexportVersionGenerics = 2
|
||||||
|
|
||||||
|
// Start of the unstable series of versions, remove "+ n" before release.
|
||||||
|
iexportVersionCurrent = iexportVersionGenerics + 1
|
||||||
|
)
|
||||||
|
|
||||||
const predeclReserved = 32
|
const predeclReserved = 32
|
||||||
|
|
||||||
type itag uint64
|
type itag uint64
|
||||||
@ -64,7 +74,7 @@ const (
|
|||||||
// If the export data version is not recognized or the format is otherwise
|
// If the export data version is not recognized or the format is otherwise
|
||||||
// compromised, an error is returned.
|
// compromised, an error is returned.
|
||||||
func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
|
func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
|
||||||
const currentVersion = 1
|
const currentVersion = iexportVersionCurrent
|
||||||
version := int64(-1)
|
version := int64(-1)
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
@ -80,9 +90,13 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
|
|||||||
|
|
||||||
version = int64(r.uint64())
|
version = int64(r.uint64())
|
||||||
switch version {
|
switch version {
|
||||||
case currentVersion, 0:
|
case currentVersion, iexportVersionPosCol, iexportVersionGo1_11:
|
||||||
default:
|
default:
|
||||||
errorf("unknown iexport format version %d", version)
|
if version > iexportVersionGenerics {
|
||||||
|
errorf("unstable iexport format version %d, just rebuild compiler and std library", version)
|
||||||
|
} else {
|
||||||
|
errorf("unknown iexport format version %d", version)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sLen := int64(r.uint64())
|
sLen := int64(r.uint64())
|
||||||
@ -94,8 +108,9 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
|
|||||||
r.Seek(sLen+dLen, io.SeekCurrent)
|
r.Seek(sLen+dLen, io.SeekCurrent)
|
||||||
|
|
||||||
p := iimporter{
|
p := iimporter{
|
||||||
ipath: path,
|
exportVersion: version,
|
||||||
version: int(version),
|
ipath: path,
|
||||||
|
version: int(version),
|
||||||
|
|
||||||
stringData: stringData,
|
stringData: stringData,
|
||||||
stringCache: make(map[uint64]string),
|
stringCache: make(map[uint64]string),
|
||||||
@ -173,8 +188,9 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
|
|||||||
}
|
}
|
||||||
|
|
||||||
type iimporter struct {
|
type iimporter struct {
|
||||||
ipath string
|
exportVersion int64
|
||||||
version int
|
ipath string
|
||||||
|
version int
|
||||||
|
|
||||||
stringData []byte
|
stringData []byte
|
||||||
stringCache map[uint64]string
|
stringCache map[uint64]string
|
||||||
@ -273,19 +289,22 @@ func (r *importReader) obj(name string) {
|
|||||||
r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
|
r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
|
||||||
|
|
||||||
case 'F':
|
case 'F':
|
||||||
numTparams := r.uint64()
|
if r.p.exportVersion >= iexportVersionGenerics {
|
||||||
if numTparams > 0 {
|
numTparams := r.uint64()
|
||||||
errorf("unexpected tparam")
|
if numTparams > 0 {
|
||||||
return
|
errorf("unexpected tparam")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sig := r.signature(nil)
|
sig := r.signature(nil)
|
||||||
|
|
||||||
r.declare(types.NewFunc(pos, r.currPkg, name, sig))
|
r.declare(types.NewFunc(pos, r.currPkg, name, sig))
|
||||||
|
|
||||||
case 'T':
|
case 'T':
|
||||||
numTparams := r.uint64()
|
if r.p.exportVersion >= iexportVersionGenerics {
|
||||||
if numTparams > 0 {
|
numTparams := r.uint64()
|
||||||
errorf("unexpected tparam")
|
if numTparams > 0 {
|
||||||
|
errorf("unexpected tparam")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Types can be recursive. We need to setup a stub
|
// Types can be recursive. We need to setup a stub
|
||||||
@ -562,7 +581,7 @@ func (r *importReader) doType(base *types.Named) types.Type {
|
|||||||
return typ
|
return typ
|
||||||
|
|
||||||
case typeParamType:
|
case typeParamType:
|
||||||
errorf("do not handle tparams yet")
|
errorf("do not handle type param types yet")
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case instType:
|
case instType:
|
||||||
|
50
test/typeparam/listimp.dir/a.go
Normal file
50
test/typeparam/listimp.dir/a.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package a
|
||||||
|
|
||||||
|
type Ordered interface {
|
||||||
|
type int, int8, int16, int32, int64,
|
||||||
|
uint, uint8, uint16, uint32, uint64, uintptr,
|
||||||
|
float32, float64,
|
||||||
|
string
|
||||||
|
}
|
||||||
|
|
||||||
|
// List is a linked list of ordered values of type T.
|
||||||
|
type List[T Ordered] struct {
|
||||||
|
Next *List[T]
|
||||||
|
Val T
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *List[T]) Largest() T {
|
||||||
|
var max T
|
||||||
|
for p := l; p != nil; p = p.Next {
|
||||||
|
if p.Val > max {
|
||||||
|
max = p.Val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderedNum interface {
|
||||||
|
type int, int8, int16, int32, int64,
|
||||||
|
uint, uint8, uint16, uint32, uint64, uintptr,
|
||||||
|
float32, float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListNum is a linked _List of ordered numeric values of type T.
|
||||||
|
type ListNum[T OrderedNum] struct {
|
||||||
|
Next *ListNum[T]
|
||||||
|
Val T
|
||||||
|
}
|
||||||
|
|
||||||
|
const Clip = 5
|
||||||
|
|
||||||
|
// clippedLargest returns the largest in the list of OrderNums, but a max of 5.
|
||||||
|
// TODO(danscales): fix export/import of an untype constant with typeparam type
|
||||||
|
func (l *ListNum[T]) ClippedLargest() T {
|
||||||
|
var max T
|
||||||
|
for p := l; p != nil; p = p.Next {
|
||||||
|
if p.Val > max && p.Val < T(Clip) {
|
||||||
|
max = p.Val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max
|
||||||
|
}
|
48
test/typeparam/listimp.dir/main.go
Normal file
48
test/typeparam/listimp.dir/main.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"a"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
i3 := &a.List[int]{nil, 1}
|
||||||
|
i2 := &a.List[int]{i3, 3}
|
||||||
|
i1 := &a.List[int]{i2, 2}
|
||||||
|
if got, want := i1.Largest(), 3; got != want {
|
||||||
|
panic(fmt.Sprintf("got %d, want %d", got, want))
|
||||||
|
}
|
||||||
|
|
||||||
|
b3 := &a.List[byte]{nil, byte(1)}
|
||||||
|
b2 := &a.List[byte]{b3, byte(3)}
|
||||||
|
b1 := &a.List[byte]{b2, byte(2)}
|
||||||
|
if got, want := b1.Largest(), byte(3); got != want {
|
||||||
|
panic(fmt.Sprintf("got %d, want %d", got, want))
|
||||||
|
}
|
||||||
|
|
||||||
|
f3 := &a.List[float64]{nil, 13.5}
|
||||||
|
f2 := &a.List[float64]{f3, 1.2}
|
||||||
|
f1 := &a.List[float64]{f2, 4.5}
|
||||||
|
if got, want := f1.Largest(), 13.5; got != want {
|
||||||
|
panic(fmt.Sprintf("got %f, want %f", got, want))
|
||||||
|
}
|
||||||
|
|
||||||
|
s3 := &a.List[string]{nil, "dd"}
|
||||||
|
s2 := &a.List[string]{s3, "aa"}
|
||||||
|
s1 := &a.List[string]{s2, "bb"}
|
||||||
|
if got, want := s1.Largest(), "dd"; got != want {
|
||||||
|
panic(fmt.Sprintf("got %s, want %s", got, want))
|
||||||
|
}
|
||||||
|
j3 := &a.ListNum[int]{nil, 1}
|
||||||
|
j2 := &a.ListNum[int]{j3, 32}
|
||||||
|
j1 := &a.ListNum[int]{j2, 2}
|
||||||
|
if got, want := j1.ClippedLargest(), 2; got != want {
|
||||||
|
panic(fmt.Sprintf("got %d, want %d", got, want))
|
||||||
|
}
|
||||||
|
g3 := &a.ListNum[float64]{nil, 13.5}
|
||||||
|
g2 := &a.ListNum[float64]{g3, 1.2}
|
||||||
|
g1 := &a.ListNum[float64]{g2, 4.5}
|
||||||
|
if got, want := g1.ClippedLargest(), 4.5; got != want {
|
||||||
|
panic(fmt.Sprintf("got %f, want %f", got, want))
|
||||||
|
}
|
||||||
|
}
|
7
test/typeparam/listimp.go
Normal file
7
test/typeparam/listimp.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// rundir -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 ignored
|
Loading…
Reference in New Issue
Block a user