1
0
mirror of https://github.com/golang/go synced 2024-11-26 06:17:57 -07:00

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

Merge List:

+ 2021-02-18 eb982727e3 cmd/go/internal/mvs: fix Downgrade to match Algorithm 4
+ 2021-02-18 3b7277d365 cmd/go: add a script test for artifacts resulting from 'go get -u'
+ 2021-02-18 f3c2208e2c cmd/go: add script tests for potential upgrades due to downgrades
+ 2021-02-18 a5c8a15f64 cmd/go/internal/mvs: clarify and annotate test cases
+ 2021-02-18 a76efea1fe cmd/go/internal/mvs: don't emit duplicates from Req
+ 2021-02-18 609d82b289 cmd/dist: set GOARM=7 for windows/arm
+ 2021-02-18 f0be3cc547 runtime: unbreak linux/riscv64 following regabi merge
+ 2021-02-18 07ef313525 runtime/cgo: add cast in C code to avoid C compiler warning

Change-Id: I8e58ad1e82a9ea313a99c1b11df5b341f80680d4
This commit is contained in:
Robert Griesemer 2021-02-18 14:35:08 -08:00
commit e7493a9c74
9 changed files with 462 additions and 34 deletions

View File

@ -389,6 +389,10 @@ func xgetgoarm() string {
// sense to auto-detect the setting. // sense to auto-detect the setting.
return "7" return "7"
} }
if goos == "windows" {
// windows/arm only works with ARMv7 executables.
return "7"
}
if gohostarch != "arm" || goos != gohostos { if gohostarch != "arm" || goos != gohostos {
// Conservative default for cross-compilation. // Conservative default for cross-compilation.
return "5" return "5"

View File

@ -293,10 +293,15 @@ func Req(target module.Version, base []string, reqs Reqs) ([]module.Version, err
} }
// First walk the base modules that must be listed. // First walk the base modules that must be listed.
var min []module.Version var min []module.Version
haveBase := map[string]bool{}
for _, path := range base { for _, path := range base {
if haveBase[path] {
continue
}
m := module.Version{Path: path, Version: max[path]} m := module.Version{Path: path, Version: max[path]}
min = append(min, m) min = append(min, m)
walk(m) walk(m)
haveBase[path] = true
} }
// Now the reverse postorder to bring in anything else. // Now the reverse postorder to bring in anything else.
for i := len(postorder) - 1; i >= 0; i-- { for i := len(postorder) - 1; i >= 0; i-- {
@ -370,10 +375,19 @@ func Upgrade(target module.Version, reqs Reqs, upgrade ...module.Version) ([]mod
// reqs.Previous, but the methods of reqs must otherwise handle such versions // reqs.Previous, but the methods of reqs must otherwise handle such versions
// correctly. // correctly.
func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([]module.Version, error) { func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([]module.Version, error) {
list, err := reqs.Required(target) // Per https://research.swtch.com/vgo-mvs#algorithm_4:
// “To avoid an unnecessary downgrade to E 1.1, we must also add a new
// requirement on E 1.2. We can apply Algorithm R to find the minimal set of
// new requirements to write to go.mod.”
//
// In order to generate those new requirements, we need to identify versions
// for every module in the build list — not just reqs.Required(target).
list, err := BuildList(target, reqs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
list = list[1:] // remove target
max := make(map[string]string) max := make(map[string]string)
for _, r := range list { for _, r := range list {
max[r.Path] = r.Version max[r.Path] = r.Version
@ -406,6 +420,9 @@ func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([
} }
added[m] = true added[m] = true
if v, ok := max[m.Path]; ok && reqs.Max(m.Version, v) != v { if v, ok := max[m.Path]; ok && reqs.Max(m.Version, v) != v {
// m would upgrade an existing dependency — it is not a strict downgrade,
// and because it was already present as a dependency, it could affect the
// behavior of other relevant packages.
exclude(m) exclude(m)
return return
} }
@ -422,6 +439,7 @@ func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([
// is transient (we couldn't download go.mod), return the error from // is transient (we couldn't download go.mod), return the error from
// Downgrade. Currently, we can't tell what kind of error it is. // Downgrade. Currently, we can't tell what kind of error it is.
exclude(m) exclude(m)
return
} }
for _, r := range list { for _, r := range list {
add(r) add(r)
@ -433,8 +451,8 @@ func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([
} }
} }
var out []module.Version downgraded := make([]module.Version, 0, len(list)+1)
out = append(out, target) downgraded = append(downgraded, target)
List: List:
for _, r := range list { for _, r := range list {
add(r) add(r)
@ -461,10 +479,14 @@ List:
add(p) add(p)
r = p r = p
} }
out = append(out, r) downgraded = append(downgraded, r)
} }
return out, nil return BuildList(target, &override{
target: target,
list: downgraded,
Reqs: reqs,
})
} }
type override struct { type override struct {

View File

@ -28,10 +28,11 @@ D4: E2 F1
D5: E2 D5: E2
G1: C4 G1: C4
A2: B1 C4 D4 A2: B1 C4 D4
build A: A B1 C2 D4 E2 F1 build A: A B1 C2 D4 E2 F1
upgrade* A: A B1 C4 D5 E2 F1 G1 upgrade* A: A B1 C4 D5 E2 F1 G1
upgrade A C4: A B1 C4 D4 E2 F1 G1 upgrade A C4: A B1 C4 D4 E2 F1 G1
downgrade A2 D2: A2 C4 D2 build A2: A2 B1 C4 D4 E2 F1 G1
downgrade A2 D2: A2 C4 D2 E2 F1 G1
name: trim name: trim
A: B1 C2 A: B1 C2
@ -68,7 +69,7 @@ B2: D1
C: D2 C: D2
D1: E2 D1: E2
D2: E1 D2: E1
build A: A B1 C D2 E1 build A: A B1 C D2 E1
upgrade A B2: A B2 C D2 E2 upgrade A B2: A B2 C D2 E2
name: cross1R name: cross1R
@ -136,17 +137,17 @@ name: cross5
A: D1 A: D1
D1: E2 D1: E2
D2: E1 D2: E1
build A: A D1 E2 build A: A D1 E2
upgrade* A: A D2 E2 upgrade* A: A D2 E2
upgrade A D2: A D2 E2 upgrade A D2: A D2 E2
upgradereq A D2: D2 E2 upgradereq A D2: D2 E2
name: cross6 name: cross6
A: D2 A: D2
D1: E2 D1: E2
D2: E1 D2: E1
build A: A D2 E1 build A: A D2 E1
upgrade* A: A D2 E2 upgrade* A: A D2 E2
upgrade A E2: A D2 E2 upgrade A E2: A D2 E2
name: cross7 name: cross7
@ -175,7 +176,7 @@ B1: D1
B2: B2:
C2: C2:
D2: D2:
build A: A B1 C1 D1 build A: A B1 C1 D1
upgrade* A: A B2 C2 D2 upgrade* A: A B2 C2 D2
name: simplify name: simplify
@ -194,7 +195,7 @@ B4:
B5.hidden: B5.hidden:
C2: C2:
C3: C3:
build A: A B1 C1 build A: A B1 C1
upgrade* A: A B4 C3 upgrade* A: A B4 C3
name: up2 name: up2
@ -206,15 +207,15 @@ B4:
B5.hidden: B5.hidden:
C2: C2:
C3: C3:
build A: A B5.hidden C1 build A: A B5.hidden C1
upgrade* A: A B5.hidden C3 upgrade* A: A B5.hidden C3
name: down1 name: down1
A: B2 A: B2
B1: C1 B1: C1
B2: C2 B2: C2
build A: A B2 C2 build A: A B2 C2
downgrade A C1: A B1 downgrade A C1: A B1 C1
name: down2 name: down2
A: B2 E2 A: B2 E2
@ -227,12 +228,51 @@ D2: B2
E2: D2 E2: D2
E1: E1:
F1: F1:
downgrade A F1: A B1 E1 build A: A B2 C2 D2 E2 F2
downgrade A F1: A B1 C1 D1 E1 F1
# https://research.swtch.com/vgo-mvs#algorithm_4:
# [D]owngrades are constrained to only downgrade packages, not also upgrade
# them; if an upgrade before downgrade is needed, the user must ask for it
# explicitly.
#
# Here, downgrading B2 to B1 upgrades C1 to C2, and C2 does not depend on D2.
# However, C2 would be an upgrade not a downgrade so B1 must also be
# rejected.
name: downcross1
A: B2 C1
B1: C2
B2: C1
C1: D2
C2:
D1:
D2:
build A: A B2 C1 D2
downgrade A D1: A D1
# https://research.swtch.com/vgo-mvs#algorithm_4:
# Unlike upgrades, downgrades must work by removing requirements, not adding
# them.
#
# However, downgrading a requirement may introduce a new requirement on a
# previously-unrequired module. If each dependency's requirements are complete
# (tidy), that can't change the behavior of any other package whose version is
# not also being downgraded, so we should allow it.
name: downcross2
A: B2
B1: C1
B2: D2
C1:
D1:
D2:
build A: A B2 D2
downgrade A D1: A B1 C1 D1
name: downcycle name: downcycle
A: A B2 A: A B2
B2: A B2: A
B1: B1:
build A: A B2
downgrade A B1: A B1 downgrade A B1: A B1
# golang.org/issue/25542. # golang.org/issue/25542.
@ -240,6 +280,7 @@ name: noprev1
A: B4 C2 A: B4 C2
B2.hidden: B2.hidden:
C2: C2:
build A: A B4 C2
downgrade A B2.hidden: A B2.hidden C2 downgrade A B2.hidden: A B2.hidden C2
name: noprev2 name: noprev2
@ -247,6 +288,7 @@ A: B4 C2
B2.hidden: B2.hidden:
B1: B1:
C2: C2:
build A: A B4 C2
downgrade A B2.hidden: A B2.hidden C2 downgrade A B2.hidden: A B2.hidden C2
name: noprev3 name: noprev3
@ -254,6 +296,7 @@ A: B4 C2
B3: B3:
B2.hidden: B2.hidden:
C2: C2:
build A: A B4 C2
downgrade A B2.hidden: A B2.hidden C2 downgrade A B2.hidden: A B2.hidden C2
# Cycles involving the target. # Cycles involving the target.
@ -264,9 +307,9 @@ A: B1
B1: A1 B1: A1
B2: A2 B2: A2
B3: A3 B3: A3
build A: A B1 build A: A B1
upgrade A B2: A B2 upgrade A B2: A B2
upgrade* A: A B3 upgrade* A: A B3
# golang.org/issue/29773: # golang.org/issue/29773:
# Requirements of older versions of the target # Requirements of older versions of the target
@ -280,7 +323,7 @@ B2: A2
C1: A2 C1: A2
C2: C2:
D2: D2:
build A: A B1 C1 D1 build A: A B1 C1 D1
upgrade* A: A B2 C2 D2 upgrade* A: A B2 C2 D2
# Cycles with multiple possible solutions. # Cycles with multiple possible solutions.
@ -293,23 +336,23 @@ B2: C2
C1: C1:
C2: B2 C2: B2
build M: M A1 B2 C2 build M: M A1 B2 C2
req M: A1 B2 req M: A1 B2
req M A: A1 B2 req M A: A1 B2
req M C: A1 C2 req M C: A1 C2
# Requirement minimization. # Requirement minimization.
name: req1 name: req1
A: B1 C1 D1 E1 F1 A: B1 C1 D1 E1 F1
B1: C1 E1 F1 B1: C1 E1 F1
req A: B1 D1 req A: B1 D1
req A C: B1 C1 D1 req A C: B1 C1 D1
name: req2 name: req2
A: G1 H1 A: G1 H1
G1: H1 G1: H1
H1: G1 H1: G1
req A: G1 req A: G1
req A G: G1 req A G: G1
req A H: H1 req A H: H1
@ -326,7 +369,20 @@ M: Anone B1 D1 E1
B1: Cnone D1 B1: Cnone D1
E1: Fnone E1: Fnone
build M: M B1 D1 E1 build M: M B1 D1 E1
req M: B1 E1 req M: B1 E1
name: reqdup
M: A1 B1
A1: B1
B1:
req M A A: A1
name: reqcross
M: A1 B1 C1
A1: B1 C1
B1: C1
C1:
req M A B: A1 B1
` `
func Test(t *testing.T) { func Test(t *testing.T) {

View File

@ -0,0 +1,81 @@
# This test illustrates a case where downgrading one module may upgrade another.
# Compare to the downcross2 test case in cmd/go/internal/mvs/mvs_test.go.
# The initial package import graph used in this test looks like:
#
# a ---- b ---- d
#
# The module dependency graph originally looks like:
#
# a ---- b.2 ---- d.2
#
# b.1 ---- c.1
#
# If we downgrade module d to version 1, we must downgrade b as well.
# If that downgrade selects b version 1, we will add a new dependency on module c.
cp go.mod go.mod.orig
go mod tidy
cmp go.mod.orig go.mod
go get -d example.com/d@v0.1.0
go list -m all
stdout '^example.com/b v0.1.0 '
stdout '^example.com/c v0.1.0 '
stdout '^example.com/d v0.1.0 '
-- go.mod --
module example.com/a
go 1.15
require example.com/b v0.2.0
replace (
example.com/b v0.1.0 => ./b1
example.com/b v0.2.0 => ./b2
example.com/c v0.1.0 => ./c
example.com/d v0.1.0 => ./d
example.com/d v0.2.0 => ./d
)
-- a.go --
package a
import _ "example.com/b"
-- b1/go.mod --
module example.com/b
go 1.15
require example.com/c v0.1.0
-- b1/b.go --
package b
import _ "example.com/c"
-- b2/go.mod --
module example.com/b
go 1.15
require example.com/d v0.2.0
-- b2/b.go --
package b
import _ "example.com/d"
-- c/go.mod --
module example.com/c
go 1.15
-- c/c.go --
package c
-- d/go.mod --
module example.com/d
go 1.15
-- d/d.go --
package d

View File

@ -0,0 +1,165 @@
# This test illustrates a case where an upgradedowngradeupgrade cycle can
# result in upgrades of otherwise-irrelevant dependencies.
#
# This case has no corresponding test in the mvs package, because it is an
# artifact that results from the composition of *multiple* MVS operations.
# The initial package import graph used in the test looks like:
#
# m ---- a
# | |
# +----- b
# | |
# +----- c
# |
# +----- d
#
# b version 2 adds its own import of package d.
#
# The module dependency graph initially looks like:
#
# m ---- a.1
# | |
# +----- b.1
# | |
# +----- c.1
# |
# +----- d.1
#
# b.2 ---- c.2
# |
# +------ d.2
# |
# +------ e.1
#
# If we upgrade module b to version 2, we will upgrade c and d and add a new
# dependency on e. If b version 2 is disallowed because of any of those
# dependencies, the other dependencies should not be upgraded as a side-effect.
cp go.mod go.mod.orig
go mod tidy
cmp go.mod go.mod.orig
go list -m all
stdout '^example.com/a v0.1.0 '
stdout '^example.com/b v0.1.0 '
stdout '^example.com/c v0.1.0 '
stdout '^example.com/d v0.1.0 '
! stdout '^example.com/e '
# b is imported by a, so the -u flag would normally upgrade it to v0.2.0.
# However, that would conflict with the explicit c@v0.1.0 constraint,
# so b must remain at v0.1.0.
#
# If we're not careful, we might temporarily add b@v0.2.0 and pull in its
# upgrades of module d and addition of module e, which are not relevant to
# b@v0.1.0 and should not be added to the main module's dependencies.
go get -u -d example.com/a@latest example.com/c@v0.1.0
go list -m all
stdout '^example.com/a v0.1.0 '
stdout '^example.com/b v0.1.0 '
stdout '^example.com/c v0.1.0 '
# BUG: d should remain at v0.1.0, because it is not transitively imported by a
# with b@v0.1.0. Today, it is spuriously upgraded to v0.2.0.
stdout '^example.com/d v0.2.0 '
# BUG: e should not be added, because it is not transitively imported by a
# with b@v0.1.0. Today, it is spuriously added.
stdout '^example.com/e v0.1.0 '
-- go.mod --
module example.com/m
go 1.16
require (
example.com/a v0.1.0
example.com/b v0.1.0
example.com/c v0.1.0
example.com/d v0.1.0
)
replace (
example.com/a v0.1.0 => ./a1
example.com/b v0.1.0 => ./b1
example.com/b v0.2.0 => ./b2
example.com/c v0.1.0 => ./c
example.com/c v0.2.0 => ./c
example.com/d v0.1.0 => ./d
example.com/d v0.2.0 => ./d
example.com/e v0.1.0 => ./e
)
-- m.go --
package m
import (
_ "example.com/a"
_ "example.com/b"
_ "example.com/c"
_ "example.com/d"
)
-- a1/go.mod --
module example.com/a
go 1.16
require example.com/b v0.1.0
-- a1/a.go --
package a
import _ "example.com/b"
-- b1/go.mod --
module example.com/b
go 1.16
require example.com/c v0.1.0
-- b1/b.go --
package b
import _ "example.com/c"
-- b2/go.mod --
module example.com/b
go 1.16
require (
example.com/c v0.2.0
example.com/d v0.2.0
example.com/e v0.1.0
)
-- b2/b.go --
package b
import (
"example.com/c"
"example.com/d"
"example.com/e"
)
-- c/go.mod --
module example.com/c
go 1.16
-- c/c.go --
package c
-- d/go.mod --
module example.com/d
go 1.16
-- d/d.go --
package d
-- e/go.mod --
module example.com/e
go 1.16
-- e/e.go --
package e

View File

@ -0,0 +1,101 @@
# This test illustrates a case where downgrading one module may upgrade another.
# Compare to the downcross1 test case in cmd/go/internal/mvs/mvs_test.go.
# The package import graph used in this test looks like:
#
# a ---- b
# \ \
# \ \
# ----- c ---- d
#
# The module dependency graph originally looks like:
#
# a ---- b.2
# \ \
# \ \
# ----- c.1 ---- d.2
#
# b.1 ---- c.2
#
# If we downgrade module d to version 1, we must downgrade b as well.
# If that downgrade selects b version 1, we will upgrade module c to version 2.
# So 'go get d@1' should instead downgrade both b and c to "none".
cp go.mod go.mod.orig
go mod tidy
cmp go.mod.orig go.mod
go get -d example.com/d@v0.1.0
go list -m all
! stdout '^example.com/b '
! stdout '^example.com/c '
stdout '^example.com/d v0.1.0 '
-- go.mod --
module example.com/a
go 1.15
require (
example.com/b v0.2.0
example.com/c v0.1.0
)
replace (
example.com/b v0.1.0 => ./b1
example.com/b v0.2.0 => ./b2
example.com/c v0.1.0 => ./c1
example.com/c v0.2.0 => ./c2
example.com/d v0.1.0 => ./d
example.com/d v0.2.0 => ./d
)
-- a.go --
package a
import (
_ "example.com/b"
_ "example.com/c"
)
-- b1/go.mod --
module example.com/b
go 1.15
require example.com/c v0.2.0
-- b1/b.go --
package b
import _ "example.com/c"
-- b2/go.mod --
module example.com/b
go 1.15
require example.com/c v0.1.0
-- b2/b.go --
package b
import _ "example.com/c"
-- c1/go.mod --
module example.com/c
go 1.15
require example.com/d v0.2.0
-- c1/c.go --
package c
-- c2/go.mod --
module example.com/c
go 1.15
-- c2/c.go --
package c
-- d/go.mod --
module example.com/d
go 1.15

View File

@ -74,8 +74,7 @@ go get: example.com/badchain/c@v1.0.0 updating to
module declares its path as: badchain.example.com/c module declares its path as: badchain.example.com/c
but was required as: example.com/badchain/c but was required as: example.com/badchain/c
-- update-a-expected -- -- update-a-expected --
go get: example.com/badchain/a@v1.0.0 updating to go get: example.com/badchain/a@v1.1.0 requires
example.com/badchain/a@v1.1.0 requires
example.com/badchain/b@v1.1.0 requires example.com/badchain/b@v1.1.0 requires
example.com/badchain/c@v1.1.0: parsing go.mod: example.com/badchain/c@v1.1.0: parsing go.mod:
module declares its path as: badchain.example.com/c module declares its path as: badchain.example.com/c

View File

@ -449,7 +449,7 @@ TEXT callRet<>(SB), NOSPLIT, $40-0
MOV A1, 16(X2) MOV A1, 16(X2)
MOV A3, 24(X2) MOV A3, 24(X2)
MOV A2, 32(X2) MOV A2, 32(X2)
MOV $0, 40(X2) MOV ZERO, 40(X2)
CALL runtime·reflectcallmove(SB) CALL runtime·reflectcallmove(SB)
RET RET

View File

@ -32,7 +32,7 @@ typedef struct {
#define SET_RETVAL(fn) \ #define SET_RETVAL(fn) \
uintptr_t ret = (uintptr_t) fn ; \ uintptr_t ret = (uintptr_t) fn ; \
if (ret == -1) { \ if (ret == (uintptr_t) -1) { \
x->retval = (uintptr_t) errno; \ x->retval = (uintptr_t) errno; \
} else \ } else \
x->retval = ret x->retval = ret