// Additional type conversion abstractions // // Copyright (C) 2014-2023 Ryan Specialty, LLC. // // This file is part of TAME. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . //! TAMER opinionated traits for conversion between types. //! //! _This should not be used for error reporting to users!_ //! Panics in TAMER represent internal compiler errors. //! //! This module introduces two new traits: //! //! - [`ExpectFrom`] implemented for all [`TryFrom`]; and //! - [`ExpectInto`] implemented for all [`TryInto`]. //! //! These traits provide two new methods: //! //! - `expect_{from,into}`, which is equivalent to calling //! [`Result::expect`] on the result; and //! - `unwrap_{from,into}`, which is equivalent to calling //! [`Result::unwrap`] on the result. //! //! These two traits are intended to eliminate boilerplate in situations //! where _it is expected that these will never fail_. //! There may be better options; //! these are most useful in writing tests. use crate::{ diagnose::{panic::DiagnosticPanic, NO_DESC}, f::ThunkOrStaticRef, }; use std::{ convert::{TryFrom, TryInto}, fmt::{Debug, Display}, }; /// Safe type conversion that may panic under some circumstances. /// /// This is implemented for every type implementing [`TryFrom`] and is /// intended to be used in situations where we are certain that failure /// cannot occur, /// or where failure would otherwise be folowed by [`Result::expect`] or /// [`Result::unwrap`]. /// /// Once Rust is further along with a sound trait impl specialization /// implementation, /// this system ought to utilize spans when available for diagnostic /// messages. /// /// See the [module-level documentation](self) for more information. pub trait ExpectFrom: TryFrom where >::Error: Debug, { /// Attempt to convert `value` using `T::try_from`, /// causing a panic with the given `msg` on failure. /// /// Panics /// ====== /// Causes a panic on failure. fn expect_from>(value: T, msg: M) -> Self where M::Output: Display, { Self::try_from(value).diagnostic_expect(|| NO_DESC, msg) } /// Attempt to convert and unwrap `value` using `T::try_from`. /// /// Panics /// ====== /// Causes a panic on failure. fn unwrap_from(value: T) -> Self { Self::try_from(value).diagnostic_unwrap(|| NO_DESC) } } impl ExpectFrom for T where T: TryFrom, >::Error: Debug, { } /// An attempted conversion that consumes `self`, /// which may or may not be expensive and will panic on failure. /// /// This is implemented for every type implementing [`TryInto`] and is /// intended to be used in situations where we are certain that failure /// cannot occur, /// or where failure would otherwise be folowed by [`Result::expect`] or /// [`Result::unwrap`]. /// /// See the [module-level documentation](self) for more information. pub trait ExpectInto: TryInto where >::Error: Debug, { /// Attempt to convert a value using `self.try_into()`, /// causing a panic with the given `msg` on failure. /// /// Panics /// ====== /// Causes a panic on failure. fn expect_into>(self, msg: M) -> T where M::Output: Display, { self.try_into().diagnostic_expect(|| NO_DESC, msg) } /// Attempt to convert and unwrap a value using `self.try_into()`. /// /// Panics /// ====== /// Causes a panic on failure. fn unwrap_into(self) -> T { self.try_into().diagnostic_unwrap(|| NO_DESC) } } impl ExpectInto for T where T: TryInto, >::Error: Debug, { }