@@ -426,12 +426,35 @@ func newImportState(logf func(string, ...any), caller *Caller, callee *gobCallee
426426 // For simplicity we ignore existing dot imports, so that a qualified
427427 // identifier (QI) in the callee is always represented by a QI in the caller,
428428 // allowing us to treat a QI like a selection on a package name.
429- is := & importState {
429+ ist := & importState {
430430 logf : logf ,
431431 caller : caller ,
432432 importMap : make (map [string ][]string ),
433433 }
434434
435+ // Build an index of used-once PkgNames.
436+ type pkgNameUse struct {
437+ count int
438+ id * ast.Ident // an arbitrary use
439+ }
440+ pkgNameUses := make (map [* types.PkgName ]pkgNameUse )
441+ for id , obj := range caller .Info .Uses {
442+ if pkgname , ok := obj .(* types.PkgName ); ok {
443+ u := pkgNameUses [pkgname ]
444+ u .id = id
445+ u .count ++
446+ pkgNameUses [pkgname ] = u
447+ }
448+ }
449+ // soleUse returns the ident that refers to pkgname, if there is exactly one.
450+ soleUse := func (pkgname * types.PkgName ) * ast.Ident {
451+ u := pkgNameUses [pkgname ]
452+ if u .count == 1 {
453+ return u .id
454+ }
455+ return nil
456+ }
457+
435458 for _ , imp := range caller .File .Imports {
436459 if pkgName , ok := importedPkgName (caller .Info , imp ); ok &&
437460 pkgName .Name () != "." &&
@@ -450,7 +473,7 @@ func newImportState(logf func(string, ...any), caller *Caller, callee *gobCallee
450473 // need this import. Doing so eagerly simplifies the resulting logic.
451474 needed := true
452475 sel , ok := ast .Unparen (caller .Call .Fun ).(* ast.SelectorExpr )
453- if ok && soleUse (caller . Info , pkgName ) == sel .X {
476+ if ok && soleUse (pkgName ) == sel .X {
454477 needed = false // no longer needed by caller
455478 // Check to see if any of the inlined free objects need this package.
456479 for _ , obj := range callee .FreeObjs {
@@ -465,13 +488,13 @@ func newImportState(logf func(string, ...any), caller *Caller, callee *gobCallee
465488 // return value holds these.
466489 if needed {
467490 path := pkgName .Imported ().Path ()
468- is .importMap [path ] = append (is .importMap [path ], pkgName .Name ())
491+ ist .importMap [path ] = append (ist .importMap [path ], pkgName .Name ())
469492 } else {
470- is .oldImports = append (is .oldImports , oldImport {pkgName : pkgName , spec : imp })
493+ ist .oldImports = append (ist .oldImports , oldImport {pkgName : pkgName , spec : imp })
471494 }
472495 }
473496 }
474- return is
497+ return ist
475498}
476499
477500// importName finds an existing import name to use in a particular shadowing
@@ -3736,18 +3759,4 @@ func hasNonTrivialReturn(returnInfo [][]returnOperandFlags) bool {
37363759 return false
37373760}
37383761
3739- // soleUse returns the ident that refers to obj, if there is exactly one.
3740- func soleUse (info * types.Info , obj types.Object ) (sole * ast.Ident ) {
3741- // This is not efficient, but it is called infrequently.
3742- for id , obj2 := range info .Uses {
3743- if obj2 == obj {
3744- if sole != nil {
3745- return nil // not unique
3746- }
3747- sole = id
3748- }
3749- }
3750- return sole
3751- }
3752-
37533762type unit struct {} // for representing sets as maps
0 commit comments