@@ -128,19 +128,18 @@ type Config struct {
128
128
129
129
// TypeChecker provides additional configuration for type-checking syntax trees.
130
130
//
131
- // The TypeCheck loader does not use the TypeChecker configuration
132
- // for packages that have their type information provided by the
133
- // underlying build system .
131
+ // It is used for all packages in LoadAllSyntax mode,
132
+ // and for the packages matching the patterns, but not their dependencies,
133
+ // in LoadSyntax mode .
134
134
//
135
135
// The TypeChecker.Error function is ignored:
136
136
// errors are reported using the Error function defined above.
137
137
//
138
138
// The TypeChecker.Importer function is ignored:
139
139
// the loader defines an appropriate importer.
140
140
//
141
- // The TypeChecker.Sizes are only used by the WholeProgram loader.
142
- // The TypeCheck loader uses the same sizes as the main build.
143
- // TODO(rsc): At least, it should. Derive these from runtime?
141
+ // TODO(rsc): TypeChecker.Sizes should use the same sizes as the main build.
142
+ // Derive them from the runtime?
144
143
TypeChecker types.Config
145
144
}
146
145
@@ -232,7 +231,7 @@ type loaderPackage struct {
232
231
importErrors map [string ]error // maps each bad import to its error
233
232
loadOnce sync.Once
234
233
color uint8 // for cycle detection
235
- mark , needsrc bool // used in TypeCheck mode only
234
+ mark , needsrc bool // used when Mode >= LoadTypes
236
235
}
237
236
238
237
func (lpkg * Package ) String () string { return lpkg .ID }
@@ -317,7 +316,8 @@ func (ld *loader) loadFrom(roots []string, list ...*raw.Package) ([]*Package, er
317
316
GoFiles : pkg .GoFiles ,
318
317
OtherFiles : pkg .OtherFiles ,
319
318
},
320
- needsrc : ld .Mode >= LoadAllSyntax || pkg .Export == "" ,
319
+ needsrc : ld .Mode >= LoadAllSyntax ||
320
+ (pkg .Export == "" && pkg .PkgPath != "unsafe" ),
321
321
}
322
322
ld .pkgs [lpkg .ID ] = lpkg
323
323
}
@@ -421,11 +421,10 @@ func (ld *loader) loadFrom(roots []string, list ...*raw.Package) ([]*Package, er
421
421
return result , nil
422
422
}
423
423
424
- // loadRecursive loads, parses, and type-checks the specified package and its
425
- // dependencies, recursively, in parallel, in topological order.
424
+ // loadRecursive loads the specified package and its dependencies,
425
+ // recursively, in parallel, in topological order.
426
426
// It is atomic and idempotent.
427
- // Precondition: ld.mode != Metadata.
428
- // In typeCheck mode, only needsrc packages are loaded.
427
+ // Precondition: ld.Mode >= LoadTypes.
429
428
func (ld * loader ) loadRecursive (lpkg * loaderPackage ) {
430
429
lpkg .loadOnce .Do (func () {
431
430
// Load the direct dependencies, in parallel.
@@ -444,11 +443,10 @@ func (ld *loader) loadRecursive(lpkg *loaderPackage) {
444
443
})
445
444
}
446
445
447
- // loadPackage loads, parses, and type-checks the
448
- // files of the specified package, if needed.
446
+ // loadPackage loads the specified package.
449
447
// It must be called only once per Package,
450
448
// after immediate dependencies are loaded.
451
- // Precondition: ld.mode != Metadata .
449
+ // Precondition: ld.Mode >= LoadTypes .
452
450
func (ld * loader ) loadPackage (lpkg * loaderPackage ) {
453
451
if lpkg .raw .PkgPath == "unsafe" {
454
452
// Fill in the blanks to avoid surprises.
@@ -459,8 +457,14 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
459
457
return
460
458
}
461
459
460
+ // Call NewPackage directly with explicit name.
461
+ // This avoids skew between golist and go/types when the files'
462
+ // package declarations are inconsistent.
463
+ lpkg .Types = types .NewPackage (lpkg .raw .PkgPath , lpkg .Name )
464
+
462
465
if ! lpkg .needsrc {
463
- return // not a source package
466
+ ld .loadFromExportData (lpkg )
467
+ return // not a source package, don't get syntax trees
464
468
}
465
469
466
470
hardErrors := false
@@ -482,11 +486,6 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
482
486
lpkg .Fset = ld .Fset
483
487
lpkg .Syntax = files
484
488
485
- // Call NewPackage directly with explicit name.
486
- // This avoids skew between golist and go/types when the files'
487
- // package declarations are inconsistent.
488
- lpkg .Types = types .NewPackage (lpkg .raw .PkgPath , lpkg .Name )
489
-
490
489
lpkg .TypesInfo = & types.Info {
491
490
Types : make (map [ast.Expr ]types.TypeAndValue ),
492
491
Defs : make (map [* ast.Ident ]types.Object ),
@@ -516,16 +515,9 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) {
516
515
return nil , fmt .Errorf ("no metadata for %s" , path )
517
516
}
518
517
519
- ld .exportMu .Lock ()
520
- defer ld .exportMu .Unlock ()
521
-
522
518
if ipkg .Types != nil && ipkg .Types .Complete () {
523
519
return ipkg .Types , nil
524
520
}
525
- imp := ld .pkgs [ipkg .ID ]
526
- if ! imp .needsrc {
527
- return ld .loadFromExportData (imp )
528
- }
529
521
log .Fatalf ("internal error: nil Pkg importing %q from %q" , path , lpkg )
530
522
panic ("unreachable" )
531
523
})
@@ -643,16 +635,8 @@ func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error
643
635
// Not all accesses to Package.Pkg need to be protected by exportMu:
644
636
// graph ordering ensures that direct dependencies of source
645
637
// packages are fully loaded before the importer reads their Pkg field.
646
- //
647
- // TODO(matloob): Ask adonovan if this is safe. Because of diamonds in the
648
- // dependency graph, it's possible that the same package is loaded in
649
- // two separate goroutines and there's a race in the write of the Package's
650
- // Types here and the read earlier checking if types is set before calling
651
- // this function.
652
- /*
653
- ld.exportMu.Lock()
654
- defer ld.exportMu.Unlock()
655
- */
638
+ ld .exportMu .Lock ()
639
+ defer ld .exportMu .Unlock ()
656
640
657
641
if tpkg := lpkg .Types ; tpkg != nil && tpkg .Complete () {
658
642
return tpkg , nil // cache hit
@@ -690,45 +674,28 @@ func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error
690
674
//
691
675
// So, we must build a PkgPath-keyed view of the global
692
676
// (conceptually ID-keyed) cache of packages and pass it to
693
- // gcexportdata, then copy back to the global cache any newly
694
- // created entries in the view map. The view must contain every
695
- // existing package that might possibly be mentioned by the
696
- // current package---its reflexive transitive closure.
697
- //
698
- // (Yes, reflexive: although loadRecursive processes source
699
- // packages in topological order, export data packages are
700
- // processed only lazily within Importer calls. In the graph
701
- // A->B->C, A->C where A is a source package and B and C are
702
- // export data packages, processing of the A->B and A->C import
703
- // edges may occur in either order, depending on the sequence
704
- // of imports within A. If B is processed first, and its export
705
- // data mentions C, an incomplete package for C will be created
706
- // before processing of C.)
707
- // We could do export data processing in topological order using
708
- // loadRecursive, but there's no parallelism to be gained.
677
+ // gcexportdata. The view must contain every existing
678
+ // package that might possibly be mentioned by the
679
+ // current package---its transitive closure.
709
680
//
710
681
// TODO(adonovan): it would be more simpler and more efficient
711
682
// if the export data machinery invoked a callback to
712
683
// get-or-create a package instead of a map.
713
684
//
714
685
view := make (map [string ]* types.Package ) // view seen by gcexportdata
715
686
seen := make (map [* loaderPackage ]bool ) // all visited packages
716
- var copyback []* loaderPackage // candidates for copying back to global cache
717
- var visit func (p * loaderPackage )
718
- visit = func (p * loaderPackage ) {
719
- if ! seen [p ] {
720
- seen [p ] = true
721
- if p .Types != nil {
722
- view [p .raw .PkgPath ] = p .Types
723
- } else {
724
- copyback = append (copyback , p )
725
- }
726
- for _ , p := range p .Imports {
727
- visit (ld .pkgs [p .ID ])
687
+ var visit func (pkgs map [string ]* Package )
688
+ visit = func (pkgs map [string ]* Package ) {
689
+ for _ , p := range pkgs {
690
+ lpkg := ld .pkgs [p .ID ]
691
+ if ! seen [lpkg ] {
692
+ seen [lpkg ] = true
693
+ view [lpkg .raw .PkgPath ] = lpkg .Types
694
+ visit (lpkg .Imports )
728
695
}
729
696
}
730
697
}
731
- visit (lpkg )
698
+ visit (lpkg . Imports )
732
699
733
700
// Parse the export data.
734
701
// (May create/modify packages in view.)
@@ -737,12 +704,6 @@ func (ld *loader) loadFromExportData(lpkg *loaderPackage) (*types.Package, error
737
704
return nil , fmt .Errorf ("reading %s: %v" , lpkg .raw .Export , err )
738
705
}
739
706
740
- // For each newly created types.Package in the view,
741
- // save it in the main graph.
742
- for _ , p := range copyback {
743
- p .Types = view [p .raw .PkgPath ] // may still be nil
744
- }
745
-
746
707
lpkg .Types = tpkg
747
708
lpkg .IllTyped = false
748
709
0 commit comments