explicit/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Utilities which allow code to be more robust to changes in dependencies.
//!
//! The utilities in this crate allow code to depend on details of its
//! dependencies which would not normally be captured by code using the
//! canonical Rust style. See [this document][rust-patterns] for a discussion of
//! when and why this might be desirable.
//!
//! [rust-patterns]: https://fuchsia.dev/fuchsia-src/contribute/contributing-to-netstack/rust-patterns

#![no_std]
#![deny(missing_docs)]

use core::convert::Infallible as Never;
use core::task::Poll;

/// An extension trait adding functionality to [`Result`].
pub trait ResultExt<T, E> {
    /// Like [`Result::ok`], but the caller must provide the error type being
    /// discarded.
    ///
    /// This allows code to be written which will stop compiling if a result's
    /// error type changes in the future.
    fn ok_checked<EE: sealed::EqType<E>>(self) -> Option<T>;

    /// Like [`Result::err`], but the caller must provide the ok type being
    /// discarded.
    ///
    /// This allows code to be written which will stop compiling if a result's
    /// ok type changes in the future.
    fn err_checked<TT: sealed::EqType<T>>(self) -> Option<E>;
}

impl<T, E> ResultExt<T, E> for Result<T, E> {
    fn ok_checked<EE: sealed::EqType<E>>(self) -> Option<T> {
        Result::ok(self)
    }

    fn err_checked<TT: sealed::EqType<T>>(self) -> Option<E> {
        Result::err(self)
    }
}

/// An extension trait adding functionality to [`Poll`].
pub trait PollExt<T> {
    /// Like [`Poll::is_ready`], but the caller must provide the inner type.
    ///
    /// This allows both the authors and the reviewers to check if information
    /// is being discarded unnoticed.
    fn is_ready_checked<TT: sealed::EqType<T>>(&self) -> bool;
}

impl<T> PollExt<T> for Poll<T> {
    fn is_ready_checked<TT: sealed::EqType<T>>(&self) -> bool {
        Poll::is_ready(self)
    }
}

/// A trait providing unreachability assertion enforced by the type system.
///
/// # Example
/// ```
/// use core::convert::Infallible as Never;
///
/// /// Provides guaranteed winning lottery numbers.
/// trait LotteryOracle {
///   fn get_winning_number(&self) -> u32;
/// }
///
/// // Might return a thing that gives winning lottery numbers.
/// fn try_get_lottery_oracle() -> Option<impl LotteryOracle> {
///   // This function always returns `None` but we still need a type that
///   // the option _could_ hold.
///
///   /// Uninstantiable type that implements [`LotteryOracle`].
///   struct UninstantiableOracle(Never);
///
///   /// Enable use with [`UnreachableExt`].
///   impl AsRef<Never> for UninstantiableOracle {
///     fn as_ref(&self) -> Never {
///       &self.0
///     }
///   }
///
///   /// Trivial implementation that can't actually be used.
///   impl LotteryOracle for UninstantiableOracle {
///     fn get_winning_number(&self) -> u32 {
///       self.uninstantiable_unreachable()
///     }
///   }
///
///   Option::<UninstantiableOracle>::None
/// }
/// ```
///
/// # Implementing
///
/// This trait is blanket-implemented for any type that can be used to construct
/// an instance of [`Never`]. To use it, simply implement [`AsRef<Never>`].
pub trait UnreachableExt: sealed::Sealed {
    /// A method that can't be called.
    ///
    /// This method returns an instance of any caller-specified type, which
    /// makes it impossible to implement unless the method receiver is itself
    /// uninstantiable. This method is similar to the `unreachable!` macro, but
    /// should be preferred over the macro since it uses the type system to
    /// enforce unreachability where `unreachable!` indicates a logical
    /// assertion checked at runtime.
    fn uninstantiable_unreachable<T>(&self) -> T;
}

impl<N: AsRef<Never>> UnreachableExt for N {
    fn uninstantiable_unreachable<T>(&self) -> T {
        match *self.as_ref() {}
    }
}

mod sealed {
    use core::convert::Infallible as Never;

    /// `EqType<T>` indicates that the implementer is equal to `T`.
    ///
    /// For all `T`, `T: EqType<T>`. For all distinct `T` and `U`, `T:
    /// !EqType<U>`.
    pub trait EqType<T> {}

    impl<T> EqType<T> for T {}

    /// Trait that can only be implemented within this crate.
    pub trait Sealed {}

    impl<T: AsRef<Never>> Sealed for T {}
}