}
 
 // Issue 4568.
-func TestSymlinksDoNotConfuseGoList(t *testing.T) {
+func TestSymlinksList(t *testing.T) {
        switch runtime.GOOS {
        case "plan9", "windows":
                t.Skipf("skipping symlink test on %s", runtime.GOOS)
        }
 }
 
+// Issue 14054.
+func TestSymlinksVendor(t *testing.T) {
+       switch runtime.GOOS {
+       case "plan9", "windows":
+               t.Skipf("skipping symlink test on %s", runtime.GOOS)
+       }
+
+       tg := testgo(t)
+       defer tg.cleanup()
+       tg.setenv("GO15VENDOREXPERIMENT", "1")
+       tg.tempDir("gopath/src/dir1/vendor/v")
+       tg.tempFile("gopath/src/dir1/p.go", "package main\nimport _ `v`\nfunc main(){}")
+       tg.tempFile("gopath/src/dir1/vendor/v/v.go", "package v")
+       tg.must(os.Symlink(tg.path("gopath/src/dir1"), tg.path("symdir1")))
+       tg.setenv("GOPATH", tg.path("gopath"))
+       tg.cd(tg.path("symdir1"))
+       tg.run("list", "-f", "{{.Root}}", ".")
+       if strings.TrimSpace(tg.getStdout()) != tg.path("gopath") {
+               t.Error("list confused by symlinks")
+       }
+
+       // All of these should succeed, not die in vendor-handling code.
+       tg.run("run", "p.go")
+       tg.run("build")
+       tg.run("install")
+}
+
+func TestSymlinksInternal(t *testing.T) {
+       switch runtime.GOOS {
+       case "plan9", "windows":
+               t.Skipf("skipping symlink test on %s", runtime.GOOS)
+       }
+
+       tg := testgo(t)
+       defer tg.cleanup()
+       tg.tempDir("gopath/src/dir1/internal/v")
+       tg.tempFile("gopath/src/dir1/p.go", "package main\nimport _ `dir1/internal/v`\nfunc main(){}")
+       tg.tempFile("gopath/src/dir1/internal/v/v.go", "package v")
+       tg.must(os.Symlink(tg.path("gopath/src/dir1"), tg.path("symdir1")))
+       tg.setenv("GOPATH", tg.path("gopath"))
+       tg.cd(tg.path("symdir1"))
+       tg.run("list", "-f", "{{.Root}}", ".")
+       if strings.TrimSpace(tg.getStdout()) != tg.path("gopath") {
+               t.Error("list confused by symlinks")
+       }
+
+       // All of these should succeed, not die in internal-handling code.
+       tg.run("run", "p.go")
+       tg.run("build")
+       tg.run("install")
+}
+
 // Issue 4515.
 func TestInstallWithTags(t *testing.T) {
        tg := testgo(t)
 
        if parent == nil || parent.Root == "" || !go15VendorExperiment {
                return path
        }
+
        dir := filepath.Clean(parent.Dir)
        root := filepath.Join(parent.Root, "src")
+       if !hasFilePathPrefix(dir, root) {
+               // Look for symlinks before reporting error.
+               dir = expandPath(dir)
+               root = expandPath(root)
+       }
        if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator {
                fatalf("invalid vendoredImportPath: dir=%q root=%q separator=%q", dir, root, string(filepath.Separator))
        }
+
        vpath := "vendor/" + path
        for i := len(dir); i >= len(root); i-- {
                if i < len(dir) && dir[i] != filepath.Separator {
                return p
        }
 
+       // Look for symlinks before reporting error.
+       srcDir = expandPath(srcDir)
+       parent = expandPath(parent)
+       if hasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
+               return p
+       }
+
        // Internal is present, and srcDir is outside parent's tree. Not allowed.
        perr := *p
        perr.Error = &PackageError{
                return p
        }
 
+       // Look for symlinks before reporting error.
+       srcDir = expandPath(srcDir)
+       parent = expandPath(parent)
+       if hasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
+               return p
+       }
+
        // Vendor is present, and srcDir is outside parent's tree. Not allowed.
        perr := *p
        perr.Error = &PackageError{