go/loader: don't treat unsafe specially wrt vendoring

The loader treats GOROOT's "unsafe" package specially,
with no source files and a Package of types.Unsafe.

Tested on Go 1.4.1, 1.5, and ~1.6 (tip).

Fixes issue #13882

Change-Id: I86c4e394665d86a50ec3852d6d702f0e9c5d2276
Reviewed-on: https://go-review.googlesource.com/18457
Reviewed-by: Robert Griesemer <gri@golang.org>
diff --git a/go/loader/example14_test.go b/go/loader/example14_test.go
index 76d5ea6..67dbefa 100644
--- a/go/loader/example14_test.go
+++ b/go/loader/example14_test.go
@@ -83,7 +83,7 @@
 	// created: []
 	// imported: [errors runtime unicode/utf8]
 	// initial: [errors runtime unicode/utf8]
-	// all: [errors runtime unicode/utf8]
+	// all: [errors runtime unicode/utf8 unsafe]
 }
 
 // This example creates and type-checks a single package (without tests)
@@ -139,7 +139,7 @@
 	// created: [hello]
 	// imported: []
 	// initial: [hello]
-	// all: [errors fmt hello io math os reflect runtime strconv sync sync/atomic syscall time unicode/utf8]
+	// all: [errors fmt hello io math os reflect runtime strconv sync sync/atomic syscall time unicode/utf8 unsafe]
 	// strconv.Files: [atob.go atof.go atoi.go decimal.go extfloat.go ftoa.go isprint.go itoa.go quote.go]
 }
 
@@ -167,7 +167,7 @@
 	// created: [strconv_test]
 	// imported: [errors strconv unicode/utf8]
 	// initial: [errors strconv strconv_test unicode/utf8]
-	// all: [bufio bytes errors flag fmt io math math/rand os reflect runtime runtime/pprof sort strconv strconv_test strings sync sync/atomic syscall testing text/tabwriter time unicode unicode/utf8]
+	// all: [bufio bytes errors flag fmt io math math/rand os reflect runtime runtime/pprof sort strconv strconv_test strings sync sync/atomic syscall testing text/tabwriter time unicode unicode/utf8 unsafe]
 	// strconv.Files: [atob.go atof.go atoi.go decimal.go extfloat.go ftoa.go isprint.go itoa.go quote.go internal_test.go]
 	// strconv_test.Files: [atob_test.go atof_test.go atoi_test.go decimal_test.go fp_test.go ftoa_test.go itoa_test.go quote_example_test.go quote_test.go strconv_test.go]
 }
diff --git a/go/loader/example15_test.go b/go/loader/example15_test.go
index 63c57e9..5cf365b 100644
--- a/go/loader/example15_test.go
+++ b/go/loader/example15_test.go
@@ -87,7 +87,7 @@
 	// created: []
 	// imported: [errors runtime unicode/utf8]
 	// initial: [errors runtime unicode/utf8]
-	// all: [errors runtime unicode/utf8]
+	// all: [errors runtime unicode/utf8 unsafe]
 }
 
 // This example creates and type-checks a single package (without tests)
@@ -143,7 +143,7 @@
 	// created: [hello]
 	// imported: []
 	// initial: [hello]
-	// all: [errors fmt hello io math os reflect runtime strconv sync sync/atomic syscall time unicode/utf8]
+	// all: [errors fmt hello io math os reflect runtime strconv sync sync/atomic syscall time unicode/utf8 unsafe]
 	// strconv.Files: [atob.go atof.go atoi.go decimal.go doc.go extfloat.go ftoa.go isprint.go itoa.go quote.go]
 }
 
@@ -171,7 +171,7 @@
 	// created: [strconv_test]
 	// imported: [errors strconv unicode/utf8]
 	// initial: [errors strconv strconv_test unicode/utf8]
-	// all: [bufio bytes errors flag fmt io log math math/rand os reflect runtime runtime/pprof runtime/trace sort strconv strconv_test strings sync sync/atomic syscall testing text/tabwriter time unicode unicode/utf8]
+	// all: [bufio bytes errors flag fmt io log math math/rand os reflect runtime runtime/pprof runtime/trace sort strconv strconv_test strings sync sync/atomic syscall testing text/tabwriter time unicode unicode/utf8 unsafe]
 	// strconv.Files: [atob.go atof.go atoi.go decimal.go doc.go extfloat.go ftoa.go isprint.go itoa.go quote.go internal_test.go]
 	// strconv_test.Files: [atob_test.go atof_test.go atoi_test.go decimal_test.go example_test.go fp_test.go ftoa_test.go itoa_test.go quote_test.go strconv_test.go]
 }
diff --git a/go/loader/example_test.go b/go/loader/example_test.go
index 9319afb..66ddb92 100644
--- a/go/loader/example_test.go
+++ b/go/loader/example_test.go
@@ -87,7 +87,7 @@
 	// created: []
 	// imported: [errors runtime unicode/utf8]
 	// initial: [errors runtime unicode/utf8]
-	// all: [errors runtime runtime/internal/atomic runtime/internal/sys unicode/utf8]
+	// all: [errors runtime runtime/internal/atomic runtime/internal/sys unicode/utf8 unsafe]
 }
 
 // This example creates and type-checks a single package (without tests)
@@ -143,7 +143,7 @@
 	// created: [hello]
 	// imported: []
 	// initial: [hello]
