A trait for types which support bounded recursion to prevent stack overflow. The rather odd design of this trait allows checked recursion to be added to existing mutually recursive functions without threading an explicit `depth: &mut usize` parameter through each function. As long as there is an existing context structure, or if the mutually recursive functions are methods on a context structure,
| 176 | /// } |
| 177 | /// ``` |
| 178 | pub trait CheckedRecursion { |
| 179 | /// Extracts a reference to the recursion guard embedded within the type. |
| 180 | fn recursion_guard(&self) -> &RecursionGuard; |
| 181 | |
| 182 | /// Checks whether it is safe to recur and calls `f` if so. |
| 183 | /// |
| 184 | /// If the recursion limit for the recursion guard returned by |
| 185 | /// [`CheckedRecursion::recursion_guard`] has been reached, returns a |
| 186 | /// `RecursionLimitError`. Otherwise, it will call `f`, possibly growing the |
| 187 | /// stack if necessary. |
| 188 | /// |
| 189 | /// Calls to this function must be manually inserted at any point that |
| 190 | /// mutual recursion occurs. |
| 191 | #[inline(always)] |
| 192 | fn checked_recur<F, T, E>(&self, f: F) -> Result<T, E> |
| 193 | where |
| 194 | F: FnOnce(&Self) -> Result<T, E>, |
| 195 | E: From<RecursionLimitError>, |
| 196 | { |
| 197 | self.recursion_guard().descend()?; |
| 198 | let out = maybe_grow(|| f(self)); |
| 199 | self.recursion_guard().ascend(); |
| 200 | out |
| 201 | } |
| 202 | |
| 203 | /// Like [`CheckedRecursion::checked_recur`], but operates on a mutable |
| 204 | /// reference to `Self`. |
| 205 | #[inline(always)] |
| 206 | fn checked_recur_mut<F, T, E>(&mut self, f: F) -> Result<T, E> |
| 207 | where |
| 208 | F: FnOnce(&mut Self) -> Result<T, E>, |
| 209 | E: From<RecursionLimitError>, |
| 210 | { |
| 211 | self.recursion_guard().descend()?; |
| 212 | let out = maybe_grow(|| f(self)); |
| 213 | self.recursion_guard().ascend(); |
| 214 | out |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | /// Tracks recursion depth. |
| 219 | /// |
no outgoing calls
no test coverage detected