diff --git a/src/cmd/go.mod b/src/cmd/go.mod index e6431c0f20a..c72a250aeab 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -11,7 +11,7 @@ require ( golang.org/x/sys v0.36.0 golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 golang.org/x/term v0.34.0 - golang.org/x/tools v0.37.1-0.20250911182313-3adf0e96d87d + golang.org/x/tools v0.37.1-0.20250915202913-9fccddc465ef ) require ( diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 5a70558fe9c..a4801f18430 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -22,7 +22,7 @@ golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= -golang.org/x/tools v0.37.1-0.20250911182313-3adf0e96d87d h1:ykSs3aFXygx903AtF0IG27E/xLaCW5t85BAdCALyp8s= -golang.org/x/tools v0.37.1-0.20250911182313-3adf0e96d87d/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= +golang.org/x/tools v0.37.1-0.20250915202913-9fccddc465ef h1:ISPkUgvOYIt0oS7oVnwAPktCKBvgWkDlWWGMgX0veZM= +golang.org/x/tools v0.37.1-0.20250915202913-9fccddc465ef/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef h1:mqLYrXCXYEZOop9/Dbo6RPX11539nwiCNBb1icVPmw8= rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef/go.mod h1:8xcPgWmwlZONN1D9bjxtHEjrUtSEa3fakVF8iaewYKQ= diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go index 1aa7afb9c2a..efbf05d596a 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go @@ -237,7 +237,7 @@ Files: // so accumulate them all and then prefer the one that // matches build.Default.GOARCH. var archCandidates []*asmArch - for _, fld := range strings.Fields(m[1]) { + for fld := range strings.FieldsSeq(m[1]) { for _, a := range arches { if a.name == fld { archCandidates = append(archCandidates, a) diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go index 6c7a0df585d..6e32f298dc2 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go @@ -298,7 +298,7 @@ func (check *checker) plusBuildLine(pos token.Pos, line string) { fields := strings.Fields(line[len("//"):]) // IsPlusBuildConstraint check above implies fields[0] == "+build" for _, arg := range fields[1:] { - for _, elem := range strings.Split(arg, ",") { + for elem := range strings.SplitSeq(arg, ",") { if strings.HasPrefix(elem, "!!") { check.pass.Reportf(pos, "invalid double negative in build constraint: %s", arg) check.crossCheck = false diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/hostport/hostport.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/hostport/hostport.go index e808b1aa1ba..07f154963e8 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/hostport/hostport.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/hostport/hostport.go @@ -10,7 +10,9 @@ import ( "fmt" "go/ast" "go/constant" + "go/token" "go/types" + "strconv" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/inspect" @@ -57,13 +59,16 @@ func run(pass *analysis.Pass) (any, error) { } // checkAddr reports a diagnostic (and returns true) if e - // is a call of the form fmt.Sprintf("%d:%d", ...). + // is a call of the form fmt.Sprintf("%s:%d", ...). // The diagnostic includes a fix. // // dialCall is non-nil if the Dial call is non-local // but within the same file. checkAddr := func(e ast.Expr, dialCall *ast.CallExpr) { - if call, ok := e.(*ast.CallExpr); ok && typeutil.Callee(info, call) == fmtSprintf { + if call, ok := e.(*ast.CallExpr); ok && + len(call.Args) == 3 && + typeutil.Callee(info, call) == fmtSprintf { + // Examine format string. formatArg := call.Args[0] if tv := info.Types[formatArg]; tv.Value != nil { @@ -99,21 +104,41 @@ func run(pass *analysis.Pass) (any, error) { // Turn numeric port into a string. if numericPort { - // port => fmt.Sprintf("%d", port) - // 123 => "123" port := call.Args[2] - newPort := fmt.Sprintf(`fmt.Sprintf("%%d", %s)`, port) - if port := info.Types[port].Value; port != nil { - if i, ok := constant.Int64Val(port); ok { - newPort = fmt.Sprintf(`"%d"`, i) // numeric constant + + // Is port an integer literal? + // + // (Don't allow arbitrary constants k otherwise the + // transformation k => fmt.Sprintf("%d", "123") + // loses the symbolic connection to k.) + var kPort int64 = -1 + if lit, ok := port.(*ast.BasicLit); ok && lit.Kind == token.INT { + if v, err := strconv.ParseInt(lit.Value, 0, 64); err == nil { + kPort = v } } - - edits = append(edits, analysis.TextEdit{ - Pos: port.Pos(), - End: port.End(), - NewText: []byte(newPort), - }) + if kPort >= 0 { + // literal: 0x7B => "123" + edits = append(edits, analysis.TextEdit{ + Pos: port.Pos(), + End: port.End(), + NewText: fmt.Appendf(nil, `"%d"`, kPort), // (decimal) + }) + } else { + // non-literal: port => fmt.Sprintf("%d", port) + edits = append(edits, []analysis.TextEdit{ + { + Pos: port.Pos(), + End: port.Pos(), + NewText: []byte(`fmt.Sprintf("%d", `), + }, + { + Pos: port.End(), + End: port.End(), + NewText: []byte(`)`), + }, + }...) + } } // Refer to Dial call, if not adjacent. diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go index 9ad18a041e5..f008eca36fe 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go @@ -992,7 +992,7 @@ func (ss stringSet) String() string { } func (ss stringSet) Set(flag string) error { - for _, name := range strings.Split(flag, ",") { + for name := range strings.SplitSeq(flag, ",") { if len(name) == 0 { return fmt.Errorf("empty string") } diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go index 556ffed7d99..ed4cf7ae0be 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/unusedresult/unusedresult.go @@ -188,7 +188,7 @@ func (ss *stringSetFlag) String() string { func (ss *stringSetFlag) Set(s string) error { m := make(map[string]bool) // clobber previous value if s != "" { - for _, name := range strings.Split(s, ",") { + for name := range strings.SplitSeq(s, ",") { if name == "" { continue // TODO: report error? proceed? } diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go index 633af5a1da0..7b805b882bf 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go @@ -74,7 +74,8 @@ type Config struct { VetxOnly bool // run analysis only for facts, not diagnostics VetxOutput string // where to write file of fact information Stdout string // write stdout (e.g. JSON, unified diff) to this file - SucceedOnTypecheckFailure bool + SucceedOnTypecheckFailure bool // obsolete awful hack; see #18395 and below + WarnDiagnostics bool // printing diagnostics should not cause a non-zero exit } // Main is the main function of a vet-like analysis tool that must be @@ -162,7 +163,7 @@ func Run(configFile string, analyzers []*analysis.Analyzer) { // In VetxOnly mode, the analysis is run only for facts. if !cfg.VetxOnly { - code = processResults(fset, cfg.ID, results) + code = processResults(fset, cfg.ID, results, cfg.WarnDiagnostics) } os.Exit(code) @@ -186,7 +187,7 @@ func readConfig(filename string) (*Config, error) { return cfg, nil } -func processResults(fset *token.FileSet, id string, results []result) (exit int) { +func processResults(fset *token.FileSet, id string, results []result, warnDiagnostics bool) (exit int) { if analysisflags.Fix { // Don't print the diagnostics, // but apply all fixes from the root actions. @@ -235,7 +236,9 @@ func processResults(fset *token.FileSet, id string, results []result) (exit int) for _, res := range results { for _, diag := range res.diagnostics { analysisflags.PrintPlain(os.Stderr, fset, analysisflags.Context, diag) - exit = 1 + if !warnDiagnostics { + exit = 1 + } } } } diff --git a/src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go b/src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go index c8e349f4fed..bc7f9984e90 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go @@ -74,25 +74,6 @@ func TypeErrorEndPos(fset *token.FileSet, src []byte, start token.Pos) token.Pos return end } -// WalkASTWithParent walks the AST rooted at n. The semantics are -// similar to ast.Inspect except it does not call f(nil). -func WalkASTWithParent(n ast.Node, f func(n ast.Node, parent ast.Node) bool) { - var ancestors []ast.Node - ast.Inspect(n, func(n ast.Node) (recurse bool) { - if n == nil { - ancestors = ancestors[:len(ancestors)-1] - return false - } - - var parent ast.Node - if len(ancestors) > 0 { - parent = ancestors[len(ancestors)-1] - } - ancestors = append(ancestors, n) - return f(n, parent) - }) -} - // MatchingIdents finds the names of all identifiers in 'node' that match any of the given types. // 'pos' represents the position at which the identifiers may be inserted. 'pos' must be within // the scope of each of identifier we select. Otherwise, we will insert a variable at 'pos' that diff --git a/src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/extractdoc.go b/src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/extractdoc.go index 39507723d3d..bfb5900f1b3 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/extractdoc.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/extractdoc.go @@ -97,7 +97,7 @@ func ExtractDoc(content, name string) (string, error) { if f.Doc == nil { return "", fmt.Errorf("Go source file has no package doc comment") } - for _, section := range strings.Split(f.Doc.Text(), "\n# ") { + for section := range strings.SplitSeq(f.Doc.Text(), "\n# ") { if body := strings.TrimPrefix(section, "Analyzer "+name); body != section && body != "" && body[0] == '\r' || body[0] == '\n' { diff --git a/src/cmd/vendor/golang.org/x/tools/internal/astutil/comment.go b/src/cmd/vendor/golang.org/x/tools/internal/astutil/comment.go index ee4be23f226..c3a256c987c 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/astutil/comment.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/astutil/comment.go @@ -15,7 +15,7 @@ import ( // https://go.dev/wiki/Deprecated, or "" if the documented symbol is not // deprecated. func Deprecation(doc *ast.CommentGroup) string { - for _, p := range strings.Split(doc.Text(), "\n\n") { + for p := range strings.SplitSeq(doc.Text(), "\n\n") { // There is still some ambiguity for deprecation message. This function // only returns the paragraph introduced by "Deprecated: ". More // information related to the deprecation may follow in additional diff --git a/src/cmd/vendor/golang.org/x/tools/internal/typesinternal/qualifier.go b/src/cmd/vendor/golang.org/x/tools/internal/typesinternal/qualifier.go index b64f714eb30..64f47919f02 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/typesinternal/qualifier.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/typesinternal/qualifier.go @@ -15,6 +15,14 @@ import ( // file. // If the same package is imported multiple times, the last appearance is // recorded. +// +// TODO(adonovan): this function ignores the effect of shadowing. It +// should accept a [token.Pos] and a [types.Info] and compute only the +// set of imports that are not shadowed at that point, analogous to +// [analysisinternal.AddImport]. It could also compute (as a side +// effect) the set of additional imports required to ensure that there +// is an accessible import for each necessary package, making it +// converge even more closely with AddImport. func FileQualifier(f *ast.File, pkg *types.Package) types.Qualifier { // Construct mapping of import paths to their defined names. // It is only necessary to look at renaming imports. diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 37cd448bc9e..f166b77ea20 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -73,7 +73,7 @@ golang.org/x/text/internal/tag golang.org/x/text/language golang.org/x/text/transform golang.org/x/text/unicode/norm -# golang.org/x/tools v0.37.1-0.20250911182313-3adf0e96d87d +# golang.org/x/tools v0.37.1-0.20250915202913-9fccddc465ef ## explicit; go 1.24.0 golang.org/x/tools/cmd/bisect golang.org/x/tools/cover