Skip to content

Stabilize ! in Rust 1.41.0 #65355

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Nov 21, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libcore/clone.rs
Original file line number Diff line number Diff line change
@@ -185,7 +185,7 @@ mod impls {
bool char
}

#[unstable(feature = "never_type", issue = "35121")]
#[stable(feature = "never_type", since = "1.41.0")]
impl Clone for ! {
#[inline]
fn clone(&self) -> Self {
8 changes: 4 additions & 4 deletions src/libcore/cmp.rs
Original file line number Diff line number Diff line change
@@ -1128,24 +1128,24 @@ mod impls {

ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }

#[unstable(feature = "never_type", issue = "35121")]
#[stable(feature = "never_type", since = "1.41.0")]
impl PartialEq for ! {
fn eq(&self, _: &!) -> bool {
*self
}
}

#[unstable(feature = "never_type", issue = "35121")]
#[stable(feature = "never_type", since = "1.41.0")]
impl Eq for ! {}

#[unstable(feature = "never_type", issue = "35121")]
#[stable(feature = "never_type", since = "1.41.0")]
impl PartialOrd for ! {
fn partial_cmp(&self, _: &!) -> Option<Ordering> {
*self
}
}

#[unstable(feature = "never_type", issue = "35121")]
#[stable(feature = "never_type", since = "1.41.0")]
impl Ord for ! {
fn cmp(&self, _: &!) -> Ordering {
*self
95 changes: 7 additions & 88 deletions src/libcore/convert.rs
Original file line number Diff line number Diff line change
@@ -40,8 +40,6 @@

#![stable(feature = "rust1", since = "1.0.0")]

use crate::fmt;

/// The identity function.
///
/// Two things are important to note about this function:
@@ -426,9 +424,7 @@ pub trait TryInto<T>: Sized {
/// - `TryFrom<T> for U` implies [`TryInto`]`<U> for T`
/// - [`try_from`] is reflexive, which means that `TryFrom<T> for T`
/// is implemented and cannot fail -- the associated `Error` type for
/// calling `T::try_from()` on a value of type `T` is [`Infallible`].
/// When the [`!`] type is stabilized [`Infallible`] and [`!`] will be
/// equivalent.
/// calling `T::try_from()` on a value of type `T` is [`!`].
///
/// `TryFrom<T>` can be implemented as follows:
///
@@ -477,7 +473,6 @@ pub trait TryInto<T>: Sized {
/// [`TryInto`]: trait.TryInto.html
/// [`i32::MAX`]: ../../std/i32/constant.MAX.html
/// [`!`]: ../../std/primitive.never.html
/// [`Infallible`]: enum.Infallible.html
#[stable(feature = "try_from", since = "1.34.0")]
pub trait TryFrom<T>: Sized {
/// The type returned in the event of a conversion error.
@@ -615,9 +610,9 @@ impl AsRef<str> for str {
// THE NO-ERROR ERROR TYPE
////////////////////////////////////////////////////////////////////////////////

/// The error type for errors that can never happen.
/// A type alias for [the `!` “never” type][never].
///
/// Since this enum has no variant, a value of this type can never actually exist.
/// `Infallible` represents types of errors that can never happen since `!` has no valid values.
/// This can be useful for generic APIs that use [`Result`] and parameterize the error type,
/// to indicate that the result is always [`Ok`].
///
@@ -634,91 +629,15 @@ impl AsRef<str> for str {
/// }
/// ```
///
/// # Future compatibility
///
/// This enum has the same role as [the `!` “never” type][never],
/// which is unstable in this version of Rust.
/// When `!` is stabilized, we plan to make `Infallible` a type alias to it:
///
/// ```ignore (illustrates future std change)
/// pub type Infallible = !;
/// ```
///
/// … and eventually deprecate `Infallible`.
///
///
/// However there is one case where `!` syntax can be used
/// before `!` is stabilized as a full-fleged type: in the position of a function’s return type.
/// Specifically, it is possible implementations for two different function pointer types:
///
/// ```
/// trait MyTrait {}
/// impl MyTrait for fn() -> ! {}
/// impl MyTrait for fn() -> std::convert::Infallible {}
/// ```
/// # Eventual deprecation
///
/// With `Infallible` being an enum, this code is valid.
/// However when `Infallible` becomes an alias for the never type,
/// the two `impl`s will start to overlap
/// and therefore will be disallowed by the language’s trait coherence rules.
/// Previously, `Infallible` was defined as `enum Infallible {}`.
/// Now that it is merely a type alias to `!`, we will eventually deprecate `Infallible`.
///
/// [`Ok`]: ../result/enum.Result.html#variant.Ok
/// [`Result`]: ../result/enum.Result.html
/// [`TryFrom`]: trait.TryFrom.html
/// [`Into`]: trait.Into.html
/// [never]: ../../std/primitive.never.html
#[stable(feature = "convert_infallible", since = "1.34.0")]
#[derive(Copy)]
pub enum Infallible {}

#[stable(feature = "convert_infallible", since = "1.34.0")]
impl Clone for Infallible {
fn clone(&self) -> Infallible {
match *self {}
}
}

#[stable(feature = "convert_infallible", since = "1.34.0")]
impl fmt::Debug for Infallible {
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {}
}
}

#[stable(feature = "convert_infallible", since = "1.34.0")]
impl fmt::Display for Infallible {
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {}
}
}

#[stable(feature = "convert_infallible", since = "1.34.0")]
impl PartialEq for Infallible {
fn eq(&self, _: &Infallible) -> bool {
match *self {}
}
}

#[stable(feature = "convert_infallible", since = "1.34.0")]
impl Eq for Infallible {}

#[stable(feature = "convert_infallible", since = "1.34.0")]
impl PartialOrd for Infallible {
fn partial_cmp(&self, _other: &Self) -> Option<crate::cmp::Ordering> {
match *self {}
}
}

#[stable(feature = "convert_infallible", since = "1.34.0")]
impl Ord for Infallible {
fn cmp(&self, _other: &Self) -> crate::cmp::Ordering {
match *self {}
}
}

#[stable(feature = "convert_infallible", since = "1.34.0")]
impl From<!> for Infallible {
fn from(x: !) -> Self {
x
}
}
pub type Infallible = !;
4 changes: 2 additions & 2 deletions src/libcore/fmt/mod.rs
Original file line number Diff line number Diff line change
@@ -1935,14 +1935,14 @@ macro_rules! fmt_refs {

fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp }

#[unstable(feature = "never_type", issue = "35121")]
#[stable(feature = "never_type", since = "1.41.0")]
impl Debug for ! {
fn fmt(&self, _: &mut Formatter<'_>) -> Result {
*self
}
}

#[unstable(feature = "never_type", issue = "35121")]
#[stable(feature = "never_type", since = "1.41.0")]
impl Display for ! {
fn fmt(&self, _: &mut Formatter<'_>) -> Result {
*self
2 changes: 1 addition & 1 deletion src/libcore/lib.rs
Original file line number Diff line number Diff line change
@@ -85,7 +85,7 @@
#![feature(iter_once_with)]
#![feature(lang_items)]
#![feature(link_llvm_intrinsics)]
#![feature(never_type)]
#![cfg_attr(bootstrap, feature(never_type))]
#![feature(nll)]
#![feature(exhaustive_patterns)]
#![feature(no_core)]
2 changes: 1 addition & 1 deletion src/libcore/marker.rs
Original file line number Diff line number Diff line change
@@ -774,7 +774,7 @@ mod copy_impls {
bool char
}

#[unstable(feature = "never_type", issue = "35121")]
#[stable(feature = "never_type", since = "1.41.0")]
impl Copy for ! {}

#[stable(feature = "rust1", since = "1.0.0")]
12 changes: 1 addition & 11 deletions src/libcore/num/mod.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
#![stable(feature = "rust1", since = "1.0.0")]

use crate::convert::{TryFrom, Infallible};
use crate::convert::TryFrom;
use crate::fmt;
use crate::intrinsics;
use crate::mem;
@@ -4722,18 +4722,8 @@ impl fmt::Display for TryFromIntError {
}

#[stable(feature = "try_from", since = "1.34.0")]
impl From<Infallible> for TryFromIntError {
fn from(x: Infallible) -> TryFromIntError {
match x {}
}
}

#[unstable(feature = "never_type", issue = "35121")]
impl From<!> for TryFromIntError {
fn from(never: !) -> TryFromIntError {
// Match rather than coerce to make sure that code like
// `From<Infallible> for TryFromIntError` above will keep working
// when `Infallible` becomes an alias to `!`.
match never {}
}
}
2 changes: 1 addition & 1 deletion src/librustc/lib.rs
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@
#![feature(core_intrinsics)]
#![feature(drain_filter)]
#![cfg_attr(windows, feature(libc))]
#![feature(never_type)]
#![cfg_attr(bootstrap, feature(never_type))]
#![feature(exhaustive_patterns)]
#![feature(overlapping_marker_traits)]
#![feature(extern_types)]
4 changes: 2 additions & 2 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
@@ -2440,10 +2440,10 @@ impl<'tcx> TyCtxt<'tcx> {

#[inline]
pub fn mk_diverging_default(self) -> Ty<'tcx> {
if self.features().never_type {
if self.features().never_type_fallback {
self.types.never
} else {
self.intern_tup(&[])
self.types.unit
}
}

2 changes: 1 addition & 1 deletion src/librustc_codegen_utils/lib.rs
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(core_intrinsics)]
#![feature(never_type)]
#![cfg_attr(bootstrap, feature(never_type))]
#![feature(nll)]
#![feature(in_band_lifetimes)]

4 changes: 2 additions & 2 deletions src/librustc_error_codes/error_codes/E0725.md
Original file line number Diff line number Diff line change
@@ -4,8 +4,8 @@ command line flags.
Erroneous code example:

```ignore (can't specify compiler flags from doctests)
#![feature(never_type)] // error: the feature `never_type` is not in
// the list of allowed features
#![feature(specialization)] // error: the feature `specialization` is not in
// the list of allowed features
```

Delete the offending feature attribute, or add it to the list of allowed
2 changes: 1 addition & 1 deletion src/librustc_mir/lib.rs
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
#![feature(decl_macro)]
#![feature(drain_filter)]
#![feature(exhaustive_patterns)]
#![feature(never_type)]
#![cfg_attr(bootstrap, feature(never_type))]
#![feature(specialization)]
#![feature(try_trait)]
#![feature(unicode_internals)]
11 changes: 8 additions & 3 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -3129,9 +3129,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

// Tries to apply a fallback to `ty` if it is an unsolved variable.
// Non-numerics get replaced with ! or () (depending on whether
// feature(never_type) is enabled, unconstrained ints with i32,
// unconstrained floats with f64.
//
// - Unconstrained ints are replaced with `i32`.
//
// - Unconstrained floats are replaced with with `f64`.
//
// - Non-numerics get replaced with `!` when `#![feature(never_type_fallback)]`
// is enabled. Otherwise, they are replaced with `()`.
//
// Fallback becomes very dubious if we have encountered type-checking errors.
// In that case, fallback to Error.
// The return value indicates whether fallback has occurred.
2 changes: 1 addition & 1 deletion src/librustc_typeck/lib.rs
Original file line number Diff line number Diff line change
@@ -66,7 +66,7 @@ This API is completely unstable and subject to change.
#![feature(in_band_lifetimes)]
#![feature(nll)]
#![feature(slice_patterns)]
#![feature(never_type)]
#![cfg_attr(bootstrap, feature(never_type))]

#![recursion_limit="256"]

2 changes: 1 addition & 1 deletion src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@
#![feature(crate_visibility_modifier)]
#![feature(const_fn)]
#![feature(drain_filter)]
#![feature(never_type)]
#![cfg_attr(bootstrap, feature(never_type))]
#![feature(unicode_internals)]

#![recursion_limit="256"]
2 changes: 1 addition & 1 deletion src/libserialize/lib.rs
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ Core encoding and decoding interfaces.
#![feature(box_syntax)]
#![feature(core_intrinsics)]
#![feature(specialization)]
#![feature(never_type)]
#![cfg_attr(bootstrap, feature(never_type))]
#![feature(nll)]
#![feature(associated_type_bounds)]
#![cfg_attr(test, feature(test))]
9 changes: 1 addition & 8 deletions src/libstd/error.rs
Original file line number Diff line number Diff line change
@@ -465,7 +465,7 @@ impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
}
}

#[unstable(feature = "never_type", issue = "35121")]
#[stable(feature = "never_type", since = "1.41.0")]
impl Error for ! {
fn description(&self) -> &str { *self }
}
@@ -551,13 +551,6 @@ impl Error for string::FromUtf16Error {
}
}

#[stable(feature = "str_parse_error2", since = "1.8.0")]
impl Error for string::ParseError {
fn description(&self) -> &str {
match *self {}
}
}

#[stable(feature = "decode_utf16", since = "1.9.0")]
impl Error for char::DecodeUtf16Error {
fn description(&self) -> &str {
2 changes: 1 addition & 1 deletion src/libstd/lib.rs
Original file line number Diff line number Diff line change
@@ -280,7 +280,7 @@
#![feature(maybe_uninit_ref)]
#![feature(maybe_uninit_slice)]
#![feature(needs_panic_runtime)]
#![feature(never_type)]
#![cfg_attr(bootstrap, feature(never_type))]
#![feature(nll)]
#![cfg_attr(bootstrap, feature(on_unimplemented))]
#![feature(optin_builtin_traits)]
4 changes: 1 addition & 3 deletions src/libstd/primitive_docs.rs
Original file line number Diff line number Diff line change
@@ -71,7 +71,6 @@ mod prim_bool { }
/// write:
///
/// ```
/// #![feature(never_type)]
/// # fn foo() -> u32 {
/// let x: ! = {
/// return 123
@@ -201,7 +200,6 @@ mod prim_bool { }
/// for example:
///
/// ```
/// #![feature(never_type)]
/// # use std::fmt;
/// # trait Debug {
/// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
@@ -239,7 +237,7 @@ mod prim_bool { }
/// [`Default`]: default/trait.Default.html
/// [`default()`]: default/trait.Default.html#tymethod.default
///
#[unstable(feature = "never_type", issue = "35121")]
#[stable(feature = "never_type", since = "1.41.0")]
mod prim_never { }

#[doc(primitive = "char")]
2 changes: 2 additions & 0 deletions src/libsyntax/feature_gate/accepted.rs
Original file line number Diff line number Diff line change
@@ -253,6 +253,8 @@ declare_features! (
(accepted, const_constructor, "1.40.0", Some(61456), None),
/// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
(accepted, cfg_doctest, "1.40.0", Some(62210), None),
/// Allows the `!` type. Does not imply 'exhaustive_patterns' any more.
(accepted, never_type, "1.41.0", Some(35121), None),
/// Allows relaxing the coherence rules such that
/// `impl<T> ForeignTrait<LocalType> for ForeignType<T>` is permitted.
(accepted, re_rebalance_coherence, "1.41.0", Some(55437), None),
Loading