Skip to content

Commit

Permalink
cmd/go: forbid use of one module with two different paths
Browse files Browse the repository at this point in the history
If a single module is imported via two different paths (e.g., as itself and as a
replacement for something else), some users may be surprised if the two paths
do not share the same package-level state. Others may be surprised if the two
paths do share state.

Punt on the question for now by rejecting that condition explicitly.

Fixes #26607.

Change-Id: I15c3889f61f8dd4ba5e5c48ca33ad63aeecac04e
Reviewed-on: https://go-review.googlesource.com/126156
Run-TryBot: Bryan C. Mills <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
Reviewed-by: Russ Cox <[email protected]>
  • Loading branch information
Bryan C. Mills authored and rsc committed Jul 31, 2018
1 parent 682faae commit 68170aa
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/cmd/go/internal/modload/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,25 @@ func ImportPaths(args []string) []string {
}
return roots
})

// A given module path may be used as itself or as a replacement for another
// module, but not both at the same time. Otherwise, the aliasing behavior is
// too subtle (see https://golang.org/issue/26607), and we don't want to
// commit to a specific behavior at this point.
firstPath := make(map[module.Version]string, len(buildList))
for _, mod := range buildList {
src := mod
if rep := Replacement(mod); rep.Path != "" {
src = rep
}
if prev, ok := firstPath[src]; !ok {
firstPath[src] = mod.Path
} else if prev != mod.Path {
base.Errorf("go: %s@%s used for two different module paths (%s and %s)", mod.Path, mod.Version, prev, mod.Path)
}
}
base.ExitIfErrors()

WriteGoMod()

// Process paths to produce final paths list.
Expand Down
89 changes: 89 additions & 0 deletions src/cmd/go/testdata/script/mod_replace.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
env GO111MODULE=on

go build -o a1.exe .
exec ./a1.exe
stdout 'Don''t communicate by sharing memory'

# Modules can be replaced by local packages.
go mod -replace=rsc.io/quote/v3=./local/rsc.io/quote/v3
go build -o a2.exe .
exec ./a2.exe
stdout 'Concurrency is not parallelism.'

# The module path of the replacement doesn't need to match.
# (For example, it could be a long-running fork with its own import path.)
go mod -replace=rsc.io/quote/v3=./local/not-rsc.io/quote/v3
go build -o a3.exe .
exec ./a3.exe
stdout 'Clear is better than clever.'

# However, the same module can't be used as two different paths.
go mod -dropreplace=rsc.io/quote/v3
go mod -replace=not-rsc.io/quote/[email protected]=rsc.io/quote/[email protected]
go mod -require=not-rsc.io/quote/[email protected]
! go build -o a4.exe .


-- go.mod --
module quoter

require rsc.io/quote/v3 v3.0.0

-- main.go --
package main

import (
"fmt"
"rsc.io/quote/v3"
)

func main() {
fmt.Println(quote.GoV3())
}

-- local/rsc.io/quote/v3/go.mod --
module rsc.io/quote/v3

require rsc.io/sampler v1.3.0

-- local/rsc.io/quote/v3/quote.go --
// Copyright 2018 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 quote collects pithy sayings.
package quote

import "rsc.io/sampler"

// Hello returns a greeting.
func HelloV3() string {
return sampler.Hello()
}

// Glass returns a useful phrase for world travelers.
func GlassV3() string {
// See http://www.oocities.org/nodotus/hbglass.html.
return "I can eat glass and it doesn't hurt me."
}

// Go returns a REPLACED Go proverb.
func GoV3() string {
return "Concurrency is not parallelism."
}

// Opt returns a optimization truth.
func OptV3() string {
// Wisdom from ken.
return "If a program is too slow, it must have a loop."
}

-- local/not-rsc.io/quote/v3/go.mod --
module not-rsc.io/quote/v3

-- local/not-rsc.io/quote/v3/quote.go --
package quote

func GoV3() string {
return "Clear is better than clever."
}

0 comments on commit 68170aa

Please sign in to comment.