From: Julien Cretel Date: Wed, 1 Oct 2025 20:08:18 +0000 (+0000) Subject: all: replace calls to errors.As with errors.AsType X-Git-Tag: go1.26rc1~635 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=6bcd97d9f4;p=gostls13.git all: replace calls to errors.As with errors.AsType This change replaces most occurrences (in code as well as in comments) of errors.As with errors.AsType. It leaves the errors package and vendored code untouched. Change-Id: I3bde73f318a0b408bdb8f5a251494af15a13118a GitHub-Last-Rev: 8aaaa36a5a12d2a6a90c6d51680464e1a3115139 GitHub-Pull-Request: golang/go#75698 Reviewed-on: https://go-review.googlesource.com/c/go/+/708495 Auto-Submit: Michael Pratt LUCI-TryBot-Result: Go LUCI Reviewed-by: Alan Donovan Reviewed-by: Michael Pratt --- diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 0d3c8b8e3e..4b7012e6c4 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -2468,8 +2468,8 @@ func TestInstantiateErrors(t *testing.T) { t.Fatalf("Instantiate(%v, %v) returned nil error, want non-nil", T, test.targs) } - var argErr *ArgumentError - if !errors.As(err, &argErr) { + argErr, ok := errors.AsType[*ArgumentError](err) + if !ok { t.Fatalf("Instantiate(%v, %v): error is not an *ArgumentError", T, test.targs) } @@ -2484,8 +2484,8 @@ func TestArgumentErrorUnwrapping(t *testing.T) { Index: 1, Err: Error{Msg: "test"}, } - var e Error - if !errors.As(err, &e) { + e, ok := errors.AsType[Error](err) + if !ok { t.Fatalf("error %v does not wrap types.Error", err) } if e.Msg != "test" { diff --git a/src/cmd/go/internal/base/path.go b/src/cmd/go/internal/base/path.go index 5bb7bc3bde..a7577f62e7 100644 --- a/src/cmd/go/internal/base/path.go +++ b/src/cmd/go/internal/base/path.go @@ -55,8 +55,7 @@ func sameFile(path1, path2 string) bool { // ShortPathError rewrites the path in err using base.ShortPath, if err is a wrapped PathError. func ShortPathError(err error) error { - var pe *fs.PathError - if errors.As(err, &pe) { + if pe, ok := errors.AsType[*fs.PathError](err); ok { pe.Path = ShortPath(pe.Path) } return err diff --git a/src/cmd/go/internal/doc/pkgsite.go b/src/cmd/go/internal/doc/pkgsite.go index 06289ac4fc..c173167b63 100644 --- a/src/cmd/go/internal/doc/pkgsite.go +++ b/src/cmd/go/internal/doc/pkgsite.go @@ -81,8 +81,7 @@ func doPkgsite(urlPath, fragment string) error { cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { - var ee *exec.ExitError - if errors.As(err, &ee) { + if ee, ok := errors.AsType[*exec.ExitError](err); ok { // Exit with the same exit status as pkgsite to avoid // printing of "exit status" error messages. // Any relevant messages have already been printed diff --git a/src/cmd/go/internal/fmtcmd/fmt.go b/src/cmd/go/internal/fmtcmd/fmt.go index 62b22f6bcf..83fba9661a 100644 --- a/src/cmd/go/internal/fmtcmd/fmt.go +++ b/src/cmd/go/internal/fmtcmd/fmt.go @@ -68,11 +68,10 @@ func runFmt(ctx context.Context, cmd *base.Command, args []string) { continue } if pkg.Error != nil { - var nogo *load.NoGoError - var embed *load.EmbedError - if (errors.As(pkg.Error, &nogo) || errors.As(pkg.Error, &embed)) && len(pkg.InternalAllGoFiles()) > 0 { - // Skip this error, as we will format - // all files regardless. + if _, ok := errors.AsType[*load.NoGoError](pkg.Error); ok { + // Skip this error, as we will format all files regardless. + } else if _, ok := errors.AsType[*load.EmbedError](pkg.Error); ok && len(pkg.InternalAllGoFiles()) > 0 { + // Skip this error, as we will format all files regardless. } else { base.Errorf("%v", pkg.Error) continue diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 135d7579d6..a894affc84 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -290,8 +290,8 @@ func (p *Package) setLoadPackageDataError(err error, path string, stk *ImportSta // Replace (possibly wrapped) *build.NoGoError with *load.NoGoError. // The latter is more specific about the cause. - var nogoErr *build.NoGoError - if errors.As(err, &nogoErr) { + nogoErr, ok := errors.AsType[*build.NoGoError](err) + if ok { if p.Dir == "" && nogoErr.Dir != "" { p.Dir = nogoErr.Dir } diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index d8b1f83bf1..5017f878ed 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -1294,15 +1294,13 @@ func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPack continue } - var ( - importMissing *modload.ImportMissingError - ambiguous *modload.AmbiguousImportError - ) - if !errors.As(err, &importMissing) && !errors.As(err, &ambiguous) { - // The package, which is a dependency of something we care about, has some - // problem that we can't resolve with a version change. - // Leave the error for the final LoadPackages call. - continue + if _, ok := errors.AsType[*modload.ImportMissingError](err); !ok { + if _, ok := errors.AsType[*modload.AmbiguousImportError](err); !ok { + // The package, which is a dependency of something we care about, has some + // problem that we can't resolve with a version change. + // Leave the error for the final LoadPackages call. + continue + } } path := pkgPath @@ -1674,7 +1672,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin } base.SetExitStatus(1) - if ambiguousErr := (*modload.AmbiguousImportError)(nil); errors.As(err, &ambiguousErr) { + if ambiguousErr, ok := errors.AsType[*modload.AmbiguousImportError](err); ok { for _, m := range ambiguousErr.Modules { relevantMods[m] |= hasPkg } @@ -1717,7 +1715,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin i := i r.work.Add(func() { err := modload.CheckRetractions(ctx, retractions[i].m) - if retractErr := (*modload.ModuleRetractedError)(nil); errors.As(err, &retractErr) { + if _, ok := errors.AsType[*modload.ModuleRetractedError](err); ok { retractions[i].message = err.Error() } }) @@ -1994,8 +1992,8 @@ func (r *resolver) updateBuildList(ctx context.Context, additions []module.Versi toolchain.SwitchOrFatal(ctx, err) } - var constraint *modload.ConstraintError - if !errors.As(err, &constraint) { + constraint, ok := errors.AsType[*modload.ConstraintError](err) + if !ok { base.Fatal(err) } @@ -2066,8 +2064,11 @@ func reqsFromGoMod(f *modfile.File) []module.Version { // does not exist at the requested version, either because the module does not // exist at all or because it does not include that specific version. func isNoSuchModuleVersion(err error) bool { - var noMatch *modload.NoMatchingVersionError - return errors.Is(err, os.ErrNotExist) || errors.As(err, &noMatch) + if errors.Is(err, os.ErrNotExist) { + return true + } + _, ok := errors.AsType[*modload.NoMatchingVersionError](err) + return ok } // isNoSuchPackageVersion reports whether err indicates that the requested @@ -2075,8 +2076,11 @@ func isNoSuchModuleVersion(err error) bool { // that could contain it exists at that version, or because every such module // that does exist does not actually contain the package. func isNoSuchPackageVersion(err error) bool { - var noPackage *modload.PackageNotInModuleError - return isNoSuchModuleVersion(err) || errors.As(err, &noPackage) + if isNoSuchModuleVersion(err) { + return true + } + _, ok := errors.AsType[*modload.PackageNotInModuleError](err) + return ok } // workspace represents the set of modules in a workspace. diff --git a/src/cmd/go/internal/modget/query.go b/src/cmd/go/internal/modget/query.go index db09947293..59f3023ffc 100644 --- a/src/cmd/go/internal/modget/query.go +++ b/src/cmd/go/internal/modget/query.go @@ -283,7 +283,7 @@ func reportError(q *query, err error) { // If err already mentions all of the relevant parts of q, just log err to // reduce stutter. Otherwise, log both q and err. // - // TODO(bcmills): Use errors.As to unpack these errors instead of parsing + // TODO(bcmills): Use errors.AsType to unpack these errors instead of parsing // strings with regular expressions. if !utf8.ValidString(q.pattern) || !utf8.ValidString(q.version) { diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go index cb168d58a2..a8ab82d1ec 100644 --- a/src/cmd/go/internal/modload/build.go +++ b/src/cmd/go/internal/modload/build.go @@ -129,11 +129,10 @@ func addUpdate(ctx context.Context, m *modinfo.ModulePublic) { } info, err := Query(ctx, m.Path, "upgrade", m.Version, CheckAllowed) - var noVersionErr *NoMatchingVersionError - if errors.Is(err, ErrDisallowed) || + if _, ok := errors.AsType[*NoMatchingVersionError](err); ok || errors.Is(err, fs.ErrNotExist) || - errors.As(err, &noVersionErr) { - // Ignore "not found" and "no matching version" errors. + errors.Is(err, ErrDisallowed) { + // Ignore "no matching version" and "not found" errors. // This means the proxy has no matching version or no versions at all. // // Ignore "disallowed" errors. This means the current version is @@ -238,10 +237,10 @@ func addRetraction(ctx context.Context, m *modinfo.ModulePublic) { } err := CheckRetractions(ctx, module.Version{Path: m.Path, Version: m.Version}) - var noVersionErr *NoMatchingVersionError - var retractErr *ModuleRetractedError - if err == nil || errors.Is(err, fs.ErrNotExist) || errors.As(err, &noVersionErr) { - // Ignore "not found" and "no matching version" errors. + if err == nil { + return + } else if _, ok := errors.AsType[*NoMatchingVersionError](err); ok || errors.Is(err, fs.ErrNotExist) { + // Ignore "no matching version" and "not found" errors. // This means the proxy has no matching version or no versions at all. // // We should report other errors though. An attacker that controls the @@ -250,7 +249,7 @@ func addRetraction(ctx context.Context, m *modinfo.ModulePublic) { // hide versions, since the "list" and "latest" endpoints are not // authenticated. return - } else if errors.As(err, &retractErr) { + } else if retractErr, ok := errors.AsType[*ModuleRetractedError](err); ok { if len(retractErr.Rationale) == 0 { m.Retracted = []string{"retracted by module author"} } else { @@ -265,9 +264,8 @@ func addRetraction(ctx context.Context, m *modinfo.ModulePublic) { // author. m.Error is set if there's an error loading deprecation information. func addDeprecation(ctx context.Context, m *modinfo.ModulePublic) { deprecation, err := CheckDeprecation(ctx, module.Version{Path: m.Path, Version: m.Version}) - var noVersionErr *NoMatchingVersionError - if errors.Is(err, fs.ErrNotExist) || errors.As(err, &noVersionErr) { - // Ignore "not found" and "no matching version" errors. + if _, ok := errors.AsType[*NoMatchingVersionError](err); ok || errors.Is(err, fs.ErrNotExist) { + // Ignore "no matching version" and "not found" errors. // This means the proxy has no matching version or no versions at all. // // We should report other errors though. An attacker that controls the diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 086626042c..cf64ee1dc2 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -922,7 +922,7 @@ func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requir q.Add(func() { skipModFile := true _, _, _, _, err := importFromModules(ctx, pkg.path, tidy, nil, skipModFile) - if aie := (*AmbiguousImportError)(nil); errors.As(err, &aie) { + if _, ok := errors.AsType[*AmbiguousImportError](err); ok { disambiguateRoot.Store(pkg.mod, true) } }) diff --git a/src/cmd/go/internal/modload/edit.go b/src/cmd/go/internal/modload/edit.go index 153c21a90c..96d864545d 100644 --- a/src/cmd/go/internal/modload/edit.go +++ b/src/cmd/go/internal/modload/edit.go @@ -226,8 +226,10 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel // conflict we discover from one or more of the original roots. mg, upgradedRoots, err := extendGraph(ctx, rootPruning, roots, selectedRoot) if err != nil { - var tooNew *gover.TooNewError - if mg == nil || errors.As(err, &tooNew) { + if mg == nil { + return orig, false, err + } + if _, ok := errors.AsType[*gover.TooNewError](err); ok { return orig, false, err } // We're about to walk the entire extended module graph, so we will find diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index 83e7e03711..392fe3edd7 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -410,7 +410,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M root, isLocal, err := fetch(ctx, m) if err != nil { - if sumErr := (*sumMissingError)(nil); errors.As(err, &sumErr) { + if _, ok := errors.AsType[*sumMissingError](err); ok { // We are missing a sum needed to fetch a module in the build list. // We can't verify that the package is unique, and we may not find // the package at all. Keep checking other modules to decide which @@ -549,7 +549,7 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver for _, m := range mods { root, isLocal, err := fetch(ctx, m) if err != nil { - if sumErr := (*sumMissingError)(nil); errors.As(err, &sumErr) { + if _, ok := errors.AsType[*sumMissingError](err); ok { return module.Version{}, &ImportMissingSumError{importPath: path} } return module.Version{}, err diff --git a/src/cmd/go/internal/modload/list.go b/src/cmd/go/internal/modload/list.go index b66e73a112..803bab49ae 100644 --- a/src/cmd/go/internal/modload/list.go +++ b/src/cmd/go/internal/modload/list.go @@ -305,13 +305,11 @@ func listModules(ctx context.Context, rs *Requirements, args []string, mode List // modinfoError wraps an error to create an error message in // modinfo.ModuleError with minimal redundancy. func modinfoError(path, vers string, err error) *modinfo.ModuleError { - var nerr *NoMatchingVersionError - var merr *module.ModuleError - if errors.As(err, &nerr) { + if _, ok := errors.AsType[*NoMatchingVersionError](err); ok { // NoMatchingVersionError contains the query, so we don't mention the // query again in ModuleError. err = &module.ModuleError{Path: path, Err: err} - } else if !errors.As(err, &merr) { + } else if _, ok := errors.AsType[*module.ModuleError](err); !ok { // If the error does not contain path and version, wrap it in a // module.ModuleError. err = &module.ModuleError{Path: path, Version: vers, Err: err} diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 413de8148f..0d661eb2e7 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -1304,7 +1304,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { } // Add importer information to checksum errors. - if sumErr := (*ImportMissingSumError)(nil); errors.As(pkg.err, &sumErr) { + if sumErr, ok := errors.AsType[*ImportMissingSumError](pkg.err); ok { if importer := pkg.stack; importer != nil { sumErr.importer = importer.path sumErr.importerVersion = importer.mod.Version @@ -1312,7 +1312,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader { } } - if stdErr := (*ImportMissingError)(nil); errors.As(pkg.err, &stdErr) && stdErr.isStd { + if stdErr, ok := errors.AsType[*ImportMissingError](pkg.err); ok && stdErr.isStd { // Add importer go version information to import errors of standard // library packages arising from newer releases. if importer := pkg.stack; importer != nil { @@ -1384,7 +1384,7 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err var maxTooNew *gover.TooNewError for _, pkg := range ld.pkgs { if pkg.err != nil { - if tooNew := (*gover.TooNewError)(nil); errors.As(pkg.err, &tooNew) { + if tooNew, ok := errors.AsType[*gover.TooNewError](pkg.err); ok { if maxTooNew == nil || gover.Compare(tooNew.GoVersion, maxTooNew.GoVersion) > 0 { maxTooNew = tooNew } @@ -1573,7 +1573,7 @@ func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[mod // we should only add the missing import once. continue } - if !errors.As(pkg.err, new(*ImportMissingError)) { + if _, ok := errors.AsType[*ImportMissingError](pkg.err); !ok { // Leave other errors for Import or load.Packages to report. continue } @@ -1584,8 +1584,7 @@ func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[mod var err error mod, err = queryImport(ctx, pkg.path, ld.requirements) if err != nil { - var ime *ImportMissingError - if errors.As(err, &ime) { + if ime, ok := errors.AsType[*ImportMissingError](err); ok { for curstack := pkg.stack; curstack != nil; curstack = curstack.stack { if LoaderState.MainModules.Contains(curstack.mod.Path) { ime.ImportingMainModule = curstack.mod @@ -1625,7 +1624,7 @@ func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[mod maxTooNewPkg *loadPkg ) for _, pm := range pkgMods { - if tooNew := (*gover.TooNewError)(nil); errors.As(pm.pkg.err, &tooNew) { + if tooNew, ok := errors.AsType[*gover.TooNewError](pm.pkg.err); ok { if maxTooNew == nil || gover.Compare(tooNew.GoVersion, maxTooNew.GoVersion) > 0 { maxTooNew = tooNew maxTooNewPkg = pm.pkg @@ -1771,8 +1770,7 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch // full module graph. m, _, _, _, err := importFromModules(ctx, path, ld.requirements, nil, ld.skipImportModFiles) if err != nil { - var missing *ImportMissingError - if errors.As(err, &missing) && ld.ResolveMissingImports { + if _, ok := errors.AsType[*ImportMissingError](err); ok && ld.ResolveMissingImports { // This package isn't provided by any selected module. // If we can find it, it will be a new root dependency. m, err = queryImport(ctx, path, ld.requirements) @@ -2196,14 +2194,14 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements, // module that previously provided the package to a version that no // longer does, or to a version for which the module source code (but // not the go.mod file in isolation) has a checksum error. - if missing := (*ImportMissingError)(nil); errors.As(mismatch.err, &missing) { + if _, ok := errors.AsType[*ImportMissingError](mismatch.err); ok { selected := module.Version{ Path: pkg.mod.Path, Version: mg.Selected(pkg.mod.Path), } ld.error(fmt.Errorf("%s loaded from %v,\n\tbut go %s would fail to locate it in %s", pkg.stackText(), pkg.mod, compatVersion, selected)) } else { - if ambiguous := (*AmbiguousImportError)(nil); errors.As(mismatch.err, &ambiguous) { + if _, ok := errors.AsType[*AmbiguousImportError](mismatch.err); ok { // TODO: Is this check needed? } ld.error(fmt.Errorf("%s loaded from %v,\n\tbut go %s would fail to locate it:\n\t%v", pkg.stackText(), pkg.mod, compatVersion, mismatch.err)) diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index fa2348d97b..3fdbdc7010 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -76,8 +76,7 @@ func ReadModFile(gomod string, fix modfile.VersionFixer) (data []byte, f *modfil } func shortPathErrorList(err error) error { - var el modfile.ErrorList - if errors.As(err, &el) { + if el, ok := errors.AsType[modfile.ErrorList](err); ok { for i := range el { el[i].Filename = base.ShortPath(el[i].Filename) } @@ -175,12 +174,15 @@ func (e *excludedError) Is(err error) bool { return err == ErrDisallowed } // its author. func CheckRetractions(ctx context.Context, m module.Version) (err error) { defer func() { - if retractErr := (*ModuleRetractedError)(nil); err == nil || errors.As(err, &retractErr) { + if err == nil { + return + } + if _, ok := errors.AsType[*ModuleRetractedError](err); ok { return } // Attribute the error to the version being checked, not the version from // which the retractions were to be loaded. - if mErr := (*module.ModuleError)(nil); errors.As(err, &mErr) { + if mErr, ok := errors.AsType[*module.ModuleError](err); ok { err = mErr.Err } err = &retractionLoadingError{m: m, err: err} diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index 94ee8bc955..b37a244fbb 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -932,7 +932,7 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod if notExistErr == nil { notExistErr = rErr } - } else if iv := (*module.InvalidVersionError)(nil); errors.As(rErr, &iv) { + } else if _, ok := errors.AsType[*module.InvalidVersionError](rErr); ok { if invalidVersion == nil { invalidVersion = rErr } diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index e667bd64f7..e225929add 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -1741,8 +1741,7 @@ func (r *runTestActor) Act(b *work.Builder, ctx context.Context, a *work.Action) } else if errors.Is(err, exec.ErrWaitDelay) { fmt.Fprintf(cmd.Stdout, "*** Test I/O incomplete %v after exiting.\n", cmd.WaitDelay) } - var ee *exec.ExitError - if len(out) == 0 || !errors.As(err, &ee) || !ee.Exited() { + if ee, ok := errors.AsType[*exec.ExitError](err); !ok || !ee.Exited() || len(out) == 0 { // If there was no test output, print the exit status so that the reason // for failure is clear. fmt.Fprintf(cmd.Stdout, "%s\n", err) diff --git a/src/cmd/go/internal/test/testflag.go b/src/cmd/go/internal/test/testflag.go index fc2b22cb56..d6891a1d0b 100644 --- a/src/cmd/go/internal/test/testflag.go +++ b/src/cmd/go/internal/test/testflag.go @@ -261,7 +261,7 @@ func testFlags(args []string) (packageNames, passToTest []string) { break } - if nf := (cmdflag.NonFlagError{}); errors.As(err, &nf) { + if nf, ok := errors.AsType[cmdflag.NonFlagError](err); ok { if !inPkgList && packageNames != nil { // We already saw the package list previously, and this argument is not // a flag, so it — and everything after it — must be either a value for @@ -296,7 +296,7 @@ func testFlags(args []string) (packageNames, passToTest []string) { inPkgList = false } - if nd := (cmdflag.FlagNotDefinedError{}); errors.As(err, &nd) { + if nd, ok := errors.AsType[cmdflag.FlagNotDefinedError](err); ok { // This is a flag we do not know. We must assume that any args we see // after this might be flag arguments, not package names, so make // packageNames non-nil to indicate that the package list is complete. diff --git a/src/cmd/go/internal/vcweb/vcstest/vcstest_test.go b/src/cmd/go/internal/vcweb/vcstest/vcstest_test.go index 67234ac20d..6a6a0eee57 100644 --- a/src/cmd/go/internal/vcweb/vcstest/vcstest_test.go +++ b/src/cmd/go/internal/vcweb/vcstest/vcstest_test.go @@ -155,10 +155,10 @@ func TestScripts(t *testing.T) { t.Log(buf) } if err != nil { - if notInstalled := (vcweb.ServerNotInstalledError{}); errors.As(err, ¬Installed) || errors.Is(err, exec.ErrNotFound) { + if _, ok := errors.AsType[vcweb.ServerNotInstalledError](err); ok || errors.Is(err, exec.ErrNotFound) { t.Skip(err) } - if skip := (vcweb.SkipError{}); errors.As(err, &skip) { + if skip, ok := errors.AsType[vcweb.SkipError](err); ok { if skip.Msg == "" { t.Skip("SKIP") } else { diff --git a/src/cmd/go/internal/vcweb/vcweb.go b/src/cmd/go/internal/vcweb/vcweb.go index b81ff5e63d..4b4e127bb0 100644 --- a/src/cmd/go/internal/vcweb/vcweb.go +++ b/src/cmd/go/internal/vcweb/vcweb.go @@ -244,9 +244,9 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { }) if err != nil { s.logger.Print(err) - if notFound := (ScriptNotFoundError{}); errors.As(err, ¬Found) { + if _, ok := errors.AsType[ScriptNotFoundError](err); ok { http.NotFound(w, req) - } else if notInstalled := (ServerNotInstalledError{}); errors.As(err, ¬Installed) || errors.Is(err, exec.ErrNotFound) { + } else if _, ok := errors.AsType[ServerNotInstalledError](err); ok || errors.Is(err, exec.ErrNotFound) { http.Error(w, err.Error(), http.StatusNotImplemented) } else { http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/src/cmd/go/internal/version/version.go b/src/cmd/go/internal/version/version.go index c26dd42b4e..781bc080e8 100644 --- a/src/cmd/go/internal/version/version.go +++ b/src/cmd/go/internal/version/version.go @@ -168,7 +168,7 @@ func scanFile(file string, info fs.FileInfo, mustPrint bool) bool { bi, err := buildinfo.ReadFile(file) if err != nil { if mustPrint { - if pathErr := (*os.PathError)(nil); errors.As(err, &pathErr) && filepath.Clean(pathErr.Path) == filepath.Clean(file) { + if pathErr, ok := errors.AsType[*os.PathError](err); ok && filepath.Clean(pathErr.Path) == filepath.Clean(file) { fmt.Fprintf(os.Stderr, "%v\n", file) } else { // Skip errors for non-Go binaries. diff --git a/src/cmd/go/internal/vet/vetflag.go b/src/cmd/go/internal/vet/vetflag.go index 7ebd8c9bfd..7342b99d6e 100644 --- a/src/cmd/go/internal/vet/vetflag.go +++ b/src/cmd/go/internal/vet/vetflag.go @@ -160,7 +160,7 @@ func toolFlags(cmd *base.Command, args []string) (passToTool, packageNames []str break } - if nf := (cmdflag.NonFlagError{}); errors.As(err, &nf) { + if _, ok := errors.AsType[cmdflag.NonFlagError](err); ok { // Everything from here on out — including the argument we just consumed — // must be a package name. packageNames = args diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index adc98f9313..fdb483d46f 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -705,7 +705,7 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) { continue } haveErrors = true - if missingErr := (*modload.ImportMissingError)(nil); !errors.As(pkg.Error, &missingErr) { + if _, ok := errors.AsType[*modload.ImportMissingError](pkg.Error); !ok { allMissingErrors = false break } diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index fa6ddce24b..703b4367db 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -169,9 +169,10 @@ func (b *Builder) Do(ctx context.Context, root *Action) { a.Package.Incomplete = true } } else { - var ipe load.ImportPathError - if a.Package != nil && (!errors.As(err, &ipe) || ipe.ImportPath() != a.Package.ImportPath) { - err = fmt.Errorf("%s: %v", a.Package.ImportPath, err) + if a.Package != nil { + if ipe, ok := errors.AsType[load.ImportPathError](err); !ok || ipe.ImportPath() != a.Package.ImportPath { + err = fmt.Errorf("%s: %v", a.Package.ImportPath, err) + } } sh := b.Shell(a) sh.Errorf("%s", err) diff --git a/src/cmd/internal/bootstrap_test/experiment_toolid_test.go b/src/cmd/internal/bootstrap_test/experiment_toolid_test.go index ff2379c899..ca292b7008 100644 --- a/src/cmd/internal/bootstrap_test/experiment_toolid_test.go +++ b/src/cmd/internal/bootstrap_test/experiment_toolid_test.go @@ -97,7 +97,7 @@ func runCmd(t *testing.T, dir string, env []string, path string, args ...string) cmd.Env = env out, err := cmd.Output() if err != nil { - if ee := (*exec.ExitError)(nil); errors.As(err, &ee) { + if ee, ok := errors.AsType[*exec.ExitError](err); ok { out = append(out, ee.Stderr...) } t.Fatalf("%s failed:\n%s\n%s", cmd, out, err) diff --git a/src/cmd/internal/robustio/robustio_darwin.go b/src/cmd/internal/robustio/robustio_darwin.go index 99fd8ebc2f..69ea247930 100644 --- a/src/cmd/internal/robustio/robustio_darwin.go +++ b/src/cmd/internal/robustio/robustio_darwin.go @@ -13,9 +13,6 @@ const errFileNotFound = syscall.ENOENT // isEphemeralError returns true if err may be resolved by waiting. func isEphemeralError(err error) bool { - var errno syscall.Errno - if errors.As(err, &errno) { - return errno == errFileNotFound - } - return false + errno, ok := errors.AsType[syscall.Errno](err) + return ok && errno == errFileNotFound } diff --git a/src/cmd/internal/robustio/robustio_flaky.go b/src/cmd/internal/robustio/robustio_flaky.go index c56e36ca62..ec1a2daea6 100644 --- a/src/cmd/internal/robustio/robustio_flaky.go +++ b/src/cmd/internal/robustio/robustio_flaky.go @@ -31,8 +31,7 @@ func retry(f func() (err error, mayRetry bool)) error { return err } - var errno syscall.Errno - if errors.As(err, &errno) && (lowestErrno == 0 || errno < lowestErrno) { + if errno, ok := errors.AsType[syscall.Errno](err); ok && (lowestErrno == 0 || errno < lowestErrno) { bestErr = err lowestErrno = errno } else if bestErr == nil { diff --git a/src/cmd/internal/robustio/robustio_windows.go b/src/cmd/internal/robustio/robustio_windows.go index 687dcb66f8..ad46ec5cfe 100644 --- a/src/cmd/internal/robustio/robustio_windows.go +++ b/src/cmd/internal/robustio/robustio_windows.go @@ -14,8 +14,7 @@ const errFileNotFound = syscall.ERROR_FILE_NOT_FOUND // isEphemeralError returns true if err may be resolved by waiting. func isEphemeralError(err error) bool { - var errno syscall.Errno - if errors.As(err, &errno) { + if errno, ok := errors.AsType[syscall.Errno](err); ok { switch errno { case syscall.ERROR_ACCESS_DENIED, syscall.ERROR_FILE_NOT_FOUND, diff --git a/src/cmd/internal/script/engine.go b/src/cmd/internal/script/engine.go index eb9344f6e2..4607868379 100644 --- a/src/cmd/internal/script/engine.go +++ b/src/cmd/internal/script/engine.go @@ -185,7 +185,7 @@ func (e *Engine) Execute(s *State, file string, script *bufio.Reader, log io.Wri var lineno int lineErr := func(err error) error { - if errors.As(err, new(*CommandError)) { + if _, ok := errors.AsType[*CommandError](err); ok { return err } return fmt.Errorf("%s:%d: %w", file, lineno, err) @@ -283,7 +283,7 @@ func (e *Engine) Execute(s *State, file string, script *bufio.Reader, log io.Wri // Run the command. err = e.runCommand(s, cmd, impl) if err != nil { - if stop := (stopError{}); errors.As(err, &stop) { + if stop, ok := errors.AsType[stopError](err); ok { // Since the 'stop' command halts execution of the entire script, // log its message separately from the section in which it appears. err = endSection(true) @@ -607,13 +607,13 @@ func checkStatus(cmd *command, err error) error { return nil } - if s := (stopError{}); errors.As(err, &s) { + if _, ok := errors.AsType[stopError](err); ok { // This error originated in the Stop command. // Propagate it as-is. return cmdError(cmd, err) } - if w := (waitError{}); errors.As(err, &w) { + if _, ok := errors.AsType[waitError](err); ok { // This error was surfaced from a background process by a call to Wait. // Add a call frame for Wait itself, but ignore its "want" field. // (Wait itself cannot fail to wait on commands or else it would leak diff --git a/src/cmd/internal/script/scripttest/scripttest.go b/src/cmd/internal/script/scripttest/scripttest.go index bace662a67..349201fd18 100644 --- a/src/cmd/internal/script/scripttest/scripttest.go +++ b/src/cmd/internal/script/scripttest/scripttest.go @@ -89,7 +89,7 @@ func Run(t testing.TB, e *script.Engine, s *script.State, filename string, testS return e.Execute(s, filename, bufio.NewReader(testScript), log) }() - if skip := (skipError{}); errors.As(err, &skip) { + if skip, ok := errors.AsType[skipError](err); ok { if skip.msg == "" { t.Skip("SKIP") } else { diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go index 0125ba8e0f..31822d21f3 100644 --- a/src/cmd/link/link_test.go +++ b/src/cmd/link/link_test.go @@ -1532,11 +1532,13 @@ func TestFlagS(t *testing.T) { } cmd = testenv.Command(t, testenv.GoToolPath(t), "tool", "nm", exe) out, err = cmd.CombinedOutput() - if err != nil && !errors.As(err, new(*exec.ExitError)) { - // Error exit is fine as it may have no symbols. - // On darwin we need to emit dynamic symbol references so it - // actually has some symbols, and nm succeeds. - t.Errorf("(mode=%s) go tool nm failed: %v\n%s", mode, err, out) + if err != nil { + if _, ok := errors.AsType[*exec.ExitError](err); !ok { + // Error exit is fine as it may have no symbols. + // On darwin we need to emit dynamic symbol references so it + // actually has some symbols, and nm succeeds. + t.Errorf("(mode=%s) go tool nm failed: %v\n%s", mode, err, out) + } } for _, s := range syms { if bytes.Contains(out, []byte(s)) { diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go index 09dc9ea94c..2de120a132 100644 --- a/src/crypto/tls/conn.go +++ b/src/crypto/tls/conn.go @@ -1578,9 +1578,9 @@ func (c *Conn) handshakeContext(ctx context.Context) (ret error) { // the handshake (RFC 9001, Section 5.7). c.quicSetReadSecret(QUICEncryptionLevelApplication, c.cipherSuite, c.in.trafficSecret) } else { - var a alert c.out.Lock() - if !errors.As(c.out.err, &a) { + a, ok := errors.AsType[alert](c.out.err) + if !ok { a = alertInternalError } c.out.Unlock() diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index 088c66fadb..a2cf176a86 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -965,10 +965,9 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error { chains, err := certs[0].Verify(opts) if err != nil { - var errCertificateInvalid x509.CertificateInvalidError - if errors.As(err, &x509.UnknownAuthorityError{}) { + if _, ok := errors.AsType[x509.UnknownAuthorityError](err); ok { c.sendAlert(alertUnknownCA) - } else if errors.As(err, &errCertificateInvalid) && errCertificateInvalid.Reason == x509.Expired { + } else if errCertificateInvalid, ok := errors.AsType[x509.CertificateInvalidError](err); ok && errCertificateInvalid.Reason == x509.Expired { c.sendAlert(alertCertificateExpired) } else { c.sendAlert(alertBadCertificate) diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go index 941f2a3373..43183db2a1 100644 --- a/src/crypto/tls/handshake_server_test.go +++ b/src/crypto/tls/handshake_server_test.go @@ -403,8 +403,7 @@ func TestAlertForwarding(t *testing.T) { err := Server(s, testConfig).Handshake() s.Close() - var opErr *net.OpError - if !errors.As(err, &opErr) || opErr.Err != error(alertUnknownCA) { + if opErr, ok := errors.AsType[*net.OpError](err); !ok || opErr.Err != error(alertUnknownCA) { t.Errorf("Got error: %s; expected: %s", err, error(alertUnknownCA)) } } diff --git a/src/crypto/tls/quic.go b/src/crypto/tls/quic.go index 3be479eb12..2ba2242b2d 100644 --- a/src/crypto/tls/quic.go +++ b/src/crypto/tls/quic.go @@ -362,12 +362,11 @@ func quicError(err error) error { if err == nil { return nil } - var ae AlertError - if errors.As(err, &ae) { + if _, ok := errors.AsType[AlertError](err); ok { return err } - var a alert - if !errors.As(err, &a) { + a, ok := errors.AsType[alert](err) + if !ok { a = alertInternalError } // Return an error wrapping the original error and an AlertError. diff --git a/src/crypto/tls/quic_test.go b/src/crypto/tls/quic_test.go index f6e8c55d9d..5f4b2b7707 100644 --- a/src/crypto/tls/quic_test.go +++ b/src/crypto/tls/quic_test.go @@ -368,8 +368,7 @@ func TestQUICHandshakeError(t *testing.T) { if !errors.Is(err, AlertError(alertBadCertificate)) { t.Errorf("connection handshake terminated with error %q, want alertBadCertificate", err) } - var e *CertificateVerificationError - if !errors.As(err, &e) { + if _, ok := errors.AsType[*CertificateVerificationError](err); !ok { t.Errorf("connection handshake terminated with error %q, want CertificateVerificationError", err) } } diff --git a/src/debug/buildinfo/buildinfo.go b/src/debug/buildinfo/buildinfo.go index 12e3b750d2..d202d5050a 100644 --- a/src/debug/buildinfo/buildinfo.go +++ b/src/debug/buildinfo/buildinfo.go @@ -67,7 +67,7 @@ const ( // with module support. func ReadFile(name string) (info *BuildInfo, err error) { defer func() { - if pathErr := (*fs.PathError)(nil); errors.As(err, &pathErr) { + if _, ok := errors.AsType[*fs.PathError](err); ok { err = fmt.Errorf("could not read Go build info: %w", err) } else if err != nil { err = fmt.Errorf("could not read Go build info from %s: %w", name, err) diff --git a/src/encoding/json/jsontext/coder_test.go b/src/encoding/json/jsontext/coder_test.go index 4a9efb3b8f..8602e3e7ff 100644 --- a/src/encoding/json/jsontext/coder_test.go +++ b/src/encoding/json/jsontext/coder_test.go @@ -486,7 +486,7 @@ func testCoderInterleaved(t *testing.T, where jsontest.CasePos, modeName string, // Retry as a ReadToken call. expectError := dec.PeekKind() == '}' || dec.PeekKind() == ']' if expectError { - if !errors.As(err, new(*SyntacticError)) { + if _, ok := errors.AsType[*SyntacticError](err); !ok { t.Fatalf("%s: Decoder.ReadToken error is %T, want %T", where, err, new(SyntacticError)) } tickTock = !tickTock diff --git a/src/encoding/json/jsontext/fuzz_test.go b/src/encoding/json/jsontext/fuzz_test.go index 60d16b9e27..3ad181d434 100644 --- a/src/encoding/json/jsontext/fuzz_test.go +++ b/src/encoding/json/jsontext/fuzz_test.go @@ -53,9 +53,10 @@ func FuzzCoder(f *testing.F) { } else { val, err := dec.ReadValue() if err != nil { - expectError := dec.PeekKind() == '}' || dec.PeekKind() == ']' - if expectError && errors.As(err, new(*SyntacticError)) { - continue + if expectError := dec.PeekKind() == '}' || dec.PeekKind() == ']'; expectError { + if _, ok := errors.AsType[*SyntacticError](err); ok { + continue + } } if err == io.EOF { break diff --git a/src/encoding/json/jsontext/state.go b/src/encoding/json/jsontext/state.go index d214fd5190..538dfe32bf 100644 --- a/src/encoding/json/jsontext/state.go +++ b/src/encoding/json/jsontext/state.go @@ -24,8 +24,7 @@ import ( // The name of a duplicate JSON object member can be extracted as: // // err := ... -// var serr jsontext.SyntacticError -// if errors.As(err, &serr) && serr.Err == jsontext.ErrDuplicateName { +// if serr, ok := errors.AsType[jsontext.SyntacticError](err); ok && serr.Err == jsontext.ErrDuplicateName { // ptr := serr.JSONPointer // JSON pointer to duplicate name // name := ptr.LastToken() // duplicate name itself // ... diff --git a/src/encoding/json/v2/errors.go b/src/encoding/json/v2/errors.go index 9485d7b527..0f50d608c9 100644 --- a/src/encoding/json/v2/errors.go +++ b/src/encoding/json/v2/errors.go @@ -28,8 +28,7 @@ import ( // The name of an unknown JSON object member can be extracted as: // // err := ... -// var serr json.SemanticError -// if errors.As(err, &serr) && serr.Err == json.ErrUnknownName { +// if serr, ok := errors.AsType[json.SemanticError](err); ok && serr.Err == json.ErrUnknownName { // ptr := serr.JSONPointer // JSON pointer to unknown name // name := ptr.LastToken() // unknown name itself // ... diff --git a/src/encoding/json/v2/example_test.go b/src/encoding/json/v2/example_test.go index c6bf0a864d..6d539bbd36 100644 --- a/src/encoding/json/v2/example_test.go +++ b/src/encoding/json/v2/example_test.go @@ -371,8 +371,7 @@ func Example_unknownMembers() { // Specifying RejectUnknownMembers causes Unmarshal // to reject the presence of any unknown members. err = json.Unmarshal([]byte(input), new(Color), json.RejectUnknownMembers(true)) - var serr *json.SemanticError - if errors.As(err, &serr) && serr.Err == json.ErrUnknownName { + if serr, ok := errors.AsType[*json.SemanticError](err); ok && serr.Err == json.ErrUnknownName { fmt.Println("Unmarshal error:", serr.Err, strconv.Quote(serr.JSONPointer.LastToken())) } diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index f7a98ae280..2798b9e0c4 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -2480,8 +2480,8 @@ func TestInstantiateErrors(t *testing.T) { t.Fatalf("Instantiate(%v, %v) returned nil error, want non-nil", T, test.targs) } - var argErr *ArgumentError - if !errors.As(err, &argErr) { + argErr, ok := errors.AsType[*ArgumentError](err) + if !ok { t.Fatalf("Instantiate(%v, %v): error is not an *ArgumentError", T, test.targs) } @@ -2496,8 +2496,8 @@ func TestArgumentErrorUnwrapping(t *testing.T) { Index: 1, Err: Error{Msg: "test"}, } - var e Error - if !errors.As(err, &e) { + e, ok := errors.AsType[Error](err) + if !ok { t.Fatalf("error %v does not wrap types.Error", err) } if e.Msg != "test" { diff --git a/src/internal/runtime/wasitest/testdata/tcpecho.go b/src/internal/runtime/wasitest/testdata/tcpecho.go index 819e352688..6da56acba1 100644 --- a/src/internal/runtime/wasitest/testdata/tcpecho.go +++ b/src/internal/runtime/wasitest/testdata/tcpecho.go @@ -62,8 +62,7 @@ func findListener() (net.Listener, error) { l, err := net.FileListener(f) f.Close() - var se syscall.Errno - switch errors.As(err, &se); se { + switch se, _ := errors.AsType[syscall.Errno](err); se { case syscall.ENOTSOCK: continue case syscall.EBADF: diff --git a/src/internal/testenv/testenv_unix.go b/src/internal/testenv/testenv_unix.go index a629078842..22eeca220d 100644 --- a/src/internal/testenv/testenv_unix.go +++ b/src/internal/testenv/testenv_unix.go @@ -21,8 +21,7 @@ func syscallIsNotSupported(err error) bool { return false } - var errno syscall.Errno - if errors.As(err, &errno) { + if errno, ok := errors.AsType[syscall.Errno](err); ok { switch errno { case syscall.EPERM, syscall.EROFS: // User lacks permission: either the call requires root permission and the diff --git a/src/io/fs/readdir_test.go b/src/io/fs/readdir_test.go index b89706b893..b729bf27ac 100644 --- a/src/io/fs/readdir_test.go +++ b/src/io/fs/readdir_test.go @@ -93,8 +93,8 @@ func TestFileInfoToDirEntry(t *testing.T) { } func errorPath(err error) string { - var perr *PathError - if !errors.As(err, &perr) { + perr, ok := errors.AsType[*PathError](err) + if !ok { return "" } return perr.Path diff --git a/src/log/log_test.go b/src/log/log_test.go index 8cc05c5e64..5d5d38cc10 100644 --- a/src/log/log_test.go +++ b/src/log/log_test.go @@ -272,8 +272,7 @@ func TestCallDepth(t *testing.T) { cmd.Env = append(cmd.Environ(), envVar+"=1") out, err := cmd.CombinedOutput() - var exitErr *exec.ExitError - if !errors.As(err, &exitErr) { + if _, ok := errors.AsType[*exec.ExitError](err); !ok { t.Fatalf("expected exec.ExitError: %v", err) } diff --git a/src/log/slog/logger_test.go b/src/log/slog/logger_test.go index bf645d9c4c..edacef13a4 100644 --- a/src/log/slog/logger_test.go +++ b/src/log/slog/logger_test.go @@ -303,8 +303,7 @@ func TestCallDepthConnection(t *testing.T) { cmd.Env = append(cmd.Environ(), envVar+"=1") out, err := cmd.CombinedOutput() - var exitErr *exec.ExitError - if !errors.As(err, &exitErr) { + if _, ok := errors.AsType[*exec.ExitError](err); !ok { t.Fatalf("expected exec.ExitError: %v", err) } diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go index 5e060a6b48..940fcccf7f 100644 --- a/src/net/dnsclient_unix.go +++ b/src/net/dnsclient_unix.go @@ -842,8 +842,7 @@ func (r *Resolver) goLookupPTR(ctx context.Context, addr string, order hostLooku } p, server, err := r.lookup(ctx, arpa, dnsmessage.TypePTR, conf) if err != nil { - var dnsErr *DNSError - if errors.As(err, &dnsErr) && dnsErr.IsNotFound { + if dnsErr, ok := errors.AsType[*DNSError](err); ok && dnsErr.IsNotFound { if order == hostLookupDNSFiles { names := lookupStaticAddr(addr) if len(names) > 0 { diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go index 826b4daba1..fc1d40f18b 100644 --- a/src/net/dnsclient_unix_test.go +++ b/src/net/dnsclient_unix_test.go @@ -2627,8 +2627,7 @@ func TestLongDNSNames(t *testing.T) { } expectedErr := DNSError{Err: errNoSuchHost.Error(), Name: v.req, IsNotFound: true} - var dnsErr *DNSError - errors.As(err, &dnsErr) + dnsErr, _ := errors.AsType[*DNSError](err) if dnsErr == nil || *dnsErr != expectedErr { t.Errorf("%v: Lookup%v: unexpected error: %v", i, testName, err) } @@ -2820,8 +2819,7 @@ func TestLookupOrderFilesNoSuchHost(t *testing.T) { } expectedErr := DNSError{Err: errNoSuchHost.Error(), Name: testName, IsNotFound: true} - var dnsErr *DNSError - errors.As(err, &dnsErr) + dnsErr, _ := errors.AsType[*DNSError](err) if dnsErr == nil || *dnsErr != expectedErr { t.Errorf("Lookup%v: unexpected error: %v", v.name, err) } @@ -2853,8 +2851,7 @@ func TestExtendedRCode(t *testing.T) { r := &Resolver{PreferGo: true, Dial: fake.DialContext} _, _, err := r.tryOneName(context.Background(), getSystemDNSConfig(), "go.dev.", dnsmessage.TypeA) - var dnsErr *DNSError - if !(errors.As(err, &dnsErr) && dnsErr.Err == errServerMisbehaving.Error()) { + if dnsErr, ok := errors.AsType[*DNSError](err); !ok || dnsErr.Err != errServerMisbehaving.Error() { t.Fatalf("r.tryOneName(): unexpected error: %v", err) } } diff --git a/src/net/http/h2_error_test.go b/src/net/http/h2_error_test.go index 5e400683b4..e71825451a 100644 --- a/src/net/http/h2_error_test.go +++ b/src/net/http/h2_error_test.go @@ -25,19 +25,18 @@ func (e externalStreamError) Error() string { } func TestStreamError(t *testing.T) { - var target externalStreamError streamErr := http2streamError(42, http2ErrCodeProtocol) - ok := errors.As(streamErr, &target) + extStreamErr, ok := errors.AsType[externalStreamError](streamErr) if !ok { - t.Fatalf("errors.As failed") + t.Fatalf("errors.AsType failed") } - if target.StreamID != streamErr.StreamID { - t.Errorf("got StreamID %v, expected %v", target.StreamID, streamErr.StreamID) + if extStreamErr.StreamID != streamErr.StreamID { + t.Errorf("got StreamID %v, expected %v", extStreamErr.StreamID, streamErr.StreamID) } - if target.Cause != streamErr.Cause { - t.Errorf("got Cause %v, expected %v", target.Cause, streamErr.Cause) + if extStreamErr.Cause != streamErr.Cause { + t.Errorf("got Cause %v, expected %v", extStreamErr.Cause, streamErr.Cause) } - if uint32(target.Code) != uint32(streamErr.Code) { - t.Errorf("got Code %v, expected %v", target.Code, streamErr.Code) + if uint32(extStreamErr.Code) != uint32(streamErr.Code) { + t.Errorf("got Code %v, expected %v", extStreamErr.Code, streamErr.Code) } } diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go index 514cbd098a..2a774100a8 100644 --- a/src/net/lookup_test.go +++ b/src/net/lookup_test.go @@ -1420,8 +1420,8 @@ func testLookupNoData(t *testing.T, prefix string) { return } - var dnsErr *DNSError - if errors.As(err, &dnsErr) { + dnsErr, ok := errors.AsType[*DNSError](err) + if ok { succeeded := true if !dnsErr.IsNotFound { succeeded = false @@ -1455,8 +1455,7 @@ func testLookupNoData(t *testing.T, prefix string) { func TestLookupPortNotFound(t *testing.T) { allResolvers(t, func(t *testing.T) { _, err := LookupPort("udp", "_-unknown-service-") - var dnsErr *DNSError - if !errors.As(err, &dnsErr) || !dnsErr.IsNotFound { + if dnsErr, ok := errors.AsType[*DNSError](err); !ok || !dnsErr.IsNotFound { t.Fatalf("unexpected error: %v", err) } }) @@ -1475,8 +1474,7 @@ var tcpOnlyService = func() string { func TestLookupPortDifferentNetwork(t *testing.T) { allResolvers(t, func(t *testing.T) { _, err := LookupPort("udp", tcpOnlyService) - var dnsErr *DNSError - if !errors.As(err, &dnsErr) || !dnsErr.IsNotFound { + if dnsErr, ok := errors.AsType[*DNSError](err); !ok || !dnsErr.IsNotFound { t.Fatalf("unexpected error: %v", err) } }) diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index 3bded3dea6..1decebdc22 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -1378,8 +1378,8 @@ func TestWaitInterrupt(t *testing.T) { // The child process should be reported as failed, // and the grandchild will exit (or die by SIGPIPE) once the // stderr pipe is closed. - if ee := new(*exec.ExitError); !errors.As(err, ee) { - t.Errorf("Wait error = %v; want %T", err, *ee) + if ee, ok := errors.AsType[*exec.ExitError](err); !ok { + t.Errorf("Wait error = %v; want %T", err, ee) } }) @@ -1423,8 +1423,8 @@ func TestWaitInterrupt(t *testing.T) { // This command ignores SIGINT, sleeping until it is killed. // Wait should return the usual error for a killed process. - if ee := new(*exec.ExitError); !errors.As(err, ee) { - t.Errorf("Wait error = %v; want %T", err, *ee) + if ee, ok := errors.AsType[*exec.ExitError](err); !ok { + t.Errorf("Wait error = %v; want %T", err, ee) } }) @@ -1471,7 +1471,7 @@ func TestWaitInterrupt(t *testing.T) { t.Logf("stderr:\n%s", cmd.Stderr) t.Logf("[%d] %v", cmd.Process.Pid, err) - if ee := new(*exec.ExitError); !errors.As(err, ee) { + if _, ok := errors.AsType[*exec.ExitError](err); !ok { t.Errorf("Wait error = %v; want %v", err, ctx.Err()) } diff --git a/src/os/os_test.go b/src/os/os_test.go index 9f6eb13e1f..536734901b 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -840,8 +840,7 @@ func TestReaddirOfFile(t *testing.T) { if err == nil { t.Error("Readdirnames succeeded; want non-nil error") } - var pe *PathError - if !errors.As(err, &pe) || pe.Path != f.Name() { + if pe, ok := errors.AsType[*PathError](err); !ok || pe.Path != f.Name() { t.Errorf("Readdirnames returned %q; want a PathError with path %q", err, f.Name()) } if len(names) > 0 { diff --git a/src/runtime/pprof/proto_windows.go b/src/runtime/pprof/proto_windows.go index f4dc44bd07..3118e8911e 100644 --- a/src/runtime/pprof/proto_windows.go +++ b/src/runtime/pprof/proto_windows.go @@ -67,8 +67,7 @@ func readMainModuleMapping() (start, end uint64, exe, buildID string, err error) func createModuleSnapshot() (syscall.Handle, error) { for { snap, err := syscall.CreateToolhelp32Snapshot(windows.TH32CS_SNAPMODULE|windows.TH32CS_SNAPMODULE32, uint32(syscall.Getpid())) - var errno syscall.Errno - if err != nil && errors.As(err, &errno) && errno == windows.ERROR_BAD_LENGTH { + if errno, ok := errors.AsType[syscall.Errno](err); ok && errno == windows.ERROR_BAD_LENGTH { // When CreateToolhelp32Snapshot(SNAPMODULE|SNAPMODULE32, ...) fails // with ERROR_BAD_LENGTH then it should be retried until it succeeds. continue diff --git a/src/testing/fstest/testfs.go b/src/testing/fstest/testfs.go index 1fb84b8928..72830a09a7 100644 --- a/src/testing/fstest/testfs.go +++ b/src/testing/fstest/testfs.go @@ -29,7 +29,7 @@ import ( // The contents of fsys must not change concurrently with TestFS. // // If TestFS finds any misbehaviors, it returns either the first error or a -// list of errors. Use [errors.Is] or [errors.As] to inspect. +// list of errors. Use [errors.Is] or [errors.AsType] to inspect. // // Typical usage inside a test is: // diff --git a/src/testing/fstest/testfs_test.go b/src/testing/fstest/testfs_test.go index d6d6d89b89..e3d7f1ab44 100644 --- a/src/testing/fstest/testfs_test.go +++ b/src/testing/fstest/testfs_test.go @@ -105,8 +105,12 @@ func TestTestFSWrappedErrors(t *testing.T) { // TestFS is expected to return a list of errors. // Enforce that the list can be extracted for browsing. - var errs interface{ Unwrap() []error } - if !errors.As(err, &errs) { + type wrapper interface{ + error + Unwrap() []error + } + errs, ok := errors.AsType[wrapper](err) + if !ok { t.Errorf("caller should be able to extract the errors as a list: %#v", err) } else { for _, err := range errs.Unwrap() { diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go index 65440901a0..8665f3ad49 100644 --- a/src/text/template/exec_test.go +++ b/src/text/template/exec_test.go @@ -1015,8 +1015,7 @@ func TestExecError_CustomError(t *testing.T) { var b bytes.Buffer err := tmpl.Execute(&b, nil) - var e *CustomError - if !errors.As(err, &e) { + if _, ok := errors.AsType[*CustomError](err); !ok { t.Fatalf("expected custom error; got %s", err) } } diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go index c28c3ea200..30b3243a5a 100644 --- a/src/text/template/funcs.go +++ b/src/text/template/funcs.go @@ -22,7 +22,7 @@ import ( // return value evaluates to non-nil during execution, execution terminates and // Execute returns that error. // -// Errors returned by Execute wrap the underlying error; call [errors.As] to +// Errors returned by Execute wrap the underlying error; call [errors.AsType] to // unwrap them. // // When template execution invokes a function with an argument list, that list