explicit/
lib.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Utilities which allow code to be more robust to changes in dependencies.
6//!
7//! The utilities in this crate allow code to depend on details of its
8//! dependencies which would not normally be captured by code using the
9//! canonical Rust style. See [this document][rust-patterns] for a discussion of
10//! when and why this might be desirable.
11//!
12//! [rust-patterns]: https://fuchsia.dev/fuchsia-src/contribute/contributing-to-netstack/rust-patterns
13
14#![no_std]
15#![warn(missing_docs)]
16
17use core::convert::Infallible as Never;
18use core::task::Poll;
19
20/// An extension trait adding functionality to [`Result`].
21pub trait ResultExt<T, E> {
22    /// Like [`Result::ok`], but the caller must provide the error type being
23    /// discarded.
24    ///
25    /// This allows code to be written which will stop compiling if a result's
26    /// error type changes in the future.
27    fn ok_checked<EE: sealed::EqType<E>>(self) -> Option<T>;
28
29    /// Like [`Result::err`], but the caller must provide the ok type being
30    /// discarded.
31    ///
32    /// This allows code to be written which will stop compiling if a result's
33    /// ok type changes in the future.
34    fn err_checked<TT: sealed::EqType<T>>(self) -> Option<E>;
35}
36
37impl<T, E> ResultExt<T, E> for Result<T, E> {
38    fn ok_checked<EE: sealed::EqType<E>>(self) -> Option<T> {
39        Result::ok(self)
40    }
41
42    fn err_checked<TT: sealed::EqType<T>>(self) -> Option<E> {
43        Result::err(self)
44    }
45}
46
47/// An extension trait adding functionality to [`Poll`].
48pub trait PollExt<T> {
49    /// Like [`Poll::is_ready`], but the caller must provide the inner type.
50    ///
51    /// This allows both the authors and the reviewers to check if information
52    /// is being discarded unnoticed.
53    fn is_ready_checked<TT: sealed::EqType<T>>(&self) -> bool;
54}
55
56impl<T> PollExt<T> for Poll<T> {
57    fn is_ready_checked<TT: sealed::EqType<T>>(&self) -> bool {
58        Poll::is_ready(self)
59    }
60}
61
62/// A trait providing unreachability assertion enforced by the type system.
63///
64/// # Example
65/// ```
66/// use core::convert::Infallible as Never;
67///
68/// /// Provides guaranteed winning lottery numbers.
69/// trait LotteryOracle {
70///   fn get_winning_number(&self) -> u32;
71/// }
72///
73/// // Might return a thing that gives winning lottery numbers.
74/// fn try_get_lottery_oracle() -> Option<impl LotteryOracle> {
75///   // This function always returns `None` but we still need a type that
76///   // the option _could_ hold.
77///
78///   /// Uninstantiable type that implements [`LotteryOracle`].
79///   struct UninstantiableOracle(Never);
80///
81///   /// Enable use with [`UnreachableExt`].
82///   impl AsRef<Never> for UninstantiableOracle {
83///     fn as_ref(&self) -> Never {
84///       &self.0
85///     }
86///   }
87///
88///   /// Trivial implementation that can't actually be used.
89///   impl LotteryOracle for UninstantiableOracle {
90///     fn get_winning_number(&self) -> u32 {
91///       self.uninstantiable_unreachable()
92///     }
93///   }
94///
95///   Option::<UninstantiableOracle>::None
96/// }
97/// ```
98///
99/// # Implementing
100///
101/// This trait is blanket-implemented for any type that can be used to construct
102/// an instance of [`Never`]. To use it, simply implement [`AsRef<Never>`].
103pub trait UnreachableExt: sealed::Sealed {
104    /// A method that can't be called.
105    ///
106    /// This method returns an instance of any caller-specified type, which
107    /// makes it impossible to implement unless the method receiver is itself
108    /// uninstantiable. This method is similar to the `unreachable!` macro, but
109    /// should be preferred over the macro since it uses the type system to
110    /// enforce unreachability where `unreachable!` indicates a logical
111    /// assertion checked at runtime.
112    fn uninstantiable_unreachable<T>(&self) -> T;
113}
114
115impl<N: AsRef<Never>> UnreachableExt for N {
116    fn uninstantiable_unreachable<T>(&self) -> T {
117        match *self.as_ref() {}
118    }
119}
120
121mod sealed {
122    use core::convert::Infallible as Never;
123
124    /// `EqType<T>` indicates that the implementer is equal to `T`.
125    ///
126    /// For all `T`, `T: EqType<T>`. For all distinct `T` and `U`, `T:
127    /// !EqType<U>`.
128    pub trait EqType<T> {}
129
130    impl<T> EqType<T> for T {}
131
132    /// Trait that can only be implemented within this crate.
133    pub trait Sealed {}
134
135    impl<T: AsRef<Never>> Sealed for T {}
136}