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
// 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, 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>;
}

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