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::task::Poll;
18
19/// An extension trait adding functionality to [`Result`].
20pub trait ResultExt<T, E> {
21 /// Like [`Result::ok`], but the caller must provide the error type being
22 /// discarded.
23 ///
24 /// This allows code to be written which will stop compiling if a result's
25 /// error type changes in the future.
26 fn ok_checked<EE: sealed::EqType<E>>(self) -> Option<T>;
27
28 /// Like [`Result::err`], but the caller must provide the ok type being
29 /// discarded.
30 ///
31 /// This allows code to be written which will stop compiling if a result's
32 /// ok type changes in the future.
33 fn err_checked<TT: sealed::EqType<T>>(self) -> Option<E>;
34}
35
36impl<T, E> ResultExt<T, E> for Result<T, E> {
37 fn ok_checked<EE: sealed::EqType<E>>(self) -> Option<T> {
38 Result::ok(self)
39 }
40
41 fn err_checked<TT: sealed::EqType<T>>(self) -> Option<E> {
42 Result::err(self)
43 }
44}
45
46/// An extension trait adding functionality to [`Poll`].
47pub trait PollExt<T> {
48 /// Like [`Poll::is_ready`], but the caller must provide the inner type.
49 ///
50 /// This allows both the authors and the reviewers to check if information
51 /// is being discarded unnoticed.
52 fn is_ready_checked<TT: sealed::EqType<T>>(&self) -> bool;
53}
54
55impl<T> PollExt<T> for Poll<T> {
56 fn is_ready_checked<TT: sealed::EqType<T>>(&self) -> bool {
57 Poll::is_ready(self)
58 }
59}
60
61/// A trait providing unreachability assertion enforced by the type system.
62///
63/// # Example
64/// ```
65///
66/// /// Provides guaranteed winning lottery numbers.
67/// trait LotteryOracle {
68/// fn get_winning_number(&self) -> u32;
69/// }
70///
71/// // Might return a thing that gives winning lottery numbers.
72/// fn try_get_lottery_oracle() -> Option<impl LotteryOracle> {
73/// // This function always returns `None` but we still need a type that
74/// // the option _could_ hold.
75///
76/// /// Uninstantiable type that implements [`LotteryOracle`].
77/// struct UninstantiableOracle(!);
78///
79/// /// Enable use with [`UnreachableExt`].
80/// impl AsRef<!> for UninstantiableOracle {
81/// fn as_ref(&self) -> ! {
82/// &self.0
83/// }
84/// }
85///
86/// /// Trivial implementation that can't actually be used.
87/// impl LotteryOracle for UninstantiableOracle {
88/// fn get_winning_number(&self) -> u32 {
89/// self.uninstantiable_unreachable()
90/// }
91/// }
92///
93/// Option::<UninstantiableOracle>::None
94/// }
95/// ```
96///
97/// # Implementing
98///
99/// This trait is blanket-implemented for any type that can be used to construct
100/// an instance of `!`. To use it, simply implement [`AsRef<!>`].
101pub trait UnreachableExt: sealed::Sealed {
102 /// A method that can't be called.
103 ///
104 /// This method returns an instance of any caller-specified type, which
105 /// makes it impossible to implement unless the method receiver is itself
106 /// uninstantiable. This method is similar to the `unreachable!` macro, but
107 /// should be preferred over the macro since it uses the type system to
108 /// enforce unreachability where `unreachable!` indicates a logical
109 /// assertion checked at runtime.
110 fn uninstantiable_unreachable<T>(&self) -> T;
111}
112
113impl<N: AsRef<!>> UnreachableExt for N {
114 fn uninstantiable_unreachable<T>(&self) -> T {
115 match *self.as_ref() {}
116 }
117}
118
119mod sealed {
120
121 /// `EqType<T>` indicates that the implementer is equal to `T`.
122 ///
123 /// For all `T`, `T: EqType<T>`. For all distinct `T` and `U`, `T:
124 /// !EqType<U>`.
125 pub trait EqType<T> {}
126
127 impl<T> EqType<T> for T {}
128
129 /// Trait that can only be implemented within this crate.
130 pub trait Sealed {}
131
132 impl<T: AsRef<!>> Sealed for T {}
133}