% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/cnd.R
\name{cnd_inherits}
\alias{cnd_inherits}
\title{Does a condition or its ancestors inherit from a class?}
\usage{
cnd_inherits(cnd, class)
}
\arguments{
\item{cnd}{A condition to test.}

\item{class}{A class passed to \code{\link[=inherits]{inherits()}}.}
}
\description{
Like any R objects, errors captured with catchers like \code{\link[=tryCatch]{tryCatch()}}
have a \code{\link[=class]{class()}} which you can test with \code{\link[=inherits]{inherits()}}.  However,
with chained errors, the class of a captured error might be
different than the error that was originally signalled. Use
\code{cnd_inherits()} to detect whether an error or any of its \emph{parent}
inherits from a class.

Whereas \code{inherits()} tells you whether an object is a particular
kind of error, \code{cnd_inherits()} answers the question whether an
object is a particular kind of error or has been caused by such an
error.

Some chained conditions carry parents that are not inherited. See
the \code{.inherit} argument of \code{\link[=abort]{abort()}}, \code{\link[=warn]{warn()}}, and \code{\link[=inform]{inform()}}.
}
\section{Capture an error with \code{cnd_inherits()}}{
Error catchers like \code{\link[=tryCatch]{tryCatch()}} and \code{\link[=try_fetch]{try_fetch()}} can only match
the class of a condition, not the class of its parents. To match a
class across the ancestry of an error, you'll need a bit of
craftiness.

Ancestry matching can't be done with \code{tryCatch()} at all so you'll
need to switch to \code{\link[=withCallingHandlers]{withCallingHandlers()}}. Alternatively, you can
use the experimental rlang function \code{\link[=try_fetch]{try_fetch()}} which is able to
perform the roles of both \code{tryCatch()} and \code{withCallingHandlers()}.
\subsection{\code{withCallingHandlers()}}{

Unlike \code{tryCatch()}, \code{withCallingHandlers()} does not capture an
error. If you don't explicitly jump with an \emph{error} or a \emph{value}
throw, nothing happens.

Since we don't want to throw an error, we'll throw a value using
\code{\link[=callCC]{callCC()}}:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{f <- function() \{
  parent <- error_cnd("bar", message = "Bar")
  abort("Foo", parent = parent)
\}

cnd <- callCC(function(throw) \{
  withCallingHandlers(
    f(),
    error = function(x) if (cnd_inherits(x, "bar")) throw(x)
  )
\})

class(cnd)
#> [1] "rlang_error" "error"       "condition"
class(cnd$parent)
#> [1] "bar"         "rlang_error" "error"       "condition"
}\if{html}{\out{</div>}}
}

\subsection{\code{try_fetch()}}{

This pattern is easier with \code{\link[=try_fetch]{try_fetch()}}. Like
\code{withCallingHandlers()}, it doesn't capture a matching error right
away. Instead, it captures it only if the handler doesn't return a
\code{\link[=zap]{zap()}} value.

\if{html}{\out{<div class="sourceCode r">}}\preformatted{cnd <- try_fetch(
  f(),
  error = function(x) if (cnd_inherits(x, "bar")) x else zap()
)

class(cnd)
#> [1] "rlang_error" "error"       "condition"
class(cnd$parent)
#> [1] "bar"         "rlang_error" "error"       "condition"
}\if{html}{\out{</div>}}

Note that \code{try_fetch()} uses \code{cnd_inherits()} internally. This
makes it very easy to match a parent condition:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{cnd <- try_fetch(
  f(),
  bar = function(x) x
)

# This is the parent
class(cnd)
#> [1] "bar"         "rlang_error" "error"       "condition"
}\if{html}{\out{</div>}}
}
}