-	// all: [errors fmt hello internal/race io math os reflect runtime runtime/internal/atomic runtime/internal/sys strconv sync sync/atomic syscall time unicode/utf8]
+	// all: [errors fmt hello internal/race io math os reflect runtime runtime/internal/atomic runtime/internal/sys strconv sync sync/atomic syscall time unicode/utf8 unsafe]
 	// strconv.Files: [atob.go atof.go atoi.go decimal.go doc.go extfloat.go ftoa.go isprint.go itoa.go quote.go]
 }
 
@@ -171,7 +171,7 @@
 	// created: [strconv_test]
 	// imported: [errors strconv unicode/utf8]
 	// initial: [errors strconv strconv_test unicode/utf8]
-	// all: [bufio bytes errors flag fmt internal/race io log math math/rand os reflect runtime runtime/debug runtime/internal/atomic runtime/internal/sys runtime/pprof runtime/trace sort strconv strconv_test strings sync sync/atomic syscall testing text/tabwriter time unicode unicode/utf8]
+	// all: [bufio bytes errors flag fmt internal/race io log math math/rand os reflect runtime runtime/debug runtime/internal/atomic runtime/internal/sys runtime/pprof runtime/trace sort strconv strconv_test strings sync sync/atomic syscall testing text/tabwriter time unicode unicode/utf8 unsafe]
 	// strconv.Files: [atob.go atof.go atoi.go decimal.go doc.go extfloat.go ftoa.go isprint.go itoa.go quote.go internal_test.go]
 	// strconv_test.Files: [atob_test.go atof_test.go atoi_test.go decimal_test.go example_test.go fp_test.go ftoa_test.go itoa_test.go quote_test.go strconv_test.go]
 }
diff --git a/go/loader/loader.go b/go/loader/loader.go
index 6671352..19e2bbd 100644
--- a/go/loader/loader.go
+++ b/go/loader/loader.go
@@ -308,7 +308,7 @@
 func (conf *Config) Import(path string) { conf.addImport(path, false) }
 
 func (conf *Config) addImport(path string, tests bool) {
-	if path == "C" || path == "unsafe" {
+	if path == "C" {
 		return // ignore; not a real package
 	}
 	if conf.ImportPkgs == nil {
@@ -718,6 +718,9 @@
 //    'x': include external *_test.go source files. (XTestGoFiles)
 //
 func (conf *Config) parsePackageFiles(bp *build.Package, which rune) ([]*ast.File, []error) {
+	if bp.Goroot && bp.ImportPath == "unsafe" {
+		return nil, nil
+	}
 	var filenames []string
 	switch which {
 	case 'g':
@@ -756,11 +759,6 @@
 // Idempotent.
 //
 func (imp *importer) doImport(from *PackageInfo, to string) (*types.Package, error) {
-	// Package unsafe is handled specially, and has no PackageInfo.
-	// (Let's assume there is no "vendor/unsafe" package.)
-	if to == "unsafe" {
-		return types.Unsafe, nil
-	}
 	if to == "C" {
 		// This should be unreachable, but ad hoc packages are
 		// not currently subject to cgo preprocessing.
@@ -774,6 +772,12 @@
 		return nil, err
 	}
 
+	// The standard unsafe package is handled specially,
+	// and has no PackageInfo.
+	if bp.Goroot && bp.ImportPath == "unsafe" {
+		return types.Unsafe, nil
+	}
+
 	// Look for the package in the cache using its canonical path.
 	path := bp.ImportPath
 	imp.importedMu.Lock()
diff --git a/go/loader/loader14.go b/go/loader/loader14.go
index 836ab92..d3fb157 100644
--- a/go/loader/loader14.go
+++ b/go/loader/loader14.go
@@ -306,7 +306,7 @@
 func (conf *Config) Import(path string) { conf.addImport(path, false) }
 
 func (conf *Config) addImport(path string, tests bool) {
-	if path == "C" || path == "unsafe" {
+	if path == "C" {
 		return // ignore; not a real package
 	}
 	if conf.ImportPkgs == nil {
@@ -714,6 +714,9 @@
 //    'x': include external *_test.go source files. (XTestGoFiles)
 //
 func (conf *Config) parsePackageFiles(bp *build.Package, which rune) ([]*ast.File, []error) {
+	if bp.Goroot && bp.ImportPath == "unsafe" {
+		return nil, nil
+	}
 	var filenames []string
 	switch which {
 	case 'g':
@@ -752,11 +755,6 @@
 // Idempotent.
 //
 func (imp *importer) doImport(from *PackageInfo, to string) (*types.Package, error) {
-	// Package unsafe is handled specially, and has no PackageInfo.
-	// (Let's assume there is no "vendor/unsafe" package.)
-	if to == "unsafe" {
-		return types.Unsafe, nil
-	}
 	if to == "C" {
 		// This should be unreachable, but ad hoc packages are
 		// not currently subject to cgo preprocessing.
@@ -770,6 +768,12 @@
 		return nil, err
 	}
 
+	// The standard unsafe package is handled specially,
+	// and has no PackageInfo.
+	if bp.Goroot && bp.ImportPath == "unsafe" {
+		return types.Unsafe, nil
+	}
+
 	// Look for the package in the cache using its canonical path.
 	path := bp.ImportPath
 	imp.importedMu.Lock()
diff --git a/go/loader/util.go b/go/loader/util.go
index 4e01462..7f38dd7 100644
--- a/go/loader/util.go
+++ b/go/loader/util.go
@@ -103,8 +103,8 @@
 					if err != nil {
 						continue // quietly ignore the error
 					}
-					if path == "C" || path == "unsafe" {
-						continue // skip pseudo packages
+					if path == "C" {
+						continue // skip pseudopackage
 					}
 					imports[path] = true
 				}