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: 8aaaa36a5a
GitHub-Pull-Request: golang/go#75698
Reviewed-on: https://go-review.googlesource.com/c/go/+/708495
Auto-Submit: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
Julien Cretel 2025-10-01 20:08:18 +00:00 committed by Gopher Robot
parent 1cd71689f2
commit 6bcd97d9f4
58 changed files with 160 additions and 180 deletions

View file

@ -2468,8 +2468,8 @@ func TestInstantiateErrors(t *testing.T) {
t.Fatalf("Instantiate(%v, %v) returned nil error, want non-nil", T, test.targs) t.Fatalf("Instantiate(%v, %v) returned nil error, want non-nil", T, test.targs)
} }
var argErr *ArgumentError argErr, ok := errors.AsType[*ArgumentError](err)
if !errors.As(err, &argErr) { if !ok {
t.Fatalf("Instantiate(%v, %v): error is not an *ArgumentError", T, test.targs) t.Fatalf("Instantiate(%v, %v): error is not an *ArgumentError", T, test.targs)
} }
@ -2484,8 +2484,8 @@ func TestArgumentErrorUnwrapping(t *testing.T) {
Index: 1, Index: 1,
Err: Error{Msg: "test"}, Err: Error{Msg: "test"},
} }
var e Error e, ok := errors.AsType[Error](err)
if !errors.As(err, &e) { if !ok {
t.Fatalf("error %v does not wrap types.Error", err) t.Fatalf("error %v does not wrap types.Error", err)
} }
if e.Msg != "test" { if e.Msg != "test" {

View file

@ -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. // ShortPathError rewrites the path in err using base.ShortPath, if err is a wrapped PathError.
func ShortPathError(err error) error { func ShortPathError(err error) error {
var pe *fs.PathError if pe, ok := errors.AsType[*fs.PathError](err); ok {
if errors.As(err, &pe) {
pe.Path = ShortPath(pe.Path) pe.Path = ShortPath(pe.Path)
} }
return err return err

View file

@ -81,8 +81,7 @@ func doPkgsite(urlPath, fragment string) error {
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
var ee *exec.ExitError if ee, ok := errors.AsType[*exec.ExitError](err); ok {
if errors.As(err, &ee) {
// Exit with the same exit status as pkgsite to avoid // Exit with the same exit status as pkgsite to avoid
// printing of "exit status" error messages. // printing of "exit status" error messages.
// Any relevant messages have already been printed // Any relevant messages have already been printed

View file

@ -68,11 +68,10 @@ func runFmt(ctx context.Context, cmd *base.Command, args []string) {
continue continue
} }
if pkg.Error != nil { if pkg.Error != nil {
var nogo *load.NoGoError if _, ok := errors.AsType[*load.NoGoError](pkg.Error); ok {
var embed *load.EmbedError // Skip this error, as we will format all files regardless.
if (errors.As(pkg.Error, &nogo) || errors.As(pkg.Error, &embed)) && len(pkg.InternalAllGoFiles()) > 0 { } else if _, ok := errors.AsType[*load.EmbedError](pkg.Error); ok && len(pkg.InternalAllGoFiles()) > 0 {
// Skip this error, as we will format // Skip this error, as we will format all files regardless.
// all files regardless.
} else { } else {
base.Errorf("%v", pkg.Error) base.Errorf("%v", pkg.Error)
continue continue

View file

@ -290,8 +290,8 @@ func (p *Package) setLoadPackageDataError(err error, path string, stk *ImportSta
// Replace (possibly wrapped) *build.NoGoError with *load.NoGoError. // Replace (possibly wrapped) *build.NoGoError with *load.NoGoError.
// The latter is more specific about the cause. // The latter is more specific about the cause.
var nogoErr *build.NoGoError nogoErr, ok := errors.AsType[*build.NoGoError](err)
if errors.As(err, &nogoErr) { if ok {
if p.Dir == "" && nogoErr.Dir != "" { if p.Dir == "" && nogoErr.Dir != "" {
p.Dir = nogoErr.Dir p.Dir = nogoErr.Dir
} }

View file

@ -1294,15 +1294,13 @@ func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPack
continue continue
} }
var ( if _, ok := errors.AsType[*modload.ImportMissingError](err); !ok {
importMissing *modload.ImportMissingError if _, ok := errors.AsType[*modload.AmbiguousImportError](err); !ok {
ambiguous *modload.AmbiguousImportError // The package, which is a dependency of something we care about, has some
) // problem that we can't resolve with a version change.
if !errors.As(err, &importMissing) && !errors.As(err, &ambiguous) { // Leave the error for the final LoadPackages call.
// The package, which is a dependency of something we care about, has some continue
// problem that we can't resolve with a version change. }
// Leave the error for the final LoadPackages call.
continue
} }
path := pkgPath path := pkgPath
@ -1674,7 +1672,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin
} }
base.SetExitStatus(1) 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 { for _, m := range ambiguousErr.Modules {
relevantMods[m] |= hasPkg relevantMods[m] |= hasPkg
} }
@ -1717,7 +1715,7 @@ func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []strin
i := i i := i
r.work.Add(func() { r.work.Add(func() {
err := modload.CheckRetractions(ctx, retractions[i].m) 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() retractions[i].message = err.Error()
} }
}) })
@ -1994,8 +1992,8 @@ func (r *resolver) updateBuildList(ctx context.Context, additions []module.Versi
toolchain.SwitchOrFatal(ctx, err) toolchain.SwitchOrFatal(ctx, err)
} }
var constraint *modload.ConstraintError constraint, ok := errors.AsType[*modload.ConstraintError](err)
if !errors.As(err, &constraint) { if !ok {
base.Fatal(err) 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 // 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. // exist at all or because it does not include that specific version.
func isNoSuchModuleVersion(err error) bool { func isNoSuchModuleVersion(err error) bool {
var noMatch *modload.NoMatchingVersionError if errors.Is(err, os.ErrNotExist) {
return errors.Is(err, os.ErrNotExist) || errors.As(err, &noMatch) return true
}
_, ok := errors.AsType[*modload.NoMatchingVersionError](err)
return ok
} }
// isNoSuchPackageVersion reports whether err indicates that the requested // 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 could contain it exists at that version, or because every such module
// that does exist does not actually contain the package. // that does exist does not actually contain the package.
func isNoSuchPackageVersion(err error) bool { func isNoSuchPackageVersion(err error) bool {
var noPackage *modload.PackageNotInModuleError if isNoSuchModuleVersion(err) {
return isNoSuchModuleVersion(err) || errors.As(err, &noPackage) return true
}
_, ok := errors.AsType[*modload.PackageNotInModuleError](err)
return ok
} }
// workspace represents the set of modules in a workspace. // workspace represents the set of modules in a workspace.

View file

@ -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 // If err already mentions all of the relevant parts of q, just log err to
// reduce stutter. Otherwise, log both q and err. // 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. // strings with regular expressions.
if !utf8.ValidString(q.pattern) || !utf8.ValidString(q.version) { if !utf8.ValidString(q.pattern) || !utf8.ValidString(q.version) {

View file

@ -129,11 +129,10 @@ func addUpdate(ctx context.Context, m *modinfo.ModulePublic) {
} }
info, err := Query(ctx, m.Path, "upgrade", m.Version, CheckAllowed) info, err := Query(ctx, m.Path, "upgrade", m.Version, CheckAllowed)
var noVersionErr *NoMatchingVersionError if _, ok := errors.AsType[*NoMatchingVersionError](err); ok ||
if errors.Is(err, ErrDisallowed) ||
errors.Is(err, fs.ErrNotExist) || errors.Is(err, fs.ErrNotExist) ||
errors.As(err, &noVersionErr) { errors.Is(err, ErrDisallowed) {
// Ignore "not found" and "no matching version" errors. // Ignore "no matching version" and "not found" errors.
// This means the proxy has no matching version or no versions at all. // This means the proxy has no matching version or no versions at all.
// //
// Ignore "disallowed" errors. This means the current version is // 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}) err := CheckRetractions(ctx, module.Version{Path: m.Path, Version: m.Version})
var noVersionErr *NoMatchingVersionError if err == nil {
var retractErr *ModuleRetractedError return
if err == nil || errors.Is(err, fs.ErrNotExist) || errors.As(err, &noVersionErr) { } else if _, ok := errors.AsType[*NoMatchingVersionError](err); ok || errors.Is(err, fs.ErrNotExist) {
// Ignore "not found" and "no matching version" errors. // Ignore "no matching version" and "not found" errors.
// This means the proxy has no matching version or no versions at all. // This means the proxy has no matching version or no versions at all.
// //
// We should report other errors though. An attacker that controls the // 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 // hide versions, since the "list" and "latest" endpoints are not
// authenticated. // authenticated.
return return
} else if errors.As(err, &retractErr) { } else if retractErr, ok := errors.AsType[*ModuleRetractedError](err); ok {
if len(retractErr.Rationale) == 0 { if len(retractErr.Rationale) == 0 {
m.Retracted = []string{"retracted by module author"} m.Retracted = []string{"retracted by module author"}
} else { } 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. // author. m.Error is set if there's an error loading deprecation information.
func addDeprecation(ctx context.Context, m *modinfo.ModulePublic) { func addDeprecation(ctx context.Context, m *modinfo.ModulePublic) {
deprecation, err := CheckDeprecation(ctx, module.Version{Path: m.Path, Version: m.Version}) deprecation, err := CheckDeprecation(ctx, module.Version{Path: m.Path, Version: m.Version})
var noVersionErr *NoMatchingVersionError if _, ok := errors.AsType[*NoMatchingVersionError](err); ok || errors.Is(err, fs.ErrNotExist) {
if errors.Is(err, fs.ErrNotExist) || errors.As(err, &noVersionErr) { // Ignore "no matching version" and "not found" errors.
// Ignore "not found" and "no matching version" errors.
// This means the proxy has no matching version or no versions at all. // This means the proxy has no matching version or no versions at all.
// //
// We should report other errors though. An attacker that controls the // We should report other errors though. An attacker that controls the

View file

@ -922,7 +922,7 @@ func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requir
q.Add(func() { q.Add(func() {
skipModFile := true skipModFile := true
_, _, _, _, err := importFromModules(ctx, pkg.path, tidy, nil, skipModFile) _, _, _, _, 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) disambiguateRoot.Store(pkg.mod, true)
} }
}) })

View file

@ -226,8 +226,10 @@ func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSel
// conflict we discover from one or more of the original roots. // conflict we discover from one or more of the original roots.
mg, upgradedRoots, err := extendGraph(ctx, rootPruning, roots, selectedRoot) mg, upgradedRoots, err := extendGraph(ctx, rootPruning, roots, selectedRoot)
if err != nil { if err != nil {
var tooNew *gover.TooNewError if mg == nil {
if mg == nil || errors.As(err, &tooNew) { return orig, false, err
}
if _, ok := errors.AsType[*gover.TooNewError](err); ok {
return orig, false, err return orig, false, err
} }
// We're about to walk the entire extended module graph, so we will find // We're about to walk the entire extended module graph, so we will find

View file

@ -410,7 +410,7 @@ func importFromModules(ctx context.Context, path string, rs *Requirements, mg *M
root, isLocal, err := fetch(ctx, m) root, isLocal, err := fetch(ctx, m)
if err != nil { 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 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 // 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 // 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 { for _, m := range mods {
root, isLocal, err := fetch(ctx, m) root, isLocal, err := fetch(ctx, m)
if err != nil { 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{}, &ImportMissingSumError{importPath: path}
} }
return module.Version{}, err return module.Version{}, err

View file

@ -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 // modinfoError wraps an error to create an error message in
// modinfo.ModuleError with minimal redundancy. // modinfo.ModuleError with minimal redundancy.
func modinfoError(path, vers string, err error) *modinfo.ModuleError { func modinfoError(path, vers string, err error) *modinfo.ModuleError {
var nerr *NoMatchingVersionError if _, ok := errors.AsType[*NoMatchingVersionError](err); ok {
var merr *module.ModuleError
if errors.As(err, &nerr) {
// NoMatchingVersionError contains the query, so we don't mention the // NoMatchingVersionError contains the query, so we don't mention the
// query again in ModuleError. // query again in ModuleError.
err = &module.ModuleError{Path: path, Err: err} 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 // If the error does not contain path and version, wrap it in a
// module.ModuleError. // module.ModuleError.
err = &module.ModuleError{Path: path, Version: vers, Err: err} err = &module.ModuleError{Path: path, Version: vers, Err: err}

View file

@ -1304,7 +1304,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
} }
// Add importer information to checksum errors. // 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 { if importer := pkg.stack; importer != nil {
sumErr.importer = importer.path sumErr.importer = importer.path
sumErr.importerVersion = importer.mod.Version 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 // Add importer go version information to import errors of standard
// library packages arising from newer releases. // library packages arising from newer releases.
if importer := pkg.stack; importer != nil { 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 var maxTooNew *gover.TooNewError
for _, pkg := range ld.pkgs { for _, pkg := range ld.pkgs {
if pkg.err != nil { 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 { if maxTooNew == nil || gover.Compare(tooNew.GoVersion, maxTooNew.GoVersion) > 0 {
maxTooNew = tooNew maxTooNew = tooNew
} }
@ -1573,7 +1573,7 @@ func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[mod
// we should only add the missing import once. // we should only add the missing import once.
continue 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. // Leave other errors for Import or load.Packages to report.
continue continue
} }
@ -1584,8 +1584,7 @@ func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[mod
var err error var err error
mod, err = queryImport(ctx, pkg.path, ld.requirements) mod, err = queryImport(ctx, pkg.path, ld.requirements)
if err != nil { if err != nil {
var ime *ImportMissingError if ime, ok := errors.AsType[*ImportMissingError](err); ok {
if errors.As(err, &ime) {
for curstack := pkg.stack; curstack != nil; curstack = curstack.stack { for curstack := pkg.stack; curstack != nil; curstack = curstack.stack {
if LoaderState.MainModules.Contains(curstack.mod.Path) { if LoaderState.MainModules.Contains(curstack.mod.Path) {
ime.ImportingMainModule = curstack.mod ime.ImportingMainModule = curstack.mod
@ -1625,7 +1624,7 @@ func (ld *loader) resolveMissingImports(ctx context.Context) (modAddedBy map[mod
maxTooNewPkg *loadPkg maxTooNewPkg *loadPkg
) )
for _, pm := range pkgMods { 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 { if maxTooNew == nil || gover.Compare(tooNew.GoVersion, maxTooNew.GoVersion) > 0 {
maxTooNew = tooNew maxTooNew = tooNew
maxTooNewPkg = pm.pkg maxTooNewPkg = pm.pkg
@ -1771,8 +1770,7 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch
// full module graph. // full module graph.
m, _, _, _, err := importFromModules(ctx, path, ld.requirements, nil, ld.skipImportModFiles) m, _, _, _, err := importFromModules(ctx, path, ld.requirements, nil, ld.skipImportModFiles)
if err != nil { if err != nil {
var missing *ImportMissingError if _, ok := errors.AsType[*ImportMissingError](err); ok && ld.ResolveMissingImports {
if errors.As(err, &missing) && ld.ResolveMissingImports {
// This package isn't provided by any selected module. // This package isn't provided by any selected module.
// If we can find it, it will be a new root dependency. // If we can find it, it will be a new root dependency.
m, err = queryImport(ctx, path, ld.requirements) 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 // module that previously provided the package to a version that no
// longer does, or to a version for which the module source code (but // longer does, or to a version for which the module source code (but
// not the go.mod file in isolation) has a checksum error. // 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{ selected := module.Version{
Path: pkg.mod.Path, Path: pkg.mod.Path,
Version: mg.Selected(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)) 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 { } else {
if ambiguous := (*AmbiguousImportError)(nil); errors.As(mismatch.err, &ambiguous) { if _, ok := errors.AsType[*AmbiguousImportError](mismatch.err); ok {
// TODO: Is this check needed? // 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)) 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))

View file

@ -76,8 +76,7 @@ func ReadModFile(gomod string, fix modfile.VersionFixer) (data []byte, f *modfil
} }
func shortPathErrorList(err error) error { func shortPathErrorList(err error) error {
var el modfile.ErrorList if el, ok := errors.AsType[modfile.ErrorList](err); ok {
if errors.As(err, &el) {
for i := range el { for i := range el {
el[i].Filename = base.ShortPath(el[i].Filename) el[i].Filename = base.ShortPath(el[i].Filename)
} }
@ -175,12 +174,15 @@ func (e *excludedError) Is(err error) bool { return err == ErrDisallowed }
// its author. // its author.
func CheckRetractions(ctx context.Context, m module.Version) (err error) { func CheckRetractions(ctx context.Context, m module.Version) (err error) {
defer func() { defer func() {
if retractErr := (*ModuleRetractedError)(nil); err == nil || errors.As(err, &retractErr) { if err == nil {
return
}
if _, ok := errors.AsType[*ModuleRetractedError](err); ok {
return return
} }
// Attribute the error to the version being checked, not the version from // Attribute the error to the version being checked, not the version from
// which the retractions were to be loaded. // 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 = mErr.Err
} }
err = &retractionLoadingError{m: m, err: err} err = &retractionLoadingError{m: m, err: err}

View file

@ -932,7 +932,7 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod
if notExistErr == nil { if notExistErr == nil {
notExistErr = rErr notExistErr = rErr
} }
} else if iv := (*module.InvalidVersionError)(nil); errors.As(rErr, &iv) { } else if _, ok := errors.AsType[*module.InvalidVersionError](rErr); ok {
if invalidVersion == nil { if invalidVersion == nil {
invalidVersion = rErr invalidVersion = rErr
} }

View file

@ -1741,8 +1741,7 @@ func (r *runTestActor) Act(b *work.Builder, ctx context.Context, a *work.Action)
} else if errors.Is(err, exec.ErrWaitDelay) { } else if errors.Is(err, exec.ErrWaitDelay) {
fmt.Fprintf(cmd.Stdout, "*** Test I/O incomplete %v after exiting.\n", cmd.WaitDelay) fmt.Fprintf(cmd.Stdout, "*** Test I/O incomplete %v after exiting.\n", cmd.WaitDelay)
} }
var ee *exec.ExitError if ee, ok := errors.AsType[*exec.ExitError](err); !ok || !ee.Exited() || len(out) == 0 {
if len(out) == 0 || !errors.As(err, &ee) || !ee.Exited() {
// If there was no test output, print the exit status so that the reason // If there was no test output, print the exit status so that the reason
// for failure is clear. // for failure is clear.
fmt.Fprintf(cmd.Stdout, "%s\n", err) fmt.Fprintf(cmd.Stdout, "%s\n", err)

View file

@ -261,7 +261,7 @@ func testFlags(args []string) (packageNames, passToTest []string) {
break break
} }
if nf := (cmdflag.NonFlagError{}); errors.As(err, &nf) { if nf, ok := errors.AsType[cmdflag.NonFlagError](err); ok {
if !inPkgList && packageNames != nil { if !inPkgList && packageNames != nil {
// We already saw the package list previously, and this argument is not // 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 // 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 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 // 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 // after this might be flag arguments, not package names, so make
// packageNames non-nil to indicate that the package list is complete. // packageNames non-nil to indicate that the package list is complete.

View file

@ -155,10 +155,10 @@ func TestScripts(t *testing.T) {
t.Log(buf) t.Log(buf)
} }
if err != nil { if err != nil {
if notInstalled := (vcweb.ServerNotInstalledError{}); errors.As(err, &notInstalled) || errors.Is(err, exec.ErrNotFound) { if _, ok := errors.AsType[vcweb.ServerNotInstalledError](err); ok || errors.Is(err, exec.ErrNotFound) {
t.Skip(err) t.Skip(err)
} }
if skip := (vcweb.SkipError{}); errors.As(err, &skip) { if skip, ok := errors.AsType[vcweb.SkipError](err); ok {
if skip.Msg == "" { if skip.Msg == "" {
t.Skip("SKIP") t.Skip("SKIP")
} else { } else {

View file

@ -244,9 +244,9 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}) })
if err != nil { if err != nil {
s.logger.Print(err) s.logger.Print(err)
if notFound := (ScriptNotFoundError{}); errors.As(err, &notFound) { if _, ok := errors.AsType[ScriptNotFoundError](err); ok {
http.NotFound(w, req) http.NotFound(w, req)
} else if notInstalled := (ServerNotInstalledError{}); errors.As(err, &notInstalled) || 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) http.Error(w, err.Error(), http.StatusNotImplemented)
} else { } else {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)

View file

@ -168,7 +168,7 @@ func scanFile(file string, info fs.FileInfo, mustPrint bool) bool {
bi, err := buildinfo.ReadFile(file) bi, err := buildinfo.ReadFile(file)
if err != nil { if err != nil {
if mustPrint { 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) fmt.Fprintf(os.Stderr, "%v\n", file)
} else { } else {
// Skip errors for non-Go binaries. // Skip errors for non-Go binaries.

View file

@ -160,7 +160,7 @@ func toolFlags(cmd *base.Command, args []string) (passToTool, packageNames []str
break 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 — // Everything from here on out — including the argument we just consumed —
// must be a package name. // must be a package name.
packageNames = args packageNames = args

View file

@ -705,7 +705,7 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) {
continue continue
} }
haveErrors = true haveErrors = true
if missingErr := (*modload.ImportMissingError)(nil); !errors.As(pkg.Error, &missingErr) { if _, ok := errors.AsType[*modload.ImportMissingError](pkg.Error); !ok {
allMissingErrors = false allMissingErrors = false
break break
} }

View file

@ -169,9 +169,10 @@ func (b *Builder) Do(ctx context.Context, root *Action) {
a.Package.Incomplete = true a.Package.Incomplete = true
} }
} else { } else {
var ipe load.ImportPathError if a.Package != nil {
if a.Package != nil && (!errors.As(err, &ipe) || ipe.ImportPath() != a.Package.ImportPath) { if ipe, ok := errors.AsType[load.ImportPathError](err); !ok || ipe.ImportPath() != a.Package.ImportPath {
err = fmt.Errorf("%s: %v", a.Package.ImportPath, err) err = fmt.Errorf("%s: %v", a.Package.ImportPath, err)
}
} }
sh := b.Shell(a) sh := b.Shell(a)
sh.Errorf("%s", err) sh.Errorf("%s", err)

View file

@ -97,7 +97,7 @@ func runCmd(t *testing.T, dir string, env []string, path string, args ...string)
cmd.Env = env cmd.Env = env
out, err := cmd.Output() out, err := cmd.Output()
if err != nil { 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...) out = append(out, ee.Stderr...)
} }
t.Fatalf("%s failed:\n%s\n%s", cmd, out, err) t.Fatalf("%s failed:\n%s\n%s", cmd, out, err)

View file

@ -13,9 +13,6 @@ const errFileNotFound = syscall.ENOENT
// isEphemeralError returns true if err may be resolved by waiting. // isEphemeralError returns true if err may be resolved by waiting.
func isEphemeralError(err error) bool { func isEphemeralError(err error) bool {
var errno syscall.Errno errno, ok := errors.AsType[syscall.Errno](err)
if errors.As(err, &errno) { return ok && errno == errFileNotFound
return errno == errFileNotFound
}
return false
} }

View file

@ -31,8 +31,7 @@ func retry(f func() (err error, mayRetry bool)) error {
return err return err
} }
var errno syscall.Errno if errno, ok := errors.AsType[syscall.Errno](err); ok && (lowestErrno == 0 || errno < lowestErrno) {
if errors.As(err, &errno) && (lowestErrno == 0 || errno < lowestErrno) {
bestErr = err bestErr = err
lowestErrno = errno lowestErrno = errno
} else if bestErr == nil { } else if bestErr == nil {

View file

@ -14,8 +14,7 @@ const errFileNotFound = syscall.ERROR_FILE_NOT_FOUND
// isEphemeralError returns true if err may be resolved by waiting. // isEphemeralError returns true if err may be resolved by waiting.
func isEphemeralError(err error) bool { func isEphemeralError(err error) bool {
var errno syscall.Errno if errno, ok := errors.AsType[syscall.Errno](err); ok {
if errors.As(err, &errno) {
switch errno { switch errno {
case syscall.ERROR_ACCESS_DENIED, case syscall.ERROR_ACCESS_DENIED,
syscall.ERROR_FILE_NOT_FOUND, syscall.ERROR_FILE_NOT_FOUND,

View file

@ -185,7 +185,7 @@ func (e *Engine) Execute(s *State, file string, script *bufio.Reader, log io.Wri
var lineno int var lineno int
lineErr := func(err error) error { lineErr := func(err error) error {
if errors.As(err, new(*CommandError)) { if _, ok := errors.AsType[*CommandError](err); ok {
return err return err
} }
return fmt.Errorf("%s:%d: %w", file, lineno, 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. // Run the command.
err = e.runCommand(s, cmd, impl) err = e.runCommand(s, cmd, impl)
if err != nil { 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, // Since the 'stop' command halts execution of the entire script,
// log its message separately from the section in which it appears. // log its message separately from the section in which it appears.
err = endSection(true) err = endSection(true)
@ -607,13 +607,13 @@ func checkStatus(cmd *command, err error) error {
return nil return nil
} }
if s := (stopError{}); errors.As(err, &s) { if _, ok := errors.AsType[stopError](err); ok {
// This error originated in the Stop command. // This error originated in the Stop command.
// Propagate it as-is. // Propagate it as-is.
return cmdError(cmd, err) 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. // 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. // 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 // (Wait itself cannot fail to wait on commands or else it would leak

View file

@ -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) 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 == "" { if skip.msg == "" {
t.Skip("SKIP") t.Skip("SKIP")
} else { } else {

View file

@ -1532,11 +1532,13 @@ func TestFlagS(t *testing.T) {
} }
cmd = testenv.Command(t, testenv.GoToolPath(t), "tool", "nm", exe) cmd = testenv.Command(t, testenv.GoToolPath(t), "tool", "nm", exe)
out, err = cmd.CombinedOutput() out, err = cmd.CombinedOutput()
if err != nil && !errors.As(err, new(*exec.ExitError)) { if err != nil {
// Error exit is fine as it may have no symbols. if _, ok := errors.AsType[*exec.ExitError](err); !ok {
// On darwin we need to emit dynamic symbol references so it // Error exit is fine as it may have no symbols.
// actually has some symbols, and nm succeeds. // On darwin we need to emit dynamic symbol references so it
t.Errorf("(mode=%s) go tool nm failed: %v\n%s", mode, err, out) // 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 { for _, s := range syms {
if bytes.Contains(out, []byte(s)) { if bytes.Contains(out, []byte(s)) {

View file

@ -1578,9 +1578,9 @@ func (c *Conn) handshakeContext(ctx context.Context) (ret error) {
// the handshake (RFC 9001, Section 5.7). // the handshake (RFC 9001, Section 5.7).
c.quicSetReadSecret(QUICEncryptionLevelApplication, c.cipherSuite, c.in.trafficSecret) c.quicSetReadSecret(QUICEncryptionLevelApplication, c.cipherSuite, c.in.trafficSecret)
} else { } else {
var a alert
c.out.Lock() c.out.Lock()
if !errors.As(c.out.err, &a) { a, ok := errors.AsType[alert](c.out.err)
if !ok {
a = alertInternalError a = alertInternalError
} }
c.out.Unlock() c.out.Unlock()

View file

@ -965,10 +965,9 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error {
chains, err := certs[0].Verify(opts) chains, err := certs[0].Verify(opts)
if err != nil { if err != nil {
var errCertificateInvalid x509.CertificateInvalidError if _, ok := errors.AsType[x509.UnknownAuthorityError](err); ok {
if errors.As(err, &x509.UnknownAuthorityError{}) {
c.sendAlert(alertUnknownCA) 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) c.sendAlert(alertCertificateExpired)
} else { } else {
c.sendAlert(alertBadCertificate) c.sendAlert(alertBadCertificate)

View file

@ -403,8 +403,7 @@ func TestAlertForwarding(t *testing.T) {
err := Server(s, testConfig).Handshake() err := Server(s, testConfig).Handshake()
s.Close() s.Close()
var opErr *net.OpError if opErr, ok := errors.AsType[*net.OpError](err); !ok || opErr.Err != error(alertUnknownCA) {
if !errors.As(err, &opErr) || opErr.Err != error(alertUnknownCA) {
t.Errorf("Got error: %s; expected: %s", err, error(alertUnknownCA)) t.Errorf("Got error: %s; expected: %s", err, error(alertUnknownCA))
} }
} }

View file

@ -362,12 +362,11 @@ func quicError(err error) error {
if err == nil { if err == nil {
return nil return nil
} }
var ae AlertError if _, ok := errors.AsType[AlertError](err); ok {
if errors.As(err, &ae) {
return err return err
} }
var a alert a, ok := errors.AsType[alert](err)
if !errors.As(err, &a) { if !ok {
a = alertInternalError a = alertInternalError
} }
// Return an error wrapping the original error and an AlertError. // Return an error wrapping the original error and an AlertError.

View file

@ -368,8 +368,7 @@ func TestQUICHandshakeError(t *testing.T) {
if !errors.Is(err, AlertError(alertBadCertificate)) { if !errors.Is(err, AlertError(alertBadCertificate)) {
t.Errorf("connection handshake terminated with error %q, want alertBadCertificate", err) t.Errorf("connection handshake terminated with error %q, want alertBadCertificate", err)
} }
var e *CertificateVerificationError if _, ok := errors.AsType[*CertificateVerificationError](err); !ok {
if !errors.As(err, &e) {
t.Errorf("connection handshake terminated with error %q, want CertificateVerificationError", err) t.Errorf("connection handshake terminated with error %q, want CertificateVerificationError", err)
} }
} }

View file

@ -67,7 +67,7 @@ const (
// with module support. // with module support.
func ReadFile(name string) (info *BuildInfo, err error) { func ReadFile(name string) (info *BuildInfo, err error) {
defer func() { 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) err = fmt.Errorf("could not read Go build info: %w", err)
} else if err != nil { } else if err != nil {
err = fmt.Errorf("could not read Go build info from %s: %w", name, err) err = fmt.Errorf("could not read Go build info from %s: %w", name, err)

View file

@ -486,7 +486,7 @@ func testCoderInterleaved(t *testing.T, where jsontest.CasePos, modeName string,
// Retry as a ReadToken call. // Retry as a ReadToken call.
expectError := dec.PeekKind() == '}' || dec.PeekKind() == ']' expectError := dec.PeekKind() == '}' || dec.PeekKind() == ']'
if expectError { 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)) t.Fatalf("%s: Decoder.ReadToken error is %T, want %T", where, err, new(SyntacticError))
} }
tickTock = !tickTock tickTock = !tickTock

View file

@ -53,9 +53,10 @@ func FuzzCoder(f *testing.F) {
} else { } else {
val, err := dec.ReadValue() val, err := dec.ReadValue()
if err != nil { if err != nil {
expectError := dec.PeekKind() == '}' || dec.PeekKind() == ']' if expectError := dec.PeekKind() == '}' || dec.PeekKind() == ']'; expectError {
if expectError && errors.As(err, new(*SyntacticError)) { if _, ok := errors.AsType[*SyntacticError](err); ok {
continue continue
}
} }
if err == io.EOF { if err == io.EOF {
break break

View file

@ -24,8 +24,7 @@ import (
// The name of a duplicate JSON object member can be extracted as: // The name of a duplicate JSON object member can be extracted as:
// //
// err := ... // err := ...
// var serr jsontext.SyntacticError // if serr, ok := errors.AsType[jsontext.SyntacticError](err); ok && serr.Err == jsontext.ErrDuplicateName {
// if errors.As(err, &serr) && serr.Err == jsontext.ErrDuplicateName {
// ptr := serr.JSONPointer // JSON pointer to duplicate name // ptr := serr.JSONPointer // JSON pointer to duplicate name
// name := ptr.LastToken() // duplicate name itself // name := ptr.LastToken() // duplicate name itself
// ... // ...

View file

@ -28,8 +28,7 @@ import (
// The name of an unknown JSON object member can be extracted as: // The name of an unknown JSON object member can be extracted as:
// //
// err := ... // err := ...
// var serr json.SemanticError // if serr, ok := errors.AsType[json.SemanticError](err); ok && serr.Err == json.ErrUnknownName {
// if errors.As(err, &serr) && serr.Err == json.ErrUnknownName {
// ptr := serr.JSONPointer // JSON pointer to unknown name // ptr := serr.JSONPointer // JSON pointer to unknown name
// name := ptr.LastToken() // unknown name itself // name := ptr.LastToken() // unknown name itself
// ... // ...

View file

@ -371,8 +371,7 @@ func Example_unknownMembers() {
// Specifying RejectUnknownMembers causes Unmarshal // Specifying RejectUnknownMembers causes Unmarshal
// to reject the presence of any unknown members. // to reject the presence of any unknown members.
err = json.Unmarshal([]byte(input), new(Color), json.RejectUnknownMembers(true)) err = json.Unmarshal([]byte(input), new(Color), json.RejectUnknownMembers(true))
var serr *json.SemanticError if serr, ok := errors.AsType[*json.SemanticError](err); ok && serr.Err == json.ErrUnknownName {
if errors.As(err, &serr) && serr.Err == json.ErrUnknownName {
fmt.Println("Unmarshal error:", serr.Err, strconv.Quote(serr.JSONPointer.LastToken())) fmt.Println("Unmarshal error:", serr.Err, strconv.Quote(serr.JSONPointer.LastToken()))
} }

View file

@ -2480,8 +2480,8 @@ func TestInstantiateErrors(t *testing.T) {
t.Fatalf("Instantiate(%v, %v) returned nil error, want non-nil", T, test.targs) t.Fatalf("Instantiate(%v, %v) returned nil error, want non-nil", T, test.targs)
} }
var argErr *ArgumentError argErr, ok := errors.AsType[*ArgumentError](err)
if !errors.As(err, &argErr) { if !ok {
t.Fatalf("Instantiate(%v, %v): error is not an *ArgumentError", T, test.targs) t.Fatalf("Instantiate(%v, %v): error is not an *ArgumentError", T, test.targs)
} }
@ -2496,8 +2496,8 @@ func TestArgumentErrorUnwrapping(t *testing.T) {
Index: 1, Index: 1,
Err: Error{Msg: "test"}, Err: Error{Msg: "test"},
} }
var e Error e, ok := errors.AsType[Error](err)
if !errors.As(err, &e) { if !ok {
t.Fatalf("error %v does not wrap types.Error", err) t.Fatalf("error %v does not wrap types.Error", err)
} }
if e.Msg != "test" { if e.Msg != "test" {

View file

@ -62,8 +62,7 @@ func findListener() (net.Listener, error) {
l, err := net.FileListener(f) l, err := net.FileListener(f)
f.Close() f.Close()
var se syscall.Errno switch se, _ := errors.AsType[syscall.Errno](err); se {
switch errors.As(err, &se); se {
case syscall.ENOTSOCK: case syscall.ENOTSOCK:
continue continue
case syscall.EBADF: case syscall.EBADF:

View file

@ -21,8 +21,7 @@ func syscallIsNotSupported(err error) bool {
return false return false
} }
var errno syscall.Errno if errno, ok := errors.AsType[syscall.Errno](err); ok {
if errors.As(err, &errno) {
switch errno { switch errno {
case syscall.EPERM, syscall.EROFS: case syscall.EPERM, syscall.EROFS:
// User lacks permission: either the call requires root permission and the // User lacks permission: either the call requires root permission and the

View file

@ -93,8 +93,8 @@ func TestFileInfoToDirEntry(t *testing.T) {
} }
func errorPath(err error) string { func errorPath(err error) string {
var perr *PathError perr, ok := errors.AsType[*PathError](err)
if !errors.As(err, &perr) { if !ok {
return "" return ""
} }
return perr.Path return perr.Path

View file

@ -272,8 +272,7 @@ func TestCallDepth(t *testing.T) {
cmd.Env = append(cmd.Environ(), envVar+"=1") cmd.Env = append(cmd.Environ(), envVar+"=1")
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
var exitErr *exec.ExitError if _, ok := errors.AsType[*exec.ExitError](err); !ok {
if !errors.As(err, &exitErr) {
t.Fatalf("expected exec.ExitError: %v", err) t.Fatalf("expected exec.ExitError: %v", err)
} }

View file

@ -303,8 +303,7 @@ func TestCallDepthConnection(t *testing.T) {
cmd.Env = append(cmd.Environ(), envVar+"=1") cmd.Env = append(cmd.Environ(), envVar+"=1")
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
var exitErr *exec.ExitError if _, ok := errors.AsType[*exec.ExitError](err); !ok {
if !errors.As(err, &exitErr) {
t.Fatalf("expected exec.ExitError: %v", err) t.Fatalf("expected exec.ExitError: %v", err)
} }

View file

@ -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) p, server, err := r.lookup(ctx, arpa, dnsmessage.TypePTR, conf)
if err != nil { if err != nil {
var dnsErr *DNSError if dnsErr, ok := errors.AsType[*DNSError](err); ok && dnsErr.IsNotFound {
if errors.As(err, &dnsErr) && dnsErr.IsNotFound {
if order == hostLookupDNSFiles { if order == hostLookupDNSFiles {
names := lookupStaticAddr(addr) names := lookupStaticAddr(addr)
if len(names) > 0 { if len(names) > 0 {

View file

@ -2627,8 +2627,7 @@ func TestLongDNSNames(t *testing.T) {
} }
expectedErr := DNSError{Err: errNoSuchHost.Error(), Name: v.req, IsNotFound: true} expectedErr := DNSError{Err: errNoSuchHost.Error(), Name: v.req, IsNotFound: true}
var dnsErr *DNSError dnsErr, _ := errors.AsType[*DNSError](err)
errors.As(err, &dnsErr)
if dnsErr == nil || *dnsErr != expectedErr { if dnsErr == nil || *dnsErr != expectedErr {
t.Errorf("%v: Lookup%v: unexpected error: %v", i, testName, err) 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} expectedErr := DNSError{Err: errNoSuchHost.Error(), Name: testName, IsNotFound: true}
var dnsErr *DNSError dnsErr, _ := errors.AsType[*DNSError](err)
errors.As(err, &dnsErr)
if dnsErr == nil || *dnsErr != expectedErr { if dnsErr == nil || *dnsErr != expectedErr {
t.Errorf("Lookup%v: unexpected error: %v", v.name, err) 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} r := &Resolver{PreferGo: true, Dial: fake.DialContext}
_, _, err := r.tryOneName(context.Background(), getSystemDNSConfig(), "go.dev.", dnsmessage.TypeA) _, _, err := r.tryOneName(context.Background(), getSystemDNSConfig(), "go.dev.", dnsmessage.TypeA)
var dnsErr *DNSError if dnsErr, ok := errors.AsType[*DNSError](err); !ok || dnsErr.Err != errServerMisbehaving.Error() {
if !(errors.As(err, &dnsErr) && dnsErr.Err == errServerMisbehaving.Error()) {
t.Fatalf("r.tryOneName(): unexpected error: %v", err) t.Fatalf("r.tryOneName(): unexpected error: %v", err)
} }
} }

View file

@ -25,19 +25,18 @@ func (e externalStreamError) Error() string {
} }
func TestStreamError(t *testing.T) { func TestStreamError(t *testing.T) {
var target externalStreamError
streamErr := http2streamError(42, http2ErrCodeProtocol) streamErr := http2streamError(42, http2ErrCodeProtocol)
ok := errors.As(streamErr, &target) extStreamErr, ok := errors.AsType[externalStreamError](streamErr)
if !ok { if !ok {
t.Fatalf("errors.As failed") t.Fatalf("errors.AsType failed")
} }
if target.StreamID != streamErr.StreamID { if extStreamErr.StreamID != streamErr.StreamID {
t.Errorf("got StreamID %v, expected %v", target.StreamID, streamErr.StreamID) t.Errorf("got StreamID %v, expected %v", extStreamErr.StreamID, streamErr.StreamID)
} }
if target.Cause != streamErr.Cause { if extStreamErr.Cause != streamErr.Cause {
t.Errorf("got Cause %v, expected %v", target.Cause, streamErr.Cause) t.Errorf("got Cause %v, expected %v", extStreamErr.Cause, streamErr.Cause)
} }
if uint32(target.Code) != uint32(streamErr.Code) { if uint32(extStreamErr.Code) != uint32(streamErr.Code) {
t.Errorf("got Code %v, expected %v", target.Code, streamErr.Code) t.Errorf("got Code %v, expected %v", extStreamErr.Code, streamErr.Code)
} }
} }

View file

@ -1420,8 +1420,8 @@ func testLookupNoData(t *testing.T, prefix string) {
return return
} }
var dnsErr *DNSError dnsErr, ok := errors.AsType[*DNSError](err)
if errors.As(err, &dnsErr) { if ok {
succeeded := true succeeded := true
if !dnsErr.IsNotFound { if !dnsErr.IsNotFound {
succeeded = false succeeded = false
@ -1455,8 +1455,7 @@ func testLookupNoData(t *testing.T, prefix string) {
func TestLookupPortNotFound(t *testing.T) { func TestLookupPortNotFound(t *testing.T) {
allResolvers(t, func(t *testing.T) { allResolvers(t, func(t *testing.T) {
_, err := LookupPort("udp", "_-unknown-service-") _, err := LookupPort("udp", "_-unknown-service-")
var dnsErr *DNSError if dnsErr, ok := errors.AsType[*DNSError](err); !ok || !dnsErr.IsNotFound {
if !errors.As(err, &dnsErr) || !dnsErr.IsNotFound {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
}) })
@ -1475,8 +1474,7 @@ var tcpOnlyService = func() string {
func TestLookupPortDifferentNetwork(t *testing.T) { func TestLookupPortDifferentNetwork(t *testing.T) {
allResolvers(t, func(t *testing.T) { allResolvers(t, func(t *testing.T) {
_, err := LookupPort("udp", tcpOnlyService) _, err := LookupPort("udp", tcpOnlyService)
var dnsErr *DNSError if dnsErr, ok := errors.AsType[*DNSError](err); !ok || !dnsErr.IsNotFound {
if !errors.As(err, &dnsErr) || !dnsErr.IsNotFound {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
}) })

View file

@ -1378,8 +1378,8 @@ func TestWaitInterrupt(t *testing.T) {
// The child process should be reported as failed, // The child process should be reported as failed,
// and the grandchild will exit (or die by SIGPIPE) once the // and the grandchild will exit (or die by SIGPIPE) once the
// stderr pipe is closed. // stderr pipe is closed.
if ee := new(*exec.ExitError); !errors.As(err, ee) { if ee, ok := errors.AsType[*exec.ExitError](err); !ok {
t.Errorf("Wait error = %v; want %T", err, *ee) 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. // This command ignores SIGINT, sleeping until it is killed.
// Wait should return the usual error for a killed process. // Wait should return the usual error for a killed process.
if ee := new(*exec.ExitError); !errors.As(err, ee) { if ee, ok := errors.AsType[*exec.ExitError](err); !ok {
t.Errorf("Wait error = %v; want %T", err, *ee) 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("stderr:\n%s", cmd.Stderr)
t.Logf("[%d] %v", cmd.Process.Pid, err) 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()) t.Errorf("Wait error = %v; want %v", err, ctx.Err())
} }

View file

@ -840,8 +840,7 @@ func TestReaddirOfFile(t *testing.T) {
if err == nil { if err == nil {
t.Error("Readdirnames succeeded; want non-nil error") t.Error("Readdirnames succeeded; want non-nil error")
} }
var pe *PathError if pe, ok := errors.AsType[*PathError](err); !ok || pe.Path != f.Name() {
if !errors.As(err, &pe) || pe.Path != f.Name() {
t.Errorf("Readdirnames returned %q; want a PathError with path %q", err, f.Name()) t.Errorf("Readdirnames returned %q; want a PathError with path %q", err, f.Name())
} }
if len(names) > 0 { if len(names) > 0 {

View file

@ -67,8 +67,7 @@ func readMainModuleMapping() (start, end uint64, exe, buildID string, err error)
func createModuleSnapshot() (syscall.Handle, error) { func createModuleSnapshot() (syscall.Handle, error) {
for { for {
snap, err := syscall.CreateToolhelp32Snapshot(windows.TH32CS_SNAPMODULE|windows.TH32CS_SNAPMODULE32, uint32(syscall.Getpid())) snap, err := syscall.CreateToolhelp32Snapshot(windows.TH32CS_SNAPMODULE|windows.TH32CS_SNAPMODULE32, uint32(syscall.Getpid()))
var errno syscall.Errno if errno, ok := errors.AsType[syscall.Errno](err); ok && errno == windows.ERROR_BAD_LENGTH {
if err != nil && errors.As(err, &errno) && errno == windows.ERROR_BAD_LENGTH {
// When CreateToolhelp32Snapshot(SNAPMODULE|SNAPMODULE32, ...) fails // When CreateToolhelp32Snapshot(SNAPMODULE|SNAPMODULE32, ...) fails
// with ERROR_BAD_LENGTH then it should be retried until it succeeds. // with ERROR_BAD_LENGTH then it should be retried until it succeeds.
continue continue

View file

@ -29,7 +29,7 @@ import (
// The contents of fsys must not change concurrently with TestFS. // The contents of fsys must not change concurrently with TestFS.
// //
// If TestFS finds any misbehaviors, it returns either the first error or a // 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: // Typical usage inside a test is:
// //

View file

@ -105,8 +105,12 @@ func TestTestFSWrappedErrors(t *testing.T) {
// TestFS is expected to return a list of errors. // TestFS is expected to return a list of errors.
// Enforce that the list can be extracted for browsing. // Enforce that the list can be extracted for browsing.
var errs interface{ Unwrap() []error } type wrapper interface{
if !errors.As(err, &errs) { 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) t.Errorf("caller should be able to extract the errors as a list: %#v", err)
} else { } else {
for _, err := range errs.Unwrap() { for _, err := range errs.Unwrap() {

View file

@ -1015,8 +1015,7 @@ func TestExecError_CustomError(t *testing.T) {
var b bytes.Buffer var b bytes.Buffer
err := tmpl.Execute(&b, nil) err := tmpl.Execute(&b, nil)
var e *CustomError if _, ok := errors.AsType[*CustomError](err); !ok {
if !errors.As(err, &e) {
t.Fatalf("expected custom error; got %s", err) t.Fatalf("expected custom error; got %s", err)
} }
} }

View file

@ -22,7 +22,7 @@ import (
// return value evaluates to non-nil during execution, execution terminates and // return value evaluates to non-nil during execution, execution terminates and
// Execute returns that error. // 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. // unwrap them.
// //
// When template execution invokes a function with an argument list, that list // When template execution invokes a function with an argument list, that list