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}