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)
}
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" {
// 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
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
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
// 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
}
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
}
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
}
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()
}
})
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)
}
// 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
// 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.
// 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) {
}
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
}
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
// 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 {
// 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
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)
}
})
// 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
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
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
// 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}
}
// 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
}
}
- 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 {
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
}
// 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
}
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
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
// 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)
// 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))
}
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)
}
// 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}
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
}
} 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)
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
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.
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 {
})
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)
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.
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
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
}
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)
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)
// 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
}
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 {
// 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,
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)
// 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)
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
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 {
}
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)) {
// 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()
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)
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))
}
}
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.
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)
}
}
// 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)
// 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
} 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
// 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
// ...
// 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
// ...
// 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()))
}
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)
}
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" {
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:
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
}
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
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)
}
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)
}
}
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 {
}
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)
}
}
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)
}
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)
}
}
}
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)
}
}
return
}
- var dnsErr *DNSError
- if errors.As(err, &dnsErr) {
+ dnsErr, ok := errors.AsType[*DNSError](err)
+ if ok {
succeeded := true
if !dnsErr.IsNotFound {
succeeded = false
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)
}
})
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)
}
})
// 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)
}
})
// 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)
}
})
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())
}
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 {
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
// 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:
//
// 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() {
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)
}
}
// 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