mirror of
https://github.com/golang/go.git
synced 2026-01-31 16:12:04 +03:00
Compare commits
28 Commits
dev.typepa
...
go1.17.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ac3bdf378 | ||
|
|
4925e0766f | ||
|
|
b18ba59aaf | ||
|
|
04242ac88f | ||
|
|
c5c1d069da | ||
|
|
abc4f092ac | ||
|
|
e79c297fa8 | ||
|
|
21a4e67ad5 | ||
|
|
328cf2e8b2 | ||
|
|
fcce86c4cf | ||
|
|
36c171763e | ||
|
|
678b07d5e5 | ||
|
|
14c9b1e00b | ||
|
|
c35f8a37d9 | ||
|
|
47a57bc4f0 | ||
|
|
2d97a87287 | ||
|
|
3969694203 | ||
|
|
1dd24caf08 | ||
|
|
ec5170397c | ||
|
|
fdd6dfd507 | ||
|
|
f7b9470992 | ||
|
|
4397d66bdd | ||
|
|
eb5a7b5050 | ||
|
|
72ab3ff68b | ||
|
|
c3ccb77d1e | ||
|
|
c3b47cb598 | ||
|
|
ddfd72f7d1 | ||
|
|
d6f4d9a2be |
@@ -1 +1,2 @@
|
||||
branch: master
|
||||
branch: release-branch.go1.17
|
||||
parent-branch: master
|
||||
|
||||
@@ -753,9 +753,9 @@ func Foo() bool {
|
||||
|
||||
<p><!-- CL 311572 -->
|
||||
The new
|
||||
<a href="/pkg/database/sql/#NullInt16"><code>NullInt16</code></a>
|
||||
and
|
||||
<a href="/pkg/database/sql/#NullByte"><code>NullByte</code></a>
|
||||
<a href="/pkg/database/sql/#NullInt16"><code>NullInt16</code></a>
|
||||
and
|
||||
<a href="/pkg/database/sql/#NullByte"><code>NullByte</code></a>
|
||||
structs represent the int16 and byte values that may be null. These can be used as
|
||||
destinations of the <a href="/pkg/database/sql/#Scan"><code>Scan</code></a> method,
|
||||
similar to NullString.
|
||||
@@ -1205,11 +1205,11 @@ func Foo() bool {
|
||||
|
||||
<p><!-- CL 300996 -->
|
||||
The package now accepts comma "," as a separator for fractional seconds when parsing and formatting time.
|
||||
The following time formats are now accepted:
|
||||
For example, the following time layouts are now accepted:
|
||||
<ul>
|
||||
<li>2006-01-02 14:06:03,999999999 -0700 MST</li>
|
||||
<li>Mon Jan _2 14:06:03,120007 2006</li>
|
||||
<li>Mon Jan 2 14:06:03,120007 2006</li>
|
||||
<li>2006-01-02 15:04:05,999999999 -0700 MST</li>
|
||||
<li>Mon Jan _2 15:04:05,000000 2006</li>
|
||||
<li>Monday, January 2 15:04:05,000 2006</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
|
||||
@@ -567,6 +567,13 @@
|
||||
offset += 8;
|
||||
});
|
||||
|
||||
// The linker guarantees global data starts from at least wasmMinDataAddr.
|
||||
// Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr.
|
||||
const wasmMinDataAddr = 4096 + 4096;
|
||||
if (offset >= wasmMinDataAddr) {
|
||||
throw new Error("command line too long");
|
||||
}
|
||||
|
||||
this._inst.exports.run(argc, argv);
|
||||
if (this.exited) {
|
||||
this._resolveExitPromise();
|
||||
|
||||
@@ -102,7 +102,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
|
||||
// indicate it contains up to 1 << 128 - 1 files. Since each file has a
|
||||
// header which will be _at least_ 30 bytes we can safely preallocate
|
||||
// if (data size / 30) >= end.directoryRecords.
|
||||
if (uint64(size)-end.directorySize)/30 >= end.directoryRecords {
|
||||
if end.directorySize < uint64(size) && (uint64(size)-end.directorySize)/30 >= end.directoryRecords {
|
||||
z.File = make([]*File, 0, end.directoryRecords)
|
||||
}
|
||||
z.Comment = end.comment
|
||||
|
||||
@@ -1384,3 +1384,21 @@ func TestCVE202133196(t *testing.T) {
|
||||
t.Errorf("Archive has unexpected number of files, got %d, want 5", len(r.File))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCVE202139293(t *testing.T) {
|
||||
// directory size is so large, that the check in Reader.init
|
||||
// overflows when subtracting from the archive size, causing
|
||||
// the pre-allocation check to be bypassed.
|
||||
data := []byte{
|
||||
0x50, 0x4b, 0x06, 0x06, 0x05, 0x06, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b,
|
||||
0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x4b,
|
||||
0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||
0xff, 0x50, 0xfe, 0x00, 0xff, 0x00, 0x3a, 0x00, 0x00, 0x00, 0xff,
|
||||
}
|
||||
_, err := NewReader(bytes.NewReader(data), int64(len(data)))
|
||||
if err != ErrFormat {
|
||||
t.Fatalf("unexpected error, got: %v, want: %v", err, ErrFormat)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2387,6 +2387,175 @@ func (s *state) ssaShiftOp(op ir.Op, t *types.Type, u *types.Type) ssa.Op {
|
||||
return x
|
||||
}
|
||||
|
||||
func (s *state) conv(n ir.Node, v *ssa.Value, ft, tt *types.Type) *ssa.Value {
|
||||
if ft.IsBoolean() && tt.IsKind(types.TUINT8) {
|
||||
// Bool -> uint8 is generated internally when indexing into runtime.staticbyte.
|
||||
return s.newValue1(ssa.OpCopy, tt, v)
|
||||
}
|
||||
if ft.IsInteger() && tt.IsInteger() {
|
||||
var op ssa.Op
|
||||
if tt.Size() == ft.Size() {
|
||||
op = ssa.OpCopy
|
||||
} else if tt.Size() < ft.Size() {
|
||||
// truncation
|
||||
switch 10*ft.Size() + tt.Size() {
|
||||
case 21:
|
||||
op = ssa.OpTrunc16to8
|
||||
case 41:
|
||||
op = ssa.OpTrunc32to8
|
||||
case 42:
|
||||
op = ssa.OpTrunc32to16
|
||||
case 81:
|
||||
op = ssa.OpTrunc64to8
|
||||
case 82:
|
||||
op = ssa.OpTrunc64to16
|
||||
case 84:
|
||||
op = ssa.OpTrunc64to32
|
||||
default:
|
||||
s.Fatalf("weird integer truncation %v -> %v", ft, tt)
|
||||
}
|
||||
} else if ft.IsSigned() {
|
||||
// sign extension
|
||||
switch 10*ft.Size() + tt.Size() {
|
||||
case 12:
|
||||
op = ssa.OpSignExt8to16
|
||||
case 14:
|
||||
op = ssa.OpSignExt8to32
|
||||
case 18:
|
||||
op = ssa.OpSignExt8to64
|
||||
case 24:
|
||||
op = ssa.OpSignExt16to32
|
||||
case 28:
|
||||
op = ssa.OpSignExt16to64
|
||||
case 48:
|
||||
op = ssa.OpSignExt32to64
|
||||
default:
|
||||
s.Fatalf("bad integer sign extension %v -> %v", ft, tt)
|
||||
}
|
||||
} else {
|
||||
// zero extension
|
||||
switch 10*ft.Size() + tt.Size() {
|
||||
case 12:
|
||||
op = ssa.OpZeroExt8to16
|
||||
case 14:
|
||||
op = ssa.OpZeroExt8to32
|
||||
case 18:
|
||||
op = ssa.OpZeroExt8to64
|
||||
case 24:
|
||||
op = ssa.OpZeroExt16to32
|
||||
case 28:
|
||||
op = ssa.OpZeroExt16to64
|
||||
case 48:
|
||||
op = ssa.OpZeroExt32to64
|
||||
default:
|
||||
s.Fatalf("weird integer sign extension %v -> %v", ft, tt)
|
||||
}
|
||||
}
|
||||
return s.newValue1(op, tt, v)
|
||||
}
|
||||
|
||||
if ft.IsFloat() || tt.IsFloat() {
|
||||
conv, ok := fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]
|
||||
if s.config.RegSize == 4 && Arch.LinkArch.Family != sys.MIPS && !s.softFloat {
|
||||
if conv1, ok1 := fpConvOpToSSA32[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]; ok1 {
|
||||
conv = conv1
|
||||
}
|
||||
}
|
||||
if Arch.LinkArch.Family == sys.ARM64 || Arch.LinkArch.Family == sys.Wasm || Arch.LinkArch.Family == sys.S390X || s.softFloat {
|
||||
if conv1, ok1 := uint64fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]; ok1 {
|
||||
conv = conv1
|
||||
}
|
||||
}
|
||||
|
||||
if Arch.LinkArch.Family == sys.MIPS && !s.softFloat {
|
||||
if ft.Size() == 4 && ft.IsInteger() && !ft.IsSigned() {
|
||||
// tt is float32 or float64, and ft is also unsigned
|
||||
if tt.Size() == 4 {
|
||||
return s.uint32Tofloat32(n, v, ft, tt)
|
||||
}
|
||||
if tt.Size() == 8 {
|
||||
return s.uint32Tofloat64(n, v, ft, tt)
|
||||
}
|
||||
} else if tt.Size() == 4 && tt.IsInteger() && !tt.IsSigned() {
|
||||
// ft is float32 or float64, and tt is unsigned integer
|
||||
if ft.Size() == 4 {
|
||||
return s.float32ToUint32(n, v, ft, tt)
|
||||
}
|
||||
if ft.Size() == 8 {
|
||||
return s.float64ToUint32(n, v, ft, tt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !ok {
|
||||
s.Fatalf("weird float conversion %v -> %v", ft, tt)
|
||||
}
|
||||
op1, op2, it := conv.op1, conv.op2, conv.intermediateType
|
||||
|
||||
if op1 != ssa.OpInvalid && op2 != ssa.OpInvalid {
|
||||
// normal case, not tripping over unsigned 64
|
||||
if op1 == ssa.OpCopy {
|
||||
if op2 == ssa.OpCopy {
|
||||
return v
|
||||
}
|
||||
return s.newValueOrSfCall1(op2, tt, v)
|
||||
}
|
||||
if op2 == ssa.OpCopy {
|
||||
return s.newValueOrSfCall1(op1, tt, v)
|
||||
}
|
||||
return s.newValueOrSfCall1(op2, tt, s.newValueOrSfCall1(op1, types.Types[it], v))
|
||||
}
|
||||
// Tricky 64-bit unsigned cases.
|
||||
if ft.IsInteger() {
|
||||
// tt is float32 or float64, and ft is also unsigned
|
||||
if tt.Size() == 4 {
|
||||
return s.uint64Tofloat32(n, v, ft, tt)
|
||||
}
|
||||
if tt.Size() == 8 {
|
||||
return s.uint64Tofloat64(n, v, ft, tt)
|
||||
}
|
||||
s.Fatalf("weird unsigned integer to float conversion %v -> %v", ft, tt)
|
||||
}
|
||||
// ft is float32 or float64, and tt is unsigned integer
|
||||
if ft.Size() == 4 {
|
||||
return s.float32ToUint64(n, v, ft, tt)
|
||||
}
|
||||
if ft.Size() == 8 {
|
||||
return s.float64ToUint64(n, v, ft, tt)
|
||||
}
|
||||
s.Fatalf("weird float to unsigned integer conversion %v -> %v", ft, tt)
|
||||
return nil
|
||||
}
|
||||
|
||||
if ft.IsComplex() && tt.IsComplex() {
|
||||
var op ssa.Op
|
||||
if ft.Size() == tt.Size() {
|
||||
switch ft.Size() {
|
||||
case 8:
|
||||
op = ssa.OpRound32F
|
||||
case 16:
|
||||
op = ssa.OpRound64F
|
||||
default:
|
||||
s.Fatalf("weird complex conversion %v -> %v", ft, tt)
|
||||
}
|
||||
} else if ft.Size() == 8 && tt.Size() == 16 {
|
||||
op = ssa.OpCvt32Fto64F
|
||||
} else if ft.Size() == 16 && tt.Size() == 8 {
|
||||
op = ssa.OpCvt64Fto32F
|
||||
} else {
|
||||
s.Fatalf("weird complex conversion %v -> %v", ft, tt)
|
||||
}
|
||||
ftp := types.FloatForComplex(ft)
|
||||
ttp := types.FloatForComplex(tt)
|
||||
return s.newValue2(ssa.OpComplexMake, tt,
|
||||
s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexReal, ftp, v)),
|
||||
s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexImag, ftp, v)))
|
||||
}
|
||||
|
||||
s.Fatalf("unhandled OCONV %s -> %s", ft.Kind(), tt.Kind())
|
||||
return nil
|
||||
}
|
||||
|
||||
// expr converts the expression n to ssa, adds it to s and returns the ssa result.
|
||||
func (s *state) expr(n ir.Node) *ssa.Value {
|
||||
if ir.HasUniquePos(n) {
|
||||
@@ -2574,174 +2743,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
|
||||
case ir.OCONV:
|
||||
n := n.(*ir.ConvExpr)
|
||||
x := s.expr(n.X)
|
||||
ft := n.X.Type() // from type
|
||||
tt := n.Type() // to type
|
||||
if ft.IsBoolean() && tt.IsKind(types.TUINT8) {
|
||||
// Bool -> uint8 is generated internally when indexing into runtime.staticbyte.
|
||||
return s.newValue1(ssa.OpCopy, n.Type(), x)
|
||||
}
|
||||
if ft.IsInteger() && tt.IsInteger() {
|
||||
var op ssa.Op
|
||||
if tt.Size() == ft.Size() {
|
||||
op = ssa.OpCopy
|
||||
} else if tt.Size() < ft.Size() {
|
||||
// truncation
|
||||
switch 10*ft.Size() + tt.Size() {
|
||||
case 21:
|
||||
op = ssa.OpTrunc16to8
|
||||
case 41:
|
||||
op = ssa.OpTrunc32to8
|
||||
case 42:
|
||||
op = ssa.OpTrunc32to16
|
||||
case 81:
|
||||
op = ssa.OpTrunc64to8
|
||||
case 82:
|
||||
op = ssa.OpTrunc64to16
|
||||
case 84:
|
||||
op = ssa.OpTrunc64to32
|
||||
default:
|
||||
s.Fatalf("weird integer truncation %v -> %v", ft, tt)
|
||||
}
|
||||
} else if ft.IsSigned() {
|
||||
// sign extension
|
||||
switch 10*ft.Size() + tt.Size() {
|
||||
case 12:
|
||||
op = ssa.OpSignExt8to16
|
||||
case 14:
|
||||
op = ssa.OpSignExt8to32
|
||||
case 18:
|
||||
op = ssa.OpSignExt8to64
|
||||
case 24:
|
||||
op = ssa.OpSignExt16to32
|
||||
case 28:
|
||||
op = ssa.OpSignExt16to64
|
||||
case 48:
|
||||
op = ssa.OpSignExt32to64
|
||||
default:
|
||||
s.Fatalf("bad integer sign extension %v -> %v", ft, tt)
|
||||
}
|
||||
} else {
|
||||
// zero extension
|
||||
switch 10*ft.Size() + tt.Size() {
|
||||
case 12:
|
||||
op = ssa.OpZeroExt8to16
|
||||
case 14:
|
||||
op = ssa.OpZeroExt8to32
|
||||
case 18:
|
||||
op = ssa.OpZeroExt8to64
|
||||
case 24:
|
||||
op = ssa.OpZeroExt16to32
|
||||
case 28:
|
||||
op = ssa.OpZeroExt16to64
|
||||
case 48:
|
||||
op = ssa.OpZeroExt32to64
|
||||
default:
|
||||
s.Fatalf("weird integer sign extension %v -> %v", ft, tt)
|
||||
}
|
||||
}
|
||||
return s.newValue1(op, n.Type(), x)
|
||||
}
|
||||
|
||||
if ft.IsFloat() || tt.IsFloat() {
|
||||
conv, ok := fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]
|
||||
if s.config.RegSize == 4 && Arch.LinkArch.Family != sys.MIPS && !s.softFloat {
|
||||
if conv1, ok1 := fpConvOpToSSA32[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]; ok1 {
|
||||
conv = conv1
|
||||
}
|
||||
}
|
||||
if Arch.LinkArch.Family == sys.ARM64 || Arch.LinkArch.Family == sys.Wasm || Arch.LinkArch.Family == sys.S390X || s.softFloat {
|
||||
if conv1, ok1 := uint64fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]; ok1 {
|
||||
conv = conv1
|
||||
}
|
||||
}
|
||||
|
||||
if Arch.LinkArch.Family == sys.MIPS && !s.softFloat {
|
||||
if ft.Size() == 4 && ft.IsInteger() && !ft.IsSigned() {
|
||||
// tt is float32 or float64, and ft is also unsigned
|
||||
if tt.Size() == 4 {
|
||||
return s.uint32Tofloat32(n, x, ft, tt)
|
||||
}
|
||||
if tt.Size() == 8 {
|
||||
return s.uint32Tofloat64(n, x, ft, tt)
|
||||
}
|
||||
} else if tt.Size() == 4 && tt.IsInteger() && !tt.IsSigned() {
|
||||
// ft is float32 or float64, and tt is unsigned integer
|
||||
if ft.Size() == 4 {
|
||||
return s.float32ToUint32(n, x, ft, tt)
|
||||
}
|
||||
if ft.Size() == 8 {
|
||||
return s.float64ToUint32(n, x, ft, tt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !ok {
|
||||
s.Fatalf("weird float conversion %v -> %v", ft, tt)
|
||||
}
|
||||
op1, op2, it := conv.op1, conv.op2, conv.intermediateType
|
||||
|
||||
if op1 != ssa.OpInvalid && op2 != ssa.OpInvalid {
|
||||
// normal case, not tripping over unsigned 64
|
||||
if op1 == ssa.OpCopy {
|
||||
if op2 == ssa.OpCopy {
|
||||
return x
|
||||
}
|
||||
return s.newValueOrSfCall1(op2, n.Type(), x)
|
||||
}
|
||||
if op2 == ssa.OpCopy {
|
||||
return s.newValueOrSfCall1(op1, n.Type(), x)
|
||||
}
|
||||
return s.newValueOrSfCall1(op2, n.Type(), s.newValueOrSfCall1(op1, types.Types[it], x))
|
||||
}
|
||||
// Tricky 64-bit unsigned cases.
|
||||
if ft.IsInteger() {
|
||||
// tt is float32 or float64, and ft is also unsigned
|
||||
if tt.Size() == 4 {
|
||||
return s.uint64Tofloat32(n, x, ft, tt)
|
||||
}
|
||||
if tt.Size() == 8 {
|
||||
return s.uint64Tofloat64(n, x, ft, tt)
|
||||
}
|
||||
s.Fatalf("weird unsigned integer to float conversion %v -> %v", ft, tt)
|
||||
}
|
||||
// ft is float32 or float64, and tt is unsigned integer
|
||||
if ft.Size() == 4 {
|
||||
return s.float32ToUint64(n, x, ft, tt)
|
||||
}
|
||||
if ft.Size() == 8 {
|
||||
return s.float64ToUint64(n, x, ft, tt)
|
||||
}
|
||||
s.Fatalf("weird float to unsigned integer conversion %v -> %v", ft, tt)
|
||||
return nil
|
||||
}
|
||||
|
||||
if ft.IsComplex() && tt.IsComplex() {
|
||||
var op ssa.Op
|
||||
if ft.Size() == tt.Size() {
|
||||
switch ft.Size() {
|
||||
case 8:
|
||||
op = ssa.OpRound32F
|
||||
case 16:
|
||||
op = ssa.OpRound64F
|
||||
default:
|
||||
s.Fatalf("weird complex conversion %v -> %v", ft, tt)
|
||||
}
|
||||
} else if ft.Size() == 8 && tt.Size() == 16 {
|
||||
op = ssa.OpCvt32Fto64F
|
||||
} else if ft.Size() == 16 && tt.Size() == 8 {
|
||||
op = ssa.OpCvt64Fto32F
|
||||
} else {
|
||||
s.Fatalf("weird complex conversion %v -> %v", ft, tt)
|
||||
}
|
||||
ftp := types.FloatForComplex(ft)
|
||||
ttp := types.FloatForComplex(tt)
|
||||
return s.newValue2(ssa.OpComplexMake, tt,
|
||||
s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexReal, ftp, x)),
|
||||
s.newValueOrSfCall1(op, ttp, s.newValue1(ssa.OpComplexImag, ftp, x)))
|
||||
}
|
||||
|
||||
s.Fatalf("unhandled OCONV %s -> %s", n.X.Type().Kind(), n.Type().Kind())
|
||||
return nil
|
||||
return s.conv(n, x, n.X.Type(), n.Type())
|
||||
|
||||
case ir.ODOTTYPE:
|
||||
n := n.(*ir.TypeAssertExpr)
|
||||
|
||||
@@ -73,7 +73,7 @@ func embedKind(typ *types.Type) int {
|
||||
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
|
||||
|
||||
@@ -1222,12 +1222,14 @@ func (r *importReader) node() ir.Node {
|
||||
switch op {
|
||||
case ir.ODOT, ir.ODOTPTR, ir.ODOTINTER:
|
||||
n.Selection = r.exoticField()
|
||||
case ir.ODOTMETH, ir.OCALLPART, ir.OMETHEXPR:
|
||||
case ir.OMETHEXPR:
|
||||
n = typecheckMethodExpr(n).(*ir.SelectorExpr)
|
||||
case ir.ODOTMETH, ir.OCALLPART:
|
||||
// These require a Lookup to link to the correct declaration.
|
||||
rcvrType := expr.Type()
|
||||
typ := n.Type()
|
||||
n.Selection = Lookdot(n, rcvrType, 1)
|
||||
if op == ir.OCALLPART || op == ir.OMETHEXPR {
|
||||
if op == ir.OCALLPART {
|
||||
// Lookdot clobbers the opcode and type, undo that.
|
||||
n.SetOp(op)
|
||||
n.SetType(typ)
|
||||
|
||||
@@ -4,12 +4,15 @@ go 1.17
|
||||
|
||||
require (
|
||||
github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect
|
||||
golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e
|
||||
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e // indirect
|
||||
golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a
|
||||
golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect
|
||||
golang.org/x/mod v0.5.1
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56
|
||||
golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e // indirect
|
||||
golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
)
|
||||
|
||||
@@ -13,8 +13,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI=
|
||||
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a h1:e8qnjKz4EE6OjRki9wTadWSIogINvq10sMcuBRORxMY=
|
||||
golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
|
||||
@@ -190,8 +190,8 @@ func limiterForEdit(ctx context.Context, rs *Requirements, tryUpgrade, mustSelec
|
||||
|
||||
// raiseLimitsForUpgrades increases the module versions in maxVersions to the
|
||||
// versions that would be needed to allow each of the modules in tryUpgrade
|
||||
// (individually) and all of the modules in mustSelect (simultaneously) to be
|
||||
// added as roots.
|
||||
// (individually or in any combination) and all of the modules in mustSelect
|
||||
// (simultaneously) to be added as roots.
|
||||
//
|
||||
// Versions not present in maxVersion are unrestricted, and it is assumed that
|
||||
// they will not be promoted to root requirements (and thus will not contribute
|
||||
@@ -213,18 +213,42 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, d
|
||||
}
|
||||
}
|
||||
|
||||
var eagerUpgrades []module.Version
|
||||
var (
|
||||
eagerUpgrades []module.Version
|
||||
isLazyRootPath map[string]bool
|
||||
)
|
||||
if depth == eager {
|
||||
eagerUpgrades = tryUpgrade
|
||||
} else {
|
||||
isLazyRootPath = make(map[string]bool, len(maxVersion))
|
||||
for p := range maxVersion {
|
||||
isLazyRootPath[p] = true
|
||||
}
|
||||
for _, m := range tryUpgrade {
|
||||
isLazyRootPath[m.Path] = true
|
||||
}
|
||||
for _, m := range mustSelect {
|
||||
isLazyRootPath[m.Path] = true
|
||||
}
|
||||
|
||||
allowedRoot := map[module.Version]bool{}
|
||||
|
||||
var allowRoot func(m module.Version) error
|
||||
allowRoot = func(m module.Version) error {
|
||||
if allowedRoot[m] {
|
||||
return nil
|
||||
}
|
||||
allowedRoot[m] = true
|
||||
|
||||
if m.Path == Target.Path {
|
||||
// Target is already considered to be higher than any possible m, so we
|
||||
// won't be upgrading to it anyway and there is no point scanning its
|
||||
// dependencies.
|
||||
continue
|
||||
return nil
|
||||
}
|
||||
|
||||
allow(m)
|
||||
|
||||
summary, err := goModSummary(m)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -234,12 +258,27 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, d
|
||||
// graph, rather than loading the (potentially-overlapping) subgraph for
|
||||
// each upgrade individually.
|
||||
eagerUpgrades = append(eagerUpgrades, m)
|
||||
continue
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, r := range summary.require {
|
||||
allow(r)
|
||||
if isLazyRootPath[r.Path] {
|
||||
// r could become a root as the result of an upgrade or downgrade,
|
||||
// in which case its dependencies will not be pruned out.
|
||||
// We need to allow those dependencies to be upgraded too.
|
||||
if err := allowRoot(r); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// r will not become a root, so its dependencies don't matter.
|
||||
// Allow only r itself.
|
||||
allow(r)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, m := range tryUpgrade {
|
||||
allowRoot(m)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,16 +307,41 @@ func raiseLimitsForUpgrades(ctx context.Context, maxVersion map[string]string, d
|
||||
}
|
||||
}
|
||||
|
||||
if len(mustSelect) > 0 {
|
||||
mustGraph, err := readModGraph(ctx, depth, mustSelect)
|
||||
// Explicitly allow any (transitive) upgrades implied by mustSelect.
|
||||
nextRoots := append([]module.Version(nil), mustSelect...)
|
||||
for nextRoots != nil {
|
||||
module.Sort(nextRoots)
|
||||
rs := newRequirements(depth, nextRoots, nil)
|
||||
nextRoots = nil
|
||||
|
||||
rs, mustGraph, err := expandGraph(ctx, rs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, r := range mustGraph.BuildList() {
|
||||
// Some module in mustSelect requires r, so we must allow at least r.Version
|
||||
// unless it conflicts with an entry in mustSelect.
|
||||
// Some module in mustSelect requires r, so we must allow at least
|
||||
// r.Version (unless it conflicts with another entry in mustSelect, in
|
||||
// which case we will error out either way).
|
||||
allow(r)
|
||||
|
||||
if isLazyRootPath[r.Path] {
|
||||
if v, ok := rs.rootSelected(r.Path); ok && r.Version == v {
|
||||
// r is already a root, so its requirements are already included in
|
||||
// the build list.
|
||||
continue
|
||||
}
|
||||
|
||||
// The dependencies in mustSelect may upgrade (or downgrade) an existing
|
||||
// root to match r, which will remain as a root. However, since r is not
|
||||
// a root of rs, its dependencies have been pruned out of this build
|
||||
// list. We need to add it back explicitly so that we allow any
|
||||
// transitive upgrades that r will pull in.
|
||||
if nextRoots == nil {
|
||||
nextRoots = rs.rootModules // already capped
|
||||
}
|
||||
nextRoots = append(nextRoots, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
67
src/cmd/go/testdata/script/mod_all.txt
vendored
67
src/cmd/go/testdata/script/mod_all.txt
vendored
@@ -202,9 +202,9 @@ go mod edit -go=1.17 u/go.mod
|
||||
go mod edit -go=1.17 w/go.mod
|
||||
go mod edit -go=1.17 x/go.mod
|
||||
go mod edit -go=1.17
|
||||
cp go.mod go.mod.orig
|
||||
cmp go.mod go.mod.beforetidy
|
||||
go mod tidy
|
||||
cmp go.mod go.mod.orig
|
||||
cmp go.mod go.mod.aftertidy
|
||||
|
||||
# With lazy loading, 'go list all' with neither -mod=vendor nor -test should
|
||||
# match -mod=vendor without -test in 1.15.
|
||||
@@ -466,3 +466,66 @@ module example.com/x
|
||||
go 1.15
|
||||
-- x/x.go --
|
||||
package x
|
||||
-- go.mod.beforetidy --
|
||||
module example.com/main
|
||||
|
||||
// Note: this go.mod file initially specifies go 1.15,
|
||||
// but includes some redundant roots so that it
|
||||
// also already obeys the 1.17 lazy loading invariants.
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
example.com/a v0.1.0
|
||||
example.com/b v0.1.0 // indirect
|
||||
example.com/q v0.1.0
|
||||
example.com/r v0.1.0 // indirect
|
||||
example.com/t v0.1.0
|
||||
example.com/u v0.1.0 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
example.com/a v0.1.0 => ./a
|
||||
example.com/b v0.1.0 => ./b
|
||||
example.com/c v0.1.0 => ./c
|
||||
example.com/d v0.1.0 => ./d
|
||||
example.com/q v0.1.0 => ./q
|
||||
example.com/r v0.1.0 => ./r
|
||||
example.com/s v0.1.0 => ./s
|
||||
example.com/t v0.1.0 => ./t
|
||||
example.com/u v0.1.0 => ./u
|
||||
example.com/w v0.1.0 => ./w
|
||||
example.com/x v0.1.0 => ./x
|
||||
)
|
||||
-- go.mod.aftertidy --
|
||||
module example.com/main
|
||||
|
||||
// Note: this go.mod file initially specifies go 1.15,
|
||||
// but includes some redundant roots so that it
|
||||
// also already obeys the 1.17 lazy loading invariants.
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
example.com/a v0.1.0
|
||||
example.com/q v0.1.0
|
||||
example.com/t v0.1.0
|
||||
)
|
||||
|
||||
require (
|
||||
example.com/b v0.1.0 // indirect
|
||||
example.com/r v0.1.0 // indirect
|
||||
example.com/u v0.1.0 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
example.com/a v0.1.0 => ./a
|
||||
example.com/b v0.1.0 => ./b
|
||||
example.com/c v0.1.0 => ./c
|
||||
example.com/d v0.1.0 => ./d
|
||||
example.com/q v0.1.0 => ./q
|
||||
example.com/r v0.1.0 => ./r
|
||||
example.com/s v0.1.0 => ./s
|
||||
example.com/t v0.1.0 => ./t
|
||||
example.com/u v0.1.0 => ./u
|
||||
example.com/w v0.1.0 => ./w
|
||||
example.com/x v0.1.0 => ./x
|
||||
)
|
||||
|
||||
117
src/cmd/go/testdata/script/mod_get_issue47979.txt
vendored
Normal file
117
src/cmd/go/testdata/script/mod_get_issue47979.txt
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
# Regression test for https://golang.org/issue/47979:
|
||||
#
|
||||
# An argument to 'go get' that results in an upgrade to a different existing
|
||||
# root should be allowed, and should not panic the 'go' command.
|
||||
|
||||
cp go.mod go.mod.orig
|
||||
|
||||
|
||||
# Transitive upgrades from upgraded roots should not prevent
|
||||
# 'go get -u' from performing upgrades.
|
||||
|
||||
cp go.mod.orig go.mod
|
||||
go get -u -d .
|
||||
cmp go.mod go.mod.want
|
||||
|
||||
|
||||
# 'go get' of a specific version should allow upgrades of
|
||||
# every dependency (transitively) required by that version,
|
||||
# including dependencies that are pulled into the module
|
||||
# graph by upgrading other root requirements
|
||||
# (in this case, example.net/indirect).
|
||||
|
||||
cp go.mod.orig go.mod
|
||||
go get -d example.net/a@v0.2.0
|
||||
cmp go.mod go.mod.want
|
||||
|
||||
|
||||
-- go.mod --
|
||||
module golang.org/issue47979
|
||||
|
||||
go 1.17
|
||||
|
||||
replace (
|
||||
example.net/a v0.1.0 => ./a1
|
||||
example.net/a v0.2.0 => ./a2
|
||||
example.net/indirect v0.1.0 => ./indirect1
|
||||
example.net/indirect v0.2.0 => ./indirect2
|
||||
example.net/other v0.1.0 => ./other
|
||||
example.net/other v0.2.0 => ./other
|
||||
)
|
||||
|
||||
require (
|
||||
example.net/a v0.1.0
|
||||
example.net/other v0.1.0
|
||||
)
|
||||
|
||||
require example.net/indirect v0.1.0 // indirect
|
||||
-- go.mod.want --
|
||||
module golang.org/issue47979
|
||||
|
||||
go 1.17
|
||||
|
||||
replace (
|
||||
example.net/a v0.1.0 => ./a1
|
||||
example.net/a v0.2.0 => ./a2
|
||||
example.net/indirect v0.1.0 => ./indirect1
|
||||
example.net/indirect v0.2.0 => ./indirect2
|
||||
example.net/other v0.1.0 => ./other
|
||||
example.net/other v0.2.0 => ./other
|
||||
)
|
||||
|
||||
require (
|
||||
example.net/a v0.2.0
|
||||
example.net/other v0.2.0
|
||||
)
|
||||
|
||||
require example.net/indirect v0.2.0 // indirect
|
||||
-- issue.go --
|
||||
package issue
|
||||
|
||||
import _ "example.net/a"
|
||||
-- useother/useother.go --
|
||||
package useother
|
||||
|
||||
import _ "example.net/other"
|
||||
-- a1/go.mod --
|
||||
module example.net/a
|
||||
|
||||
go 1.17
|
||||
|
||||
require example.net/indirect v0.1.0
|
||||
-- a1/a.go --
|
||||
package a
|
||||
-- a2/go.mod --
|
||||
module example.net/a
|
||||
|
||||
go 1.17
|
||||
|
||||
require example.net/indirect v0.2.0
|
||||
-- a2/a.go --
|
||||
package a
|
||||
|
||||
import "example.net/indirect"
|
||||
-- indirect1/go.mod --
|
||||
module example.net/indirect
|
||||
|
||||
go 1.17
|
||||
|
||||
require example.net/other v0.1.0
|
||||
-- indirect1/indirect.go --
|
||||
package indirect
|
||||
-- indirect2/go.mod --
|
||||
module example.net/indirect
|
||||
|
||||
go 1.17
|
||||
|
||||
require example.net/other v0.2.0
|
||||
-- indirect2/indirect.go --
|
||||
package indirect
|
||||
|
||||
import "example.net/other"
|
||||
-- other/go.mod --
|
||||
module example.net/other
|
||||
|
||||
go 1.17
|
||||
-- other/other.go --
|
||||
package other
|
||||
68
src/cmd/go/testdata/script/mod_get_lazy_upgrade_lazy.txt
vendored
Normal file
68
src/cmd/go/testdata/script/mod_get_lazy_upgrade_lazy.txt
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
# Check that 'go get -u' will upgrade a dependency (direct or indirect)
|
||||
# when the main module and the dependency are both lazy.
|
||||
# Verifies #47768.
|
||||
|
||||
# Check that go.mod is tidy, and an upgrade is available.
|
||||
cp go.mod go.mod.orig
|
||||
go mod tidy
|
||||
cmp go.mod go.mod.orig
|
||||
|
||||
go list -m -u example.com/lazyupgrade
|
||||
stdout '^example.com/lazyupgrade v0.1.0 \[v0.1.1\] => ./lazyupgrade@v0.1.0$'
|
||||
|
||||
# 'go get -u' on a package that directly imports the dependency should upgrade.
|
||||
go get -u ./usedirect
|
||||
go list -m example.com/lazyupgrade
|
||||
stdout '^example.com/lazyupgrade v0.1.1 => ./lazyupgrade@v0.1.1$'
|
||||
cp go.mod.orig go.mod
|
||||
|
||||
# 'go get -u' on a package that indirectly imports the dependency should upgrade.
|
||||
go get -u ./useindirect
|
||||
go list -m example.com/lazyupgrade
|
||||
stdout '^example.com/lazyupgrade v0.1.1 => ./lazyupgrade@v0.1.1$'
|
||||
|
||||
-- go.mod --
|
||||
module use
|
||||
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
direct v0.0.0
|
||||
example.com/lazyupgrade v0.1.0
|
||||
)
|
||||
|
||||
replace (
|
||||
direct => ./direct
|
||||
example.com/lazyupgrade v0.1.0 => ./lazyupgrade@v0.1.0
|
||||
example.com/lazyupgrade v0.1.1 => ./lazyupgrade@v0.1.1
|
||||
)
|
||||
-- usedirect/usedirect.go --
|
||||
package use
|
||||
|
||||
import _ "example.com/lazyupgrade"
|
||||
-- useindirect/useindirect.go --
|
||||
package use
|
||||
|
||||
import _ "direct"
|
||||
-- direct/go.mod --
|
||||
module direct
|
||||
|
||||
go 1.17
|
||||
|
||||
require example.com/lazyupgrade v0.1.0
|
||||
-- direct/direct.go --
|
||||
package direct
|
||||
|
||||
import _ "example.com/lazyupgrade"
|
||||
-- lazyupgrade@v0.1.0/go.mod --
|
||||
module example.com/lazyupgrade
|
||||
|
||||
go 1.17
|
||||
-- lazyupgrade@v0.1.0/lazyupgrade.go --
|
||||
package lazyupgrade
|
||||
-- lazyupgrade@v0.1.1/go.mod --
|
||||
module example.com/lazyupgrade
|
||||
|
||||
go 1.17
|
||||
-- lazyupgrade@v0.1.1/lazyupgrade.go --
|
||||
package lazyupgrade
|
||||
22
src/cmd/go/testdata/script/mod_retention.txt
vendored
22
src/cmd/go/testdata/script/mod_retention.txt
vendored
@@ -81,14 +81,14 @@ require (
|
||||
package x
|
||||
import _ "rsc.io/quote"
|
||||
-- go.mod.crlf --
|
||||
module m
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
rsc.io/quote v1.5.2
|
||||
rsc.io/testonly v1.0.0 // indirect
|
||||
)
|
||||
module m
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
rsc.io/quote v1.5.2
|
||||
rsc.io/testonly v1.0.0 // indirect
|
||||
)
|
||||
-- go.mod.unsorted --
|
||||
module m
|
||||
|
||||
@@ -139,10 +139,10 @@ module m
|
||||
|
||||
go $goversion
|
||||
|
||||
require rsc.io/quote v1.5.2
|
||||
|
||||
require (
|
||||
rsc.io/quote v1.5.2
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
|
||||
rsc.io/sampler v1.3.0 // indirect
|
||||
rsc.io/testonly v1.0.0 // indirect
|
||||
)
|
||||
|
||||
require golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
|
||||
|
||||
@@ -72,10 +72,9 @@ go 1.17
|
||||
|
||||
replace example.net/indirect v0.1.0 => ./indirect
|
||||
|
||||
require (
|
||||
example.net/ambiguous/nested v0.1.0 // indirect
|
||||
example.net/indirect v0.1.0
|
||||
)
|
||||
require example.net/indirect v0.1.0
|
||||
|
||||
require example.net/ambiguous/nested v0.1.0 // indirect
|
||||
-- all-m.txt --
|
||||
example.com/m
|
||||
example.net/ambiguous v0.1.0
|
||||
|
||||
@@ -97,10 +97,9 @@ replace (
|
||||
example.net/requireincompatible v0.1.0 => ./requireincompatible
|
||||
)
|
||||
|
||||
require (
|
||||
example.com/retract/incompatible v1.0.0 // indirect
|
||||
example.net/lazy v0.1.0
|
||||
)
|
||||
require example.net/lazy v0.1.0
|
||||
|
||||
require example.com/retract/incompatible v1.0.0 // indirect
|
||||
-- incompatible.go --
|
||||
package incompatible
|
||||
|
||||
|
||||
@@ -2450,6 +2450,11 @@ func splitTextSections(ctxt *Link) bool {
|
||||
return (ctxt.IsPPC64() || (ctxt.IsARM64() && ctxt.IsDarwin())) && ctxt.IsExternal()
|
||||
}
|
||||
|
||||
// On Wasm, we reserve 4096 bytes for zero page, then 4096 bytes for wasm_exec.js
|
||||
// to store command line args. Data sections starts from at least address 8192.
|
||||
// Keep in sync with wasm_exec.js.
|
||||
const wasmMinDataAddr = 4096 + 4096
|
||||
|
||||
// address assigns virtual addresses to all segments and sections and
|
||||
// returns all segments in file order.
|
||||
func (ctxt *Link) address() []*sym.Segment {
|
||||
@@ -2459,10 +2464,14 @@ func (ctxt *Link) address() []*sym.Segment {
|
||||
order = append(order, &Segtext)
|
||||
Segtext.Rwx = 05
|
||||
Segtext.Vaddr = va
|
||||
for _, s := range Segtext.Sections {
|
||||
for i, s := range Segtext.Sections {
|
||||
va = uint64(Rnd(int64(va), int64(s.Align)))
|
||||
s.Vaddr = va
|
||||
va += s.Length
|
||||
|
||||
if ctxt.IsWasm() && i == 0 && va < wasmMinDataAddr {
|
||||
va = wasmMinDataAddr
|
||||
}
|
||||
}
|
||||
|
||||
Segtext.Length = va - uint64(*FlagTextAddr)
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"fmt"
|
||||
"internal/buildcfg"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
@@ -1749,7 +1750,7 @@ func asmbElf(ctxt *Link) {
|
||||
sh.Flags = uint64(elf.SHF_ALLOC)
|
||||
sh.Addralign = 1
|
||||
|
||||
if interpreter == "" && buildcfg.GO_LDSO != "" {
|
||||
if interpreter == "" && buildcfg.GOOS == runtime.GOOS && buildcfg.GOARCH == runtime.GOARCH && buildcfg.GO_LDSO != "" {
|
||||
interpreter = buildcfg.GO_LDSO
|
||||
}
|
||||
|
||||
|
||||
313
src/cmd/vendor/golang.org/x/mod/modfile/rule.go
generated
vendored
313
src/cmd/vendor/golang.org/x/mod/modfile/rule.go
generated
vendored
@@ -956,170 +956,217 @@ func (f *File) SetRequire(req []*Require) {
|
||||
|
||||
// SetRequireSeparateIndirect updates the requirements of f to contain the given
|
||||
// requirements. Comment contents (except for 'indirect' markings) are retained
|
||||
// from the first existing requirement for each module path, and block structure
|
||||
// is maintained as long as the indirect markings match.
|
||||
// from the first existing requirement for each module path. Like SetRequire,
|
||||
// SetRequireSeparateIndirect adds requirements for new paths in req,
|
||||
// updates the version and "// indirect" comment on existing requirements,
|
||||
// and deletes requirements on paths not in req. Existing duplicate requirements
|
||||
// are deleted.
|
||||
//
|
||||
// Any requirements on paths not already present in the file are added. Direct
|
||||
// requirements are added to the last block containing *any* other direct
|
||||
// requirement. Indirect requirements are added to the last block containing
|
||||
// *only* other indirect requirements. If no suitable block exists, a new one is
|
||||
// added, with the last block containing a direct dependency (if any)
|
||||
// immediately before the first block containing only indirect dependencies.
|
||||
// As its name suggests, SetRequireSeparateIndirect puts direct and indirect
|
||||
// requirements into two separate blocks, one containing only direct
|
||||
// requirements, and the other containing only indirect requirements.
|
||||
// SetRequireSeparateIndirect may move requirements between these two blocks
|
||||
// when their indirect markings change. However, SetRequireSeparateIndirect
|
||||
// won't move requirements from other blocks, especially blocks with comments.
|
||||
//
|
||||
// The Syntax field is ignored for requirements in the given blocks.
|
||||
// If the file initially has one uncommented block of requirements,
|
||||
// SetRequireSeparateIndirect will split it into a direct-only and indirect-only
|
||||
// block. This aids in the transition to separate blocks.
|
||||
func (f *File) SetRequireSeparateIndirect(req []*Require) {
|
||||
type modKey struct {
|
||||
path string
|
||||
indirect bool
|
||||
}
|
||||
need := make(map[modKey]string)
|
||||
for _, r := range req {
|
||||
need[modKey{r.Mod.Path, r.Indirect}] = r.Mod.Version
|
||||
// hasComments returns whether a line or block has comments
|
||||
// other than "indirect".
|
||||
hasComments := func(c Comments) bool {
|
||||
return len(c.Before) > 0 || len(c.After) > 0 || len(c.Suffix) > 1 ||
|
||||
(len(c.Suffix) == 1 &&
|
||||
strings.TrimSpace(strings.TrimPrefix(c.Suffix[0].Token, string(slashSlash))) != "indirect")
|
||||
}
|
||||
|
||||
comments := make(map[string]Comments)
|
||||
for _, r := range f.Require {
|
||||
v, ok := need[modKey{r.Mod.Path, r.Indirect}]
|
||||
if !ok {
|
||||
if _, ok := need[modKey{r.Mod.Path, !r.Indirect}]; ok {
|
||||
if _, dup := comments[r.Mod.Path]; !dup {
|
||||
comments[r.Mod.Path] = r.Syntax.Comments
|
||||
}
|
||||
// moveReq adds r to block. If r was in another block, moveReq deletes
|
||||
// it from that block and transfers its comments.
|
||||
moveReq := func(r *Require, block *LineBlock) {
|
||||
var line *Line
|
||||
if r.Syntax == nil {
|
||||
line = &Line{Token: []string{AutoQuote(r.Mod.Path), r.Mod.Version}}
|
||||
r.Syntax = line
|
||||
if r.Indirect {
|
||||
r.setIndirect(true)
|
||||
}
|
||||
r.markRemoved()
|
||||
continue
|
||||
} else {
|
||||
line = new(Line)
|
||||
*line = *r.Syntax
|
||||
if !line.InBlock && len(line.Token) > 0 && line.Token[0] == "require" {
|
||||
line.Token = line.Token[1:]
|
||||
}
|
||||
r.Syntax.Token = nil // Cleanup will delete the old line.
|
||||
r.Syntax = line
|
||||
}
|
||||
r.setVersion(v)
|
||||
delete(need, modKey{r.Mod.Path, r.Indirect})
|
||||
line.InBlock = true
|
||||
block.Line = append(block.Line, line)
|
||||
}
|
||||
|
||||
// Examine existing require lines and blocks.
|
||||
var (
|
||||
lastDirectOrMixedBlock Expr
|
||||
firstIndirectOnlyBlock Expr
|
||||
lastIndirectOnlyBlock Expr
|
||||
// We may insert new requirements into the last uncommented
|
||||
// direct-only and indirect-only blocks. We may also move requirements
|
||||
// to the opposite block if their indirect markings change.
|
||||
lastDirectIndex = -1
|
||||
lastIndirectIndex = -1
|
||||
|
||||
// If there are no direct-only or indirect-only blocks, a new block may
|
||||
// be inserted after the last require line or block.
|
||||
lastRequireIndex = -1
|
||||
|
||||
// If there's only one require line or block, and it's uncommented,
|
||||
// we'll move its requirements to the direct-only or indirect-only blocks.
|
||||
requireLineOrBlockCount = 0
|
||||
|
||||
// Track the block each requirement belongs to (if any) so we can
|
||||
// move them later.
|
||||
lineToBlock = make(map[*Line]*LineBlock)
|
||||
)
|
||||
for _, stmt := range f.Syntax.Stmt {
|
||||
for i, stmt := range f.Syntax.Stmt {
|
||||
switch stmt := stmt.(type) {
|
||||
case *Line:
|
||||
if len(stmt.Token) == 0 || stmt.Token[0] != "require" {
|
||||
continue
|
||||
}
|
||||
if isIndirect(stmt) {
|
||||
lastIndirectOnlyBlock = stmt
|
||||
} else {
|
||||
lastDirectOrMixedBlock = stmt
|
||||
lastRequireIndex = i
|
||||
requireLineOrBlockCount++
|
||||
if !hasComments(stmt.Comments) {
|
||||
if isIndirect(stmt) {
|
||||
lastIndirectIndex = i
|
||||
} else {
|
||||
lastDirectIndex = i
|
||||
}
|
||||
}
|
||||
|
||||
case *LineBlock:
|
||||
if len(stmt.Token) == 0 || stmt.Token[0] != "require" {
|
||||
continue
|
||||
}
|
||||
indirectOnly := true
|
||||
lastRequireIndex = i
|
||||
requireLineOrBlockCount++
|
||||
allDirect := len(stmt.Line) > 0 && !hasComments(stmt.Comments)
|
||||
allIndirect := len(stmt.Line) > 0 && !hasComments(stmt.Comments)
|
||||
for _, line := range stmt.Line {
|
||||
if len(line.Token) == 0 {
|
||||
continue
|
||||
}
|
||||
if !isIndirect(line) {
|
||||
indirectOnly = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if indirectOnly {
|
||||
lastIndirectOnlyBlock = stmt
|
||||
if firstIndirectOnlyBlock == nil {
|
||||
firstIndirectOnlyBlock = stmt
|
||||
}
|
||||
} else {
|
||||
lastDirectOrMixedBlock = stmt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isOrContainsStmt := func(stmt Expr, target Expr) bool {
|
||||
if stmt == target {
|
||||
return true
|
||||
}
|
||||
if stmt, ok := stmt.(*LineBlock); ok {
|
||||
if target, ok := target.(*Line); ok {
|
||||
for _, line := range stmt.Line {
|
||||
if line == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
addRequire := func(path, vers string, indirect bool, comments Comments) {
|
||||
var line *Line
|
||||
if indirect {
|
||||
if lastIndirectOnlyBlock != nil {
|
||||
line = f.Syntax.addLine(lastIndirectOnlyBlock, "require", path, vers)
|
||||
} else {
|
||||
// Add a new require block after the last direct-only or mixed "require"
|
||||
// block (if any).
|
||||
//
|
||||
// (f.Syntax.addLine would add the line to an existing "require" block if
|
||||
// present, but here the existing "require" blocks are all direct-only, so
|
||||
// we know we need to add a new block instead.)
|
||||
line = &Line{Token: []string{"require", path, vers}}
|
||||
lastIndirectOnlyBlock = line
|
||||
firstIndirectOnlyBlock = line // only block implies first block
|
||||
if lastDirectOrMixedBlock == nil {
|
||||
f.Syntax.Stmt = append(f.Syntax.Stmt, line)
|
||||
lineToBlock[line] = stmt
|
||||
if hasComments(line.Comments) {
|
||||
allDirect = false
|
||||
allIndirect = false
|
||||
} else if isIndirect(line) {
|
||||
allDirect = false
|
||||
} else {
|
||||
for i, stmt := range f.Syntax.Stmt {
|
||||
if isOrContainsStmt(stmt, lastDirectOrMixedBlock) {
|
||||
f.Syntax.Stmt = append(f.Syntax.Stmt, nil) // increase size
|
||||
copy(f.Syntax.Stmt[i+2:], f.Syntax.Stmt[i+1:]) // shuffle elements up
|
||||
f.Syntax.Stmt[i+1] = line
|
||||
break
|
||||
}
|
||||
}
|
||||
allIndirect = false
|
||||
}
|
||||
}
|
||||
if allDirect {
|
||||
lastDirectIndex = i
|
||||
}
|
||||
if allIndirect {
|
||||
lastIndirectIndex = i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
oneFlatUncommentedBlock := requireLineOrBlockCount == 1 &&
|
||||
!hasComments(*f.Syntax.Stmt[lastRequireIndex].Comment())
|
||||
|
||||
// Create direct and indirect blocks if needed. Convert lines into blocks
|
||||
// if needed. If we end up with an empty block or a one-line block,
|
||||
// Cleanup will delete it or convert it to a line later.
|
||||
insertBlock := func(i int) *LineBlock {
|
||||
block := &LineBlock{Token: []string{"require"}}
|
||||
f.Syntax.Stmt = append(f.Syntax.Stmt, nil)
|
||||
copy(f.Syntax.Stmt[i+1:], f.Syntax.Stmt[i:])
|
||||
f.Syntax.Stmt[i] = block
|
||||
return block
|
||||
}
|
||||
|
||||
ensureBlock := func(i int) *LineBlock {
|
||||
switch stmt := f.Syntax.Stmt[i].(type) {
|
||||
case *LineBlock:
|
||||
return stmt
|
||||
case *Line:
|
||||
block := &LineBlock{
|
||||
Token: []string{"require"},
|
||||
Line: []*Line{stmt},
|
||||
}
|
||||
stmt.Token = stmt.Token[1:] // remove "require"
|
||||
stmt.InBlock = true
|
||||
f.Syntax.Stmt[i] = block
|
||||
return block
|
||||
default:
|
||||
panic(fmt.Sprintf("unexpected statement: %v", stmt))
|
||||
}
|
||||
}
|
||||
|
||||
var lastDirectBlock *LineBlock
|
||||
if lastDirectIndex < 0 {
|
||||
if lastIndirectIndex >= 0 {
|
||||
lastDirectIndex = lastIndirectIndex
|
||||
lastIndirectIndex++
|
||||
} else if lastRequireIndex >= 0 {
|
||||
lastDirectIndex = lastRequireIndex + 1
|
||||
} else {
|
||||
if lastDirectOrMixedBlock != nil {
|
||||
line = f.Syntax.addLine(lastDirectOrMixedBlock, "require", path, vers)
|
||||
lastDirectIndex = len(f.Syntax.Stmt)
|
||||
}
|
||||
lastDirectBlock = insertBlock(lastDirectIndex)
|
||||
} else {
|
||||
lastDirectBlock = ensureBlock(lastDirectIndex)
|
||||
}
|
||||
|
||||
var lastIndirectBlock *LineBlock
|
||||
if lastIndirectIndex < 0 {
|
||||
lastIndirectIndex = lastDirectIndex + 1
|
||||
lastIndirectBlock = insertBlock(lastIndirectIndex)
|
||||
} else {
|
||||
lastIndirectBlock = ensureBlock(lastIndirectIndex)
|
||||
}
|
||||
|
||||
// Delete requirements we don't want anymore.
|
||||
// Update versions and indirect comments on requirements we want to keep.
|
||||
// If a requirement is in last{Direct,Indirect}Block with the wrong
|
||||
// indirect marking after this, or if the requirement is in an single
|
||||
// uncommented mixed block (oneFlatUncommentedBlock), move it to the
|
||||
// correct block.
|
||||
//
|
||||
// Some blocks may be empty after this. Cleanup will remove them.
|
||||
need := make(map[string]*Require)
|
||||
for _, r := range req {
|
||||
need[r.Mod.Path] = r
|
||||
}
|
||||
have := make(map[string]*Require)
|
||||
for _, r := range f.Require {
|
||||
path := r.Mod.Path
|
||||
if need[path] == nil || have[path] != nil {
|
||||
// Requirement not needed, or duplicate requirement. Delete.
|
||||
r.markRemoved()
|
||||
continue
|
||||
}
|
||||
have[r.Mod.Path] = r
|
||||
r.setVersion(need[path].Mod.Version)
|
||||
r.setIndirect(need[path].Indirect)
|
||||
if need[path].Indirect &&
|
||||
(oneFlatUncommentedBlock || lineToBlock[r.Syntax] == lastDirectBlock) {
|
||||
moveReq(r, lastIndirectBlock)
|
||||
} else if !need[path].Indirect &&
|
||||
(oneFlatUncommentedBlock || lineToBlock[r.Syntax] == lastIndirectBlock) {
|
||||
moveReq(r, lastDirectBlock)
|
||||
}
|
||||
}
|
||||
|
||||
// Add new requirements.
|
||||
for path, r := range need {
|
||||
if have[path] == nil {
|
||||
if r.Indirect {
|
||||
moveReq(r, lastIndirectBlock)
|
||||
} else {
|
||||
// Add a new require block before the first indirect block (if any).
|
||||
//
|
||||
// That way if the file initially contains only indirect lines,
|
||||
// the direct lines still appear before it: we preserve existing
|
||||
// structure, but only to the extent that that structure already
|
||||
// reflects the direct/indirect split.
|
||||
line = &Line{Token: []string{"require", path, vers}}
|
||||
lastDirectOrMixedBlock = line
|
||||
if firstIndirectOnlyBlock == nil {
|
||||
f.Syntax.Stmt = append(f.Syntax.Stmt, line)
|
||||
} else {
|
||||
for i, stmt := range f.Syntax.Stmt {
|
||||
if isOrContainsStmt(stmt, firstIndirectOnlyBlock) {
|
||||
f.Syntax.Stmt = append(f.Syntax.Stmt, nil) // increase size
|
||||
copy(f.Syntax.Stmt[i+1:], f.Syntax.Stmt[i:]) // shuffle elements up
|
||||
f.Syntax.Stmt[i] = line
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
moveReq(r, lastDirectBlock)
|
||||
}
|
||||
f.Require = append(f.Require, r)
|
||||
}
|
||||
|
||||
line.Comments.Before = commentsAdd(line.Comments.Before, comments.Before)
|
||||
line.Comments.Suffix = commentsAdd(line.Comments.Suffix, comments.Suffix)
|
||||
|
||||
r := &Require{
|
||||
Mod: module.Version{Path: path, Version: vers},
|
||||
Indirect: indirect,
|
||||
Syntax: line,
|
||||
}
|
||||
r.setIndirect(indirect)
|
||||
f.Require = append(f.Require, r)
|
||||
}
|
||||
|
||||
for k, vers := range need {
|
||||
addRequire(k.path, vers, k.indirect, comments[k.path])
|
||||
}
|
||||
f.SortBlocks()
|
||||
}
|
||||
|
||||
|
||||
2
src/cmd/vendor/modules.txt
vendored
2
src/cmd/vendor/modules.txt
vendored
@@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm
|
||||
## explicit; go 1.17
|
||||
golang.org/x/crypto/ed25519
|
||||
golang.org/x/crypto/ed25519/internal/edwards25519
|
||||
# golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a
|
||||
# golang.org/x/mod v0.5.1
|
||||
## explicit; go 1.17
|
||||
golang.org/x/mod/internal/lazyregexp
|
||||
golang.org/x/mod/modfile
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin || openbsd
|
||||
// +build darwin openbsd
|
||||
//go:build (darwin && !ios) || openbsd
|
||||
// +build darwin,!ios openbsd
|
||||
|
||||
package rand
|
||||
|
||||
|
||||
@@ -129,3 +129,43 @@ func TestUninitialized(t *testing.T) {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,10 @@ go 1.17
|
||||
|
||||
require (
|
||||
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed
|
||||
golang.org/x/net v0.0.0-20210901185426-6d2eada6345e
|
||||
)
|
||||
|
||||
require (
|
||||
golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect
|
||||
golang.org/x/text v0.3.7-0.20210503195748-5c7c50ebbd4f // indirect
|
||||
)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI=
|
||||
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I=
|
||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210901185426-6d2eada6345e h1:50pLUXxddAhYigPZvsrMVrd+113EKnh8VVRKuSaRviw=
|
||||
golang.org/x/net v0.0.0-20210901185426-6d2eada6345e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 h1:yhBbb4IRs2HS9PPlAg6DMC6mUOKexJBNsLf4Z+6En1Q=
|
||||
|
||||
@@ -224,7 +224,6 @@ func (check *Checker) exprList(elist []ast.Expr, allowCommaOk bool) (xlist []*op
|
||||
// exactly one (possibly invalid or comma-ok) value
|
||||
xlist = []*operand{&x}
|
||||
if allowCommaOk && (x.mode == mapindex || x.mode == commaok || x.mode == commaerr) {
|
||||
x.mode = value
|
||||
x2 := &operand{mode: value, expr: e, typ: Typ[UntypedBool]}
|
||||
if x.mode == commaerr {
|
||||
x2.typ = universeError
|
||||
|
||||
@@ -276,7 +276,7 @@ func (check *Checker) collectObjects() {
|
||||
}
|
||||
|
||||
if name == "init" {
|
||||
check.errorf(d.spec.Name, _InvalidInitDecl, "cannot import package as init - init must be a func")
|
||||
check.errorf(d.spec, _InvalidInitDecl, "cannot import package as init - init must be a func")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && !ios
|
||||
// +build darwin,!ios
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
|
||||
@@ -4519,6 +4519,15 @@ func (sc *http2serverConn) serve() {
|
||||
case res := <-sc.wroteFrameCh:
|
||||
sc.wroteFrame(res)
|
||||
case res := <-sc.readFrameCh:
|
||||
// Process any written frames before reading new frames from the client since a
|
||||
// written frame could have triggered a new stream to be started.
|
||||
if sc.writingFrameAsync {
|
||||
select {
|
||||
case wroteRes := <-sc.wroteFrameCh:
|
||||
sc.wroteFrame(wroteRes)
|
||||
default:
|
||||
}
|
||||
}
|
||||
if !sc.processFrameFromReader(res) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4686,7 +4686,7 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) {
|
||||
return
|
||||
}
|
||||
|
||||
// On mips{,le}, 64bit atomics are emulated with spinlocks, in
|
||||
// On mips{,le}/arm, 64bit atomics are emulated with spinlocks, in
|
||||
// runtime/internal/atomic. If SIGPROF arrives while the program is inside
|
||||
// the critical section, it creates a deadlock (when writing the sample).
|
||||
// As a workaround, create a counter of SIGPROFs while in critical section
|
||||
@@ -4699,6 +4699,13 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if GOARCH == "arm" && goarm < 7 && GOOS == "linux" && pc&0xffff0000 == 0xffff0000 {
|
||||
// runtime/internal/atomic functions call into kernel
|
||||
// helpers on arm < 7. See
|
||||
// runtime/internal/atomic/sys_linux_arm.s.
|
||||
cpuprof.lostAtomic++
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Profiling runs concurrently with GC, so it must not allocate.
|
||||
|
||||
@@ -366,9 +366,9 @@ func deltimer(t *timer) bool {
|
||||
|
||||
// dodeltimer removes timer i from the current P's heap.
|
||||
// We are locked on the P when this is called.
|
||||
// It reports whether it saw no problems due to races.
|
||||
// It returns the smallest changed index in pp.timers.
|
||||
// The caller must have locked the timers for pp.
|
||||
func dodeltimer(pp *p, i int) {
|
||||
func dodeltimer(pp *p, i int) int {
|
||||
if t := pp.timers[i]; t.pp.ptr() != pp {
|
||||
throw("dodeltimer: wrong P")
|
||||
} else {
|
||||
@@ -380,16 +380,18 @@ func dodeltimer(pp *p, i int) {
|
||||
}
|
||||
pp.timers[last] = nil
|
||||
pp.timers = pp.timers[:last]
|
||||
smallestChanged := i
|
||||
if i != last {
|
||||
// Moving to i may have moved the last timer to a new parent,
|
||||
// so sift up to preserve the heap guarantee.
|
||||
siftupTimer(pp.timers, i)
|
||||
smallestChanged = siftupTimer(pp.timers, i)
|
||||
siftdownTimer(pp.timers, i)
|
||||
}
|
||||
if i == 0 {
|
||||
updateTimer0When(pp)
|
||||
}
|
||||
atomic.Xadd(&pp.numTimers, -1)
|
||||
return smallestChanged
|
||||
}
|
||||
|
||||
// dodeltimer0 removes timer 0 from the current P's heap.
|
||||
@@ -674,13 +676,14 @@ func adjusttimers(pp *p, now int64) {
|
||||
switch s := atomic.Load(&t.status); s {
|
||||
case timerDeleted:
|
||||
if atomic.Cas(&t.status, s, timerRemoving) {
|
||||
dodeltimer(pp, i)
|
||||
changed := dodeltimer(pp, i)
|
||||
if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
|
||||
badTimer()
|
||||
}
|
||||
atomic.Xadd(&pp.deletedTimers, -1)
|
||||
// Look at this heap position again.
|
||||
i--
|
||||
// Go back to the earliest changed heap entry.
|
||||
// "- 1" because the loop will add 1.
|
||||
i = changed - 1
|
||||
}
|
||||
case timerModifiedEarlier, timerModifiedLater:
|
||||
if atomic.Cas(&t.status, s, timerMoving) {
|
||||
@@ -690,10 +693,11 @@ func adjusttimers(pp *p, now int64) {
|
||||
// We don't add it back yet because the
|
||||
// heap manipulation could cause our
|
||||
// loop to skip some other timer.
|
||||
dodeltimer(pp, i)
|
||||
changed := dodeltimer(pp, i)
|
||||
moved = append(moved, t)
|
||||
// Look at this heap position again.
|
||||
i--
|
||||
// Go back to the earliest changed heap entry.
|
||||
// "- 1" because the loop will add 1.
|
||||
i = changed - 1
|
||||
}
|
||||
case timerNoStatus, timerRunning, timerRemoving, timerRemoved, timerMoving:
|
||||
badTimer()
|
||||
@@ -1043,7 +1047,10 @@ func timeSleepUntil() (int64, *p) {
|
||||
// "panic holding locks" message. Instead, we panic while not
|
||||
// holding a lock.
|
||||
|
||||
func siftupTimer(t []*timer, i int) {
|
||||
// siftupTimer puts the timer at position i in the right place
|
||||
// in the heap by moving it up toward the top of the heap.
|
||||
// It returns the smallest changed index.
|
||||
func siftupTimer(t []*timer, i int) int {
|
||||
if i >= len(t) {
|
||||
badTimer()
|
||||
}
|
||||
@@ -1063,8 +1070,11 @@ func siftupTimer(t []*timer, i int) {
|
||||
if tmp != t[i] {
|
||||
t[i] = tmp
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
// siftdownTimer puts the timer at position i in the right place
|
||||
// in the heap by moving it down toward the bottom of the heap.
|
||||
func siftdownTimer(t []*timer, i int) {
|
||||
n := len(t)
|
||||
if i >= n {
|
||||
|
||||
@@ -126,7 +126,7 @@ func (v *Value) Swap(new interface{}) (old interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
// CompareAndSwapPointer executes the compare-and-swap operation for the Value.
|
||||
// CompareAndSwap executes the compare-and-swap operation for the Value.
|
||||
//
|
||||
// All calls to CompareAndSwap for a given Value must use values of the same
|
||||
// concrete type. CompareAndSwap of an inconsistent type panics, as does
|
||||
|
||||
@@ -452,3 +452,13 @@ func TestIssue19294(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 48436
|
||||
func TestAddToZeroTemplate(t *testing.T) {
|
||||
tree, err := parse.Parse("c", cloneText3, "", "", nil, builtins())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var tmpl Template
|
||||
tmpl.AddParseTree("x", tree["c"])
|
||||
}
|
||||
|
||||
@@ -127,9 +127,9 @@ func (t *Template) copy(c *common) *Template {
|
||||
// its definition. If it has been defined and already has that name, the existing
|
||||
// definition is replaced; otherwise a new template is created, defined, and returned.
|
||||
func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
|
||||
t.init()
|
||||
t.muTmpl.Lock()
|
||||
defer t.muTmpl.Unlock()
|
||||
t.init()
|
||||
nt := t
|
||||
if name != t.name {
|
||||
nt = t.New(name)
|
||||
|
||||
@@ -77,9 +77,9 @@ import "errors"
|
||||
// The formats and 002 are space-padded and zero-padded
|
||||
// three-character day of year; there is no unpadded day of year format.
|
||||
//
|
||||
// A decimal point followed by one or more zeros represents a fractional
|
||||
// second, printed to the given number of decimal places.
|
||||
// Either a comma or decimal point followed by one or more nines represents
|
||||
// A comma or decimal point followed by one or more zeros represents
|
||||
// a fractional second, printed to the given number of decimal places.
|
||||
// A comma or decimal point followed by one or more nines represents
|
||||
// a fractional second, printed to the given number of decimal places, with
|
||||
// trailing zeros removed.
|
||||
// For example "15:04:05,000" or "15:04:05.000" formats or parses with
|
||||
@@ -146,10 +146,11 @@ const (
|
||||
stdFracSecond0 // ".0", ".00", ... , trailing zeros included
|
||||
stdFracSecond9 // ".9", ".99", ..., trailing zeros omitted
|
||||
|
||||
stdNeedDate = 1 << 8 // need month, day, year
|
||||
stdNeedClock = 2 << 8 // need hour, minute, second
|
||||
stdArgShift = 16 // extra argument in high bits, above low stdArgShift
|
||||
stdMask = 1<<stdArgShift - 1 // mask out argument
|
||||
stdNeedDate = 1 << 8 // need month, day, year
|
||||
stdNeedClock = 2 << 8 // need hour, minute, second
|
||||
stdArgShift = 16 // extra argument in high bits, above low stdArgShift
|
||||
stdSeparatorShift = 28 // extra argument in high 4 bits for fractional second separators
|
||||
stdMask = 1<<stdArgShift - 1 // mask out argument
|
||||
)
|
||||
|
||||
// std0x records the std values for "01", "02", ..., "06".
|
||||
@@ -289,11 +290,11 @@ func nextStdChunk(layout string) (prefix string, std int, suffix string) {
|
||||
}
|
||||
// String of digits must end here - only fractional second is all digits.
|
||||
if !isDigit(layout, j) {
|
||||
std := stdFracSecond0
|
||||
code := stdFracSecond0
|
||||
if layout[i+1] == '9' {
|
||||
std = stdFracSecond9
|
||||
code = stdFracSecond9
|
||||
}
|
||||
std |= (j - (i + 1)) << stdArgShift
|
||||
std := stdFracSecond(code, j-(i+1), c)
|
||||
return layout[0:i], std, layout[j:]
|
||||
}
|
||||
}
|
||||
@@ -430,9 +431,36 @@ func atoi(s string) (x int, err error) {
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// The "std" value passed to formatNano contains two packed fields: the number of
|
||||
// digits after the decimal and the separator character (period or comma).
|
||||
// These functions pack and unpack that variable.
|
||||
func stdFracSecond(code, n, c int) int {
|
||||
// Use 0xfff to make the failure case even more absurd.
|
||||
if c == '.' {
|
||||
return code | ((n & 0xfff) << stdArgShift)
|
||||
}
|
||||
return code | ((n & 0xfff) << stdArgShift) | 1<<stdSeparatorShift
|
||||
}
|
||||
|
||||
func digitsLen(std int) int {
|
||||
return (std >> stdArgShift) & 0xfff
|
||||
}
|
||||
|
||||
func separator(std int) byte {
|
||||
if (std >> stdSeparatorShift) == 0 {
|
||||
return '.'
|
||||
}
|
||||
return ','
|
||||
}
|
||||
|
||||
// formatNano appends a fractional second, as nanoseconds, to b
|
||||
// and returns the result.
|
||||
func formatNano(b []byte, nanosec uint, n int, trim bool) []byte {
|
||||
func formatNano(b []byte, nanosec uint, std int) []byte {
|
||||
var (
|
||||
n = digitsLen(std)
|
||||
separator = separator(std)
|
||||
trim = std&stdMask == stdFracSecond9
|
||||
)
|
||||
u := nanosec
|
||||
var buf [9]byte
|
||||
for start := len(buf); start > 0; {
|
||||
@@ -452,7 +480,7 @@ func formatNano(b []byte, nanosec uint, n int, trim bool) []byte {
|
||||
return b
|
||||
}
|
||||
}
|
||||
b = append(b, '.')
|
||||
b = append(b, separator)
|
||||
return append(b, buf[:n]...)
|
||||
}
|
||||
|
||||
@@ -732,7 +760,7 @@ func (t Time) AppendFormat(b []byte, layout string) []byte {
|
||||
b = appendInt(b, zone/60, 2)
|
||||
b = appendInt(b, zone%60, 2)
|
||||
case stdFracSecond0, stdFracSecond9:
|
||||
b = formatNano(b, uint(t.Nanosecond()), std>>stdArgShift, std&stdMask == stdFracSecond9)
|
||||
b = formatNano(b, uint(t.Nanosecond()), std)
|
||||
}
|
||||
}
|
||||
return b
|
||||
@@ -1164,7 +1192,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
|
||||
case stdFracSecond0:
|
||||
// stdFracSecond0 requires the exact number of digits as specified in
|
||||
// the layout.
|
||||
ndigit := 1 + (std >> stdArgShift)
|
||||
ndigit := 1 + digitsLen(std)
|
||||
if len(value) < ndigit {
|
||||
err = errBad
|
||||
break
|
||||
|
||||
@@ -832,3 +832,23 @@ func TestQuote(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Issue 48037
|
||||
func TestFormatFractionalSecondSeparators(t *testing.T) {
|
||||
tests := []struct {
|
||||
s, want string
|
||||
}{
|
||||
{`15:04:05.000`, `21:00:57.012`},
|
||||
{`15:04:05.999`, `21:00:57.012`},
|
||||
{`15:04:05,000`, `21:00:57,012`},
|
||||
{`15:04:05,999`, `21:00:57,012`},
|
||||
}
|
||||
|
||||
// The numeric time represents Thu Feb 4 21:00:57.012345600 PST 2009
|
||||
time := Unix(0, 1233810057012345600)
|
||||
for _, tt := range tests {
|
||||
if q := time.Format(tt.s); q != tt.want {
|
||||
t.Errorf("Format(%q) = got %q, want %q", tt.s, q, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ package time_test
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -561,6 +562,72 @@ func TestTimerModifiedEarlier(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test that rapidly moving timers earlier and later doesn't cause
|
||||
// some of the sleep times to be lost.
|
||||
// Issue 47762
|
||||
func TestAdjustTimers(t *testing.T) {
|
||||
var rnd = rand.New(rand.NewSource(Now().UnixNano()))
|
||||
|
||||
timers := make([]*Timer, 100)
|
||||
states := make([]int, len(timers))
|
||||
indices := rnd.Perm(len(timers))
|
||||
|
||||
for len(indices) != 0 {
|
||||
var ii = rnd.Intn(len(indices))
|
||||
var i = indices[ii]
|
||||
|
||||
var timer = timers[i]
|
||||
var state = states[i]
|
||||
states[i]++
|
||||
|
||||
switch state {
|
||||
case 0:
|
||||
timers[i] = NewTimer(0)
|
||||
case 1:
|
||||
<-timer.C // Timer is now idle.
|
||||
|
||||
// Reset to various long durations, which we'll cancel.
|
||||
case 2:
|
||||
if timer.Reset(1 * Minute) {
|
||||
panic("shouldn't be active (1)")
|
||||
}
|
||||
case 4:
|
||||
if timer.Reset(3 * Minute) {
|
||||
panic("shouldn't be active (3)")
|
||||
}
|
||||
case 6:
|
||||
if timer.Reset(2 * Minute) {
|
||||
panic("shouldn't be active (2)")
|
||||
}
|
||||
|
||||
// Stop and drain a long-duration timer.
|
||||
case 3, 5, 7:
|
||||
if !timer.Stop() {
|
||||
t.Logf("timer %d state %d Stop returned false", i, state)
|
||||
<-timer.C
|
||||
}
|
||||
|
||||
// Start a short-duration timer we expect to select without blocking.
|
||||
case 8:
|
||||
if timer.Reset(0) {
|
||||
t.Fatal("timer.Reset returned true")
|
||||
}
|
||||
case 9:
|
||||
now := Now()
|
||||
<-timer.C
|
||||
dur := Since(now)
|
||||
if dur > 750*Millisecond {
|
||||
t.Errorf("timer %d took %v to complete", i, dur)
|
||||
}
|
||||
|
||||
// Timer is done. Swap with tail and remove.
|
||||
case 10:
|
||||
indices[ii] = indices[len(indices)-1]
|
||||
indices = indices[:len(indices)-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Benchmark timer latency when the thread that creates the timer is busy with
|
||||
// other work and the timers must be serviced by other threads.
|
||||
// https://golang.org/issue/38860
|
||||
|
||||
2
src/vendor/modules.txt
vendored
2
src/vendor/modules.txt
vendored
@@ -8,7 +8,7 @@ golang.org/x/crypto/curve25519
|
||||
golang.org/x/crypto/hkdf
|
||||
golang.org/x/crypto/internal/subtle
|
||||
golang.org/x/crypto/poly1305
|
||||
# golang.org/x/net v0.0.0-20210510120150-4163338589ed
|
||||
# golang.org/x/net v0.0.0-20210901185426-6d2eada6345e
|
||||
## explicit; go 1.17
|
||||
golang.org/x/net/dns/dnsmessage
|
||||
golang.org/x/net/http/httpguts
|
||||
|
||||
22
test/fixedbugs/issue48088.dir/a.go
Normal file
22
test/fixedbugs/issue48088.dir/a.go
Normal file
@@ -0,0 +1,22 @@
|
||||
// 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 a
|
||||
|
||||
type T1 struct {
|
||||
*T2
|
||||
}
|
||||
|
||||
type T2 struct {
|
||||
}
|
||||
|
||||
func (t2 *T2) M() {
|
||||
}
|
||||
|
||||
func F() {
|
||||
f(T1.M)
|
||||
}
|
||||
|
||||
func f(f func(T1)) {
|
||||
}
|
||||
11
test/fixedbugs/issue48088.dir/b.go
Normal file
11
test/fixedbugs/issue48088.dir/b.go
Normal file
@@ -0,0 +1,11 @@
|
||||
// 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 b
|
||||
|
||||
import "a"
|
||||
|
||||
func F() {
|
||||
a.F()
|
||||
}
|
||||
7
test/fixedbugs/issue48088.go
Normal file
7
test/fixedbugs/issue48088.go
Normal file
@@ -0,0 +1,7 @@
|
||||
// compiledir
|
||||
|
||||
// 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
|
||||
Reference in New Issue
Block a user