void/
lib.rs

1#![cfg_attr(test, deny(warnings))]
2#![deny(missing_docs)]
3#![cfg_attr(not(feature = "std"), no_std)]
4
5//! # Void
6//!
7//! The uninhabited void type for use in statically impossible cases.
8//!
9//! In its own crate so all the users in the ecosystem can share the same type.
10//! This crate also comes ready with several extension traits for Result that add
11//! extra functionality to `Result<T, Void>` and `Result<Void, E>`.
12//!
13
14#[cfg(not(feature = "std"))]
15mod coreprovider {
16    extern crate core;
17    pub use core::{fmt, cmp};
18}
19
20#[cfg(feature = "std")]
21mod coreprovider {
22    pub use std::{fmt, cmp, error};
23}
24
25use coreprovider::*;
26
27/// The empty type for cases which can't occur.
28#[derive(Copy)]
29pub enum Void { }
30
31impl Clone for Void {
32    fn clone(&self) -> Void {
33        unreachable(*self)
34    }
35}
36
37impl fmt::Debug for Void {
38    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
39        unreachable(*self)
40    }
41}
42
43impl fmt::Display for Void {
44    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
45        unreachable(*self)
46    }
47}
48
49impl<T> cmp::PartialEq<T> for Void {
50    fn eq(&self, _: &T) -> bool {
51        unreachable(*self)
52    }
53}
54
55impl<T> cmp::PartialOrd<T> for Void {
56    fn partial_cmp(&self, _: &T) -> Option<cmp::Ordering> {
57        unreachable(*self)
58    }
59}
60
61#[cfg(feature = "std")]
62impl error::Error for Void {
63    fn description(&self) -> &str {
64        unreachable(*self)
65    }
66
67    fn cause(&self) -> Option<&error::Error> {
68        unreachable(*self)
69    }
70}
71
72/// A safe version of `intrinsincs::unreachable`.
73///
74/// If this typechecks, anything that causes this to run is unreachable code.
75///
76/// Calling this function in reachable code invokes undefined behavior, but
77/// should not be possible unless `unsafe` was used elsewhere to construct
78/// an instance of `Void` (which is already undefined behavior).
79#[inline(always)]
80pub fn unreachable(x: Void) -> ! {
81    match x {}
82}
83
84/// Extensions to `Result<T, Void>`
85pub trait ResultVoidExt<T>: Sized {
86    /// Get the value out of a wrapper.
87    fn void_unwrap(self) -> T;
88}
89
90impl<T> ResultVoidExt<T> for Result<T, Void> {
91    /// Get the value out of an always-ok Result.
92    ///
93    /// Never panics, since it is statically known to be Ok.
94    #[inline]
95    fn void_unwrap(self) -> T {
96        match self {
97            Ok(val) => val,
98            Err(e) => unreachable(e)
99        }
100    }
101}
102
103/// Extensions to `Result<Void, E>`
104pub trait ResultVoidErrExt<E>: Sized {
105    /// Get the error out of a wrapper.
106    fn void_unwrap_err(self) -> E;
107}
108
109impl<E> ResultVoidErrExt<E> for Result<Void, E> {
110    /// Get the error out of an always-err Result.
111    ///
112    /// Never panics, since it is statically known to be Err.
113    #[inline]
114    fn void_unwrap_err(self) -> E {
115        match self {
116            Ok(v) => unreachable(v),
117            Err(e) => e
118        }
119    }
120}
121