@@ -318,16 +318,16 @@ func (p *Package) copyBuild(pp *build.Package) {
318
318
319
319
// A PackageError describes an error loading information about a package.
320
320
type PackageError struct {
321
- ImportStack []string // shortest path from package named on command line to this one
322
- Pos string // position of error
323
- Err error // the error itself
324
- IsImportCycle bool // the error is an import cycle
325
- Hard bool // whether the error is soft or hard; soft errors are ignored in some places
321
+ ImportStack []string // shortest path from package named on command line to this one
322
+ Pos string // position of error
323
+ Err error // the error itself
324
+ IsImportCycle bool // the error is an import cycle
325
+ Hard bool // whether the error is soft or hard; soft errors are ignored in some places
326
+ alwaysPrintStack bool // whether to always print the ImportStack
326
327
}
327
328
328
329
func (p * PackageError ) Error () string {
329
- // Import cycles deserve special treatment.
330
- if p .Pos != "" && ! p .IsImportCycle {
330
+ if p .Pos != "" && (len (p .ImportStack ) == 0 || ! p .alwaysPrintStack ) {
331
331
// Omit import stack. The full path to the file where the error
332
332
// is the most important thing.
333
333
return p .Pos + ": " + p .Err .Error ()
@@ -339,15 +339,14 @@ func (p *PackageError) Error() string {
339
339
// last path on the stack, we don't omit the path. An error like
340
340
// "package A imports B: error loading C caused by B" would not be clearer
341
341
// if "imports B" were omitted.
342
- stack := p .ImportStack
343
- var ierr ImportPathError
344
- if len (stack ) > 0 && errors .As (p .Err , & ierr ) && ierr .ImportPath () == stack [len (stack )- 1 ] {
345
- stack = stack [:len (stack )- 1 ]
346
- }
347
- if len (stack ) == 0 {
342
+ if len (p .ImportStack ) == 0 {
348
343
return p .Err .Error ()
349
344
}
350
- return "package " + strings .Join (stack , "\n \t imports " ) + ": " + p .Err .Error ()
345
+ var optpos string
346
+ if p .Pos != "" {
347
+ optpos = "\n \t " + p .Pos
348
+ }
349
+ return "package " + strings .Join (p .ImportStack , "\n \t imports " ) + optpos + ": " + p .Err .Error ()
351
350
}
352
351
353
352
func (p * PackageError ) Unwrap () error { return p .Err }
@@ -549,9 +548,6 @@ func loadImport(pre *preload, path, srcDir string, parent *Package, stk *ImportS
549
548
panic ("LoadImport called with empty package path" )
550
549
}
551
550
552
- stk .Push (path )
553
- defer stk .Pop ()
554
-
555
551
var parentPath , parentRoot string
556
552
parentIsStd := false
557
553
if parent != nil {
@@ -564,6 +560,11 @@ func loadImport(pre *preload, path, srcDir string, parent *Package, stk *ImportS
564
560
pre .preloadImports (bp .Imports , bp )
565
561
}
566
562
if bp == nil {
563
+ if importErr , ok := err .(ImportPathError ); ! ok || importErr .ImportPath () != path {
564
+ // Only add path to the error's import stack if it's not already present on the error.
565
+ stk .Push (path )
566
+ defer stk .Pop ()
567
+ }
567
568
return & Package {
568
569
PackagePublic : PackagePublic {
569
570
ImportPath : path ,
@@ -578,7 +579,9 @@ func loadImport(pre *preload, path, srcDir string, parent *Package, stk *ImportS
578
579
importPath := bp .ImportPath
579
580
p := packageCache [importPath ]
580
581
if p != nil {
582
+ stk .Push (path )
581
583
p = reusePackage (p , stk )
584
+ stk .Pop ()
582
585
} else {
583
586
p = new (Package )
584
587
p .Internal .Local = build .IsLocalImport (path )
@@ -588,8 +591,11 @@ func loadImport(pre *preload, path, srcDir string, parent *Package, stk *ImportS
588
591
// Load package.
589
592
// loadPackageData may return bp != nil even if an error occurs,
590
593
// in order to return partial information.
591
- p .load (stk , bp , err )
592
- if p .Error != nil && p .Error .Pos == "" {
594
+ p .load (path , stk , bp , err )
595
+ // Add position information unless this is a NoGoError or an ImportCycle error.
596
+ // Import cycles deserve special treatment.
597
+ var g * build.NoGoError
598
+ if p .Error != nil && p .Error .Pos == "" && ! errors .As (err , & g ) && ! p .Error .IsImportCycle {
593
599
p = setErrorPos (p , importPos )
594
600
}
595
601
@@ -608,7 +614,7 @@ func loadImport(pre *preload, path, srcDir string, parent *Package, stk *ImportS
608
614
return setErrorPos (perr , importPos )
609
615
}
610
616
if mode & ResolveImport != 0 {
611
- if perr := disallowVendor (srcDir , path , p , stk ); perr != p {
617
+ if perr := disallowVendor (srcDir , path , parentPath , p , stk ); perr != p {
612
618
return setErrorPos (perr , importPos )
613
619
}
614
620
}
@@ -1246,7 +1252,7 @@ func disallowInternal(srcDir string, importer *Package, importerPath string, p *
1246
1252
// as if it were generated into the testing directory tree
1247
1253
// (it's actually in a temporary directory outside any Go tree).
1248
1254
// This cleans up a former kludge in passing functionality to the testing package.
1249
- if strings . HasPrefix (p .ImportPath , "testing/internal" ) && len ( * stk ) >= 2 && ( * stk )[ len ( * stk ) - 2 ] == "testmain" {
1255
+ if str . HasPathPrefix (p .ImportPath , "testing/internal" ) && importerPath == "testmain" {
1250
1256
return p
1251
1257
}
1252
1258
@@ -1262,11 +1268,10 @@ func disallowInternal(srcDir string, importer *Package, importerPath string, p *
1262
1268
return p
1263
1269
}
1264
1270
1265
- // The stack includes p.ImportPath.
1266
- // If that's the only thing on the stack, we started
1271
+ // importerPath is empty: we started
1267
1272
// with a name given on the command line, not an
1268
1273
// import. Anything listed on the command line is fine.
1269
- if len ( * stk ) == 1 {
1274
+ if importerPath == "" {
1270
1275
return p
1271
1276
}
1272
1277
@@ -1315,8 +1320,9 @@ func disallowInternal(srcDir string, importer *Package, importerPath string, p *
1315
1320
// Internal is present, and srcDir is outside parent's tree. Not allowed.
1316
1321
perr := * p
1317
1322
perr .Error = & PackageError {
1318
- ImportStack : stk .Copy (),
1319
- Err : ImportErrorf (p .ImportPath , "use of internal package " + p .ImportPath + " not allowed" ),
1323
+ alwaysPrintStack : true ,
1324
+ ImportStack : stk .Copy (),
1325
+ Err : ImportErrorf (p .ImportPath , "use of internal package " + p .ImportPath + " not allowed" ),
1320
1326
}
1321
1327
perr .Incomplete = true
1322
1328
return & perr
@@ -1344,16 +1350,15 @@ func findInternal(path string) (index int, ok bool) {
1344
1350
// disallowVendor checks that srcDir is allowed to import p as path.
1345
1351
// If the import is allowed, disallowVendor returns the original package p.
1346
1352
// If not, it returns a new package containing just an appropriate error.
1347
- func disallowVendor (srcDir string , path string , p * Package , stk * ImportStack ) * Package {
1348
- // The stack includes p.ImportPath.
1349
- // If that's the only thing on the stack, we started
1353
+ func disallowVendor (srcDir string , path string , importerPath string , p * Package , stk * ImportStack ) * Package {
1354
+ // If the importerPath is empty, we started
1350
1355
// with a name given on the command line, not an
1351
1356
// import. Anything listed on the command line is fine.
1352
- if len ( * stk ) == 1 {
1357
+ if importerPath == "" {
1353
1358
return p
1354
1359
}
1355
1360
1356
- if perr := disallowVendorVisibility (srcDir , p , stk ); perr != p {
1361
+ if perr := disallowVendorVisibility (srcDir , p , importerPath , stk ); perr != p {
1357
1362
return perr
1358
1363
}
1359
1364
@@ -1376,12 +1381,12 @@ func disallowVendor(srcDir string, path string, p *Package, stk *ImportStack) *P
1376
1381
// is not subject to the rules, only subdirectories of vendor.
1377
1382
// This allows people to have packages and commands named vendor,
1378
1383
// for maximal compatibility with existing source trees.
1379
- func disallowVendorVisibility (srcDir string , p * Package , stk * ImportStack ) * Package {
1380
- // The stack includes p.ImportPath.
1381
- // If that 's the only thing on the stack, we started
1384
+ func disallowVendorVisibility (srcDir string , p * Package , importerPath string , stk * ImportStack ) * Package {
1385
+ // The stack does not include p.ImportPath.
1386
+ // If there 's nothing on the stack, we started
1382
1387
// with a name given on the command line, not an
1383
1388
// import. Anything listed on the command line is fine.
1384
- if len ( * stk ) == 1 {
1389
+ if importerPath == "" {
1385
1390
return p
1386
1391
}
1387
1392
@@ -1525,7 +1530,8 @@ func (p *Package) DefaultExecName() string {
1525
1530
1526
1531
// load populates p using information from bp, err, which should
1527
1532
// be the result of calling build.Context.Import.
1528
- func (p * Package ) load (stk * ImportStack , bp * build.Package , err error ) {
1533
+ // stk contains the import stack, not including path itself.
1534
+ func (p * Package ) load (path string , stk * ImportStack , bp * build.Package , err error ) {
1529
1535
p .copyBuild (bp )
1530
1536
1531
1537
// The localPrefix is the path we interpret ./ imports relative to.
@@ -1548,7 +1554,16 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
1548
1554
1549
1555
if err != nil {
1550
1556
p .Incomplete = true
1557
+ // Report path in error stack unless err is an ImportPathError with path already set.
1558
+ pushed := false
1559
+ if e , ok := err .(ImportPathError ); ! ok || e .ImportPath () != path {
1560
+ stk .Push (path )
1561
+ pushed = true // Remember to pop after setError.
1562
+ }
1551
1563
setError (base .ExpandScanner (p .rewordError (err )))
1564
+ if pushed {
1565
+ stk .Pop ()
1566
+ }
1552
1567
if _ , isScanErr := err .(scanner.ErrorList ); ! isScanErr {
1553
1568
return
1554
1569
}
@@ -1675,6 +1690,23 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
1675
1690
}
1676
1691
}
1677
1692
1693
+ // Check for case-insensitive collisions of import paths.
1694
+ fold := str .ToFold (p .ImportPath )
1695
+ if other := foldPath [fold ]; other == "" {
1696
+ foldPath [fold ] = p .ImportPath
1697
+ } else if other != p .ImportPath {
1698
+ setError (ImportErrorf (p .ImportPath , "case-insensitive import collision: %q and %q" , p .ImportPath , other ))
1699
+ return
1700
+ }
1701
+
1702
+ if ! SafeArg (p .ImportPath ) {
1703
+ setError (ImportErrorf (p .ImportPath , "invalid import path %q" , p .ImportPath ))
1704
+ return
1705
+ }
1706
+
1707
+ stk .Push (path )
1708
+ defer stk .Pop ()
1709
+
1678
1710
// Check for case-insensitive collision of input files.
1679
1711
// To avoid problems on case-insensitive files, we reject any package
1680
1712
// where two different input files have equal names under a case-insensitive
@@ -1703,10 +1735,6 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
1703
1735
setError (fmt .Errorf ("invalid input directory name %q" , name ))
1704
1736
return
1705
1737
}
1706
- if ! SafeArg (p .ImportPath ) {
1707
- setError (ImportErrorf (p .ImportPath , "invalid import path %q" , p .ImportPath ))
1708
- return
1709
- }
1710
1738
1711
1739
// Build list of imported packages and full dependency list.
1712
1740
imports := make ([]* Package , 0 , len (p .Imports ))
@@ -1770,15 +1798,6 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
1770
1798
return
1771
1799
}
1772
1800
1773
- // Check for case-insensitive collisions of import paths.
1774
- fold := str .ToFold (p .ImportPath )
1775
- if other := foldPath [fold ]; other == "" {
1776
- foldPath [fold ] = p .ImportPath
1777
- } else if other != p .ImportPath {
1778
- setError (ImportErrorf (p .ImportPath , "case-insensitive import collision: %q and %q" , p .ImportPath , other ))
1779
- return
1780
- }
1781
-
1782
1801
if cfg .ModulesEnabled && p .Error == nil {
1783
1802
mainPath := p .ImportPath
1784
1803
if p .Internal .CmdlineFiles {
@@ -2266,9 +2285,7 @@ func GoFilesPackage(gofiles []string) *Package {
2266
2285
pkg := new (Package )
2267
2286
pkg .Internal .Local = true
2268
2287
pkg .Internal .CmdlineFiles = true
2269
- stk .Push ("main" )
2270
- pkg .load (& stk , bp , err )
2271
- stk .Pop ()
2288
+ pkg .load ("command-line-arguments" , & stk , bp , err )
2272
2289
pkg .Internal .LocalPrefix = dirToImportPath (dir )
2273
2290
pkg .ImportPath = "command-line-arguments"
2274
2291
pkg .Target = ""
0 commit comments