cmd/go: diagnose misuse of path@version syntax

We should only see path@version arguments
in module mode, and then only for 'go get'.

Change-Id: I223a924b42bbd1710713c2202e5b4403fef7e18d
Reviewed-on: https://go-review.googlesource.com/122405
Reviewed-by: Bryan C. Mills <bcmills@google.com>
diff --git a/vendor/cmd/go/go_test.go b/vendor/cmd/go/go_test.go
index 555b457..d549b94 100644
--- a/vendor/cmd/go/go_test.go
+++ b/vendor/cmd/go/go_test.go
@@ -6232,12 +6232,12 @@
 	tg.tempFile("src/@x/x.go", "package x\n")
 	tg.setenv("GOPATH", tg.path("."))
 	tg.runFail("build", "@x")
-	tg.grepStderr("invalid input directory name \"@x\"", "did not reject @x directory")
+	tg.grepStderr("invalid input directory name \"@x\"|cannot use path@version syntax", "did not reject @x directory")
 
 	tg.tempFile("src/@x/y/y.go", "package y\n")
 	tg.setenv("GOPATH", tg.path("."))
 	tg.runFail("build", "@x/y")
-	tg.grepStderr("invalid import path \"@x/y\"", "did not reject @x/y import path")
+	tg.grepStderr("invalid import path \"@x/y\"|cannot use path@version syntax", "did not reject @x/y import path")
 
 	tg.tempFile("src/-x/x.go", "package x\n")
 	tg.setenv("GOPATH", tg.path("."))
diff --git a/vendor/cmd/go/internal/get/get.go b/vendor/cmd/go/internal/get/get.go
index 76ba238..36aa171 100644
--- a/vendor/cmd/go/internal/get/get.go
+++ b/vendor/cmd/go/internal/get/get.go
@@ -199,6 +199,12 @@
 // in the hope that we can figure out the repository from the
 // initial ...-free prefix.
 func downloadPaths(args []string) []string {
+	for _, arg := range args {
+		if strings.Contains(arg, "@") {
+			base.Fatalf("go: cannot use path@version syntax in GOPATH mode")
+		}
+	}
+
 	args = load.ImportPathsForGoGet(args)
 	var out []string
 	for _, a := range args {
diff --git a/vendor/cmd/go/internal/load/pkg.go b/vendor/cmd/go/internal/load/pkg.go
index 0e5e758..edc29ad 100644
--- a/vendor/cmd/go/internal/load/pkg.go
+++ b/vendor/cmd/go/internal/load/pkg.go
@@ -442,6 +442,24 @@
 		}
 	}
 
+	if strings.Contains(path, "@") {
+		var text string
+		if cfg.ModulesEnabled {
+			text = "can only use path@version syntax with 'go get'"
+		} else {
+			text = "cannot use path@version syntax in GOPATH mode"
+		}
+		return &Package{
+			PackagePublic: PackagePublic{
+				ImportPath: path,
+				Error: &PackageError{
+					ImportStack: stk.Copy(),
+					Err:         text,
+				},
+			},
+		}
+	}
+
 	// Determine canonical identifier for this package.
 	// For a local import the identifier is the pseudo-import path
 	// we create from the full directory to the package.
diff --git a/vendor/cmd/go/internal/modload/load.go b/vendor/cmd/go/internal/modload/load.go
index fe3f64d..703d576 100644
--- a/vendor/cmd/go/internal/modload/load.go
+++ b/vendor/cmd/go/internal/modload/load.go
@@ -533,6 +533,11 @@
 // It is also possible to return successfully with a zero module.Version,
 // for packages in the standard library or when using vendored code.
 func (ld *loader) findDir(path string) (dir string, mod module.Version, err error) {
+	if strings.Contains(path, "@") {
+		// Leave for error during load.
+		return
+	}
+
 	// Is the package in the standard library?
 	if search.IsStandardImportPath(path) {
 		if path == "C" || path == "unsafe" {
diff --git a/vendor/cmd/go/mod_test.go b/vendor/cmd/go/mod_test.go
index e723d4e..258066f 100644
--- a/vendor/cmd/go/mod_test.go
+++ b/vendor/cmd/go/mod_test.go
@@ -92,6 +92,25 @@
 	tg.grepStdout(`"GOMOD": ""`, "expected module mode disabled")
 }
 
+func TestModVersionsInGOPATHMode(t *testing.T) {
+	tg := testgo(t)
+	tg.setenv("GO111MODULE", "off") // GOPATH mode
+	defer tg.cleanup()
+	tg.makeTempdir()
+
+	tg.runFail("get", "rsc.io/quote@v1.5.1")
+	tg.grepStderr(`go: cannot use path@version syntax in GOPATH mode`, "expected path@version error")
+
+	tg.runFail("build", "rsc.io/quote@v1.5.1")
+	tg.grepStderr(`can't load package:.* cannot use path@version syntax in GOPATH mode`, "expected path@version error")
+
+	tg.setenv("GO111MODULE", "on") // GOPATH mode
+	tg.tempFile("x/go.mod", "module x")
+	tg.cd(tg.path("x"))
+	tg.runFail("build", "rsc.io/quote@v1.5.1")
+	tg.grepStderr(`can't load package:.* can only use path@version syntax with 'go get'`, "expected path@version error")
+}
+
 func TestModFindModuleRoot(t *testing.T) {
 	tg := testgo(t)
 	tg.setenv("GO111MODULE", "on")