modfile: improve error message for replace with '@' in path

Replacement module must match format 'path version', not 'path@version'. In this case, return a more explicit error message.

Fixes golang/go#35041.

Change-Id: I4d1437fc7499abca4af426afb535bfdd0f5b254e
Reviewed-on: https://go-review.googlesource.com/c/mod/+/408014
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
diff --git a/modfile/rule.go b/modfile/rule.go
index ed2f31a..6bcde8f 100644
--- a/modfile/rule.go
+++ b/modfile/rule.go
@@ -513,6 +513,9 @@
 	nv := ""
 	if len(args) == arrow+2 {
 		if !IsDirectoryPath(ns) {
+			if strings.Contains(ns, "@") {
+				return nil, errorf("replacement module must match format 'path version', not 'path@version'")
+			}
 			return nil, errorf("replacement module without version must be directory path (rooted or starting with ./ or ../)")
 		}
 		if filepath.Separator == '/' && strings.Contains(ns, `\`) {
diff --git a/modfile/rule_test.go b/modfile/rule_test.go
index 21cea13..26879fb 100644
--- a/modfile/rule_test.go
+++ b/modfile/rule_test.go
@@ -1331,6 +1331,18 @@
 		fix:  fixV,
 	},
 	{
+		desc:    `replace_version_in_path`,
+		in:      `replace example.com/m@v1.0.0 => example.com/m@v1.1.0`,
+		wantErr: `replacement module must match format 'path version', not 'path@version'`,
+		fix:     fixV,
+	},
+	{
+		desc:    `replace_version_in_later_path`,
+		in:      `replace example.com/m => example.com/m@v1.1.0`,
+		wantErr: `replacement module must match format 'path version', not 'path@version'`,
+		fix:     fixV,
+	},
+	{
 		desc: `exclude`,
 		in:   `exclude example.com/m 1.0.0`,
 		want: `exclude example.com/m v1.0.0`,