Skip to content

Commit

Permalink
Gate fallback via #![feature(never_type_fallback)].
Browse files Browse the repository at this point in the history
  • Loading branch information
Centril committed Nov 21, 2019
1 parent 8f6197f commit 6eb0627
Show file tree
Hide file tree
Showing 18 changed files with 64 additions and 19 deletions.
6 changes: 5 additions & 1 deletion src/librustc/ty/context.rs
Expand Up @@ -2440,7 +2440,11 @@ impl<'tcx> TyCtxt<'tcx> {

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

#[inline]
Expand Down
10 changes: 8 additions & 2 deletions src/librustc_typeck/check/mod.rs
Expand Up @@ -3129,8 +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 `!`, 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.
Expand Down
3 changes: 3 additions & 0 deletions src/libsyntax/feature_gate/active.rs
Expand Up @@ -520,6 +520,9 @@ declare_features! (
/// Allows using the `efiapi` ABI.
(active, abi_efiapi, "1.40.0", Some(65815), None),

/// Allows diverging expressions to fall back to `!` rather than `()`.
(active, never_type_fallback, "1.41.0", Some(65992), None),

/// Allows using the `#[register_attr]` attribute.
(active, register_attr, "1.41.0", Some(66080), None),

Expand Down
1 change: 1 addition & 0 deletions src/libsyntax_pos/symbol.rs
Expand Up @@ -444,6 +444,7 @@ symbols! {
negate_unsigned,
never,
never_type,
never_type_fallback,
new,
next,
__next,
Expand Down
Expand Up @@ -21,5 +21,5 @@ trait Add<RHS=Self> {
fn ice<A>(a: A) {
let r = loop {};
r = r + a;
//~^ ERROR the trait bound `!: Add<A>` is not satisfied
//~^ ERROR the trait bound `(): Add<A>` is not satisfied
}
@@ -1,8 +1,8 @@
error[E0277]: the trait bound `!: Add<A>` is not satisfied
error[E0277]: the trait bound `(): Add<A>` is not satisfied
--> $DIR/associated-types-ICE-when-projecting-out-of-err.rs:23:11
|
LL | r = r + a;
| ^ the trait `Add<A>` is not implemented for `!`
| ^ the trait `Add<A>` is not implemented for `()`

error: aborting due to previous error

Expand Down
1 change: 1 addition & 0 deletions src/test/ui/binding/empty-types-in-patterns.rs
@@ -1,4 +1,5 @@
// run-pass
#![feature(never_type_fallback)]
#![feature(exhaustive_patterns)]
#![feature(slice_patterns)]
#![allow(unreachable_patterns)]
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/coercion/coerce-issue-49593-box-never.rs
@@ -1,5 +1,5 @@
// check-pass

#![feature(never_type_fallback)]
#![allow(unreachable_code)]

use std::error::Error;
Expand Down
4 changes: 4 additions & 0 deletions src/test/ui/never_type/defaulted-never-note.rs
@@ -1,3 +1,7 @@
// We need to opt into the `never_type_fallback` feature
// to trigger the requirement that this is testing.
#![feature(never_type_fallback)]

#![allow(unused)]

trait Deserialize: Sized {
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/never_type/defaulted-never-note.stderr
@@ -1,5 +1,5 @@
error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied
--> $DIR/defaulted-never-note.rs:23:5
--> $DIR/defaulted-never-note.rs:27:5
|
LL | fn foo<T: ImplementedForUnitButNotNever>(_t: T) {}
| --- ----------------------------- required by this bound in `foo`
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/never_type/diverging-fallback-control-flow.rs
Expand Up @@ -11,6 +11,8 @@
// These represent current behavior, but are pretty dubious. I would
// like to revisit these and potentially change them. --nmatsakis

#![feature(never_type_fallback)]

trait BadDefault {
fn default() -> Self;
}
Expand Down
12 changes: 12 additions & 0 deletions src/test/ui/never_type/feature-gate-never_type_fallback.rs
@@ -0,0 +1,12 @@
// This is a feature gate test for `never_type_fallback`.
// It works by using a scenario where the type fall backs to `()` rather than ´!`
// in the case where `#![feature(never_type_fallback)]` would change it to `!`.

fn main() {}

trait T {}

fn should_ret_unit() -> impl T {
//~^ ERROR the trait bound `(): T` is not satisfied
panic!()
}
11 changes: 11 additions & 0 deletions src/test/ui/never_type/feature-gate-never_type_fallback.stderr
@@ -0,0 +1,11 @@
error[E0277]: the trait bound `(): T` is not satisfied
--> $DIR/feature-gate-never_type_fallback.rs:9:25
|
LL | fn should_ret_unit() -> impl T {
| ^^^^^^ the trait `T` is not implemented for `()`
|
= note: the return type of a function must have a statically known size

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
6 changes: 3 additions & 3 deletions src/test/ui/never_type/issue-13352.stderr
@@ -1,10 +1,10 @@
error[E0277]: cannot add `!` to `usize`
error[E0277]: cannot add `()` to `usize`
--> $DIR/issue-13352.rs:9:13
|
LL | 2_usize + (loop {});
| ^ no implementation for `usize + !`
| ^ no implementation for `usize + ()`
|
= help: the trait `std::ops::Add<!>` is not implemented for `usize`
= help: the trait `std::ops::Add<()>` is not implemented for `usize`

error: aborting due to previous error

Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/never_type/issue-2149.stderr
@@ -1,10 +1,10 @@
error[E0277]: cannot add `std::vec::Vec<B>` to `!`
error[E0277]: cannot add `std::vec::Vec<B>` to `()`
--> $DIR/issue-2149.rs:8:33
|
LL | for elt in self { r = r + f(*elt); }
| ^ no implementation for `! + std::vec::Vec<B>`
| ^ no implementation for `() + std::vec::Vec<B>`
|
= help: the trait `std::ops::Add<std::vec::Vec<B>>` is not implemented for `!`
= help: the trait `std::ops::Add<std::vec::Vec<B>>` is not implemented for `()`

error[E0599]: no method named `bind` found for type `[&str; 1]` in the current scope
--> $DIR/issue-2149.rs:13:12
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/reachable/unreachable-loop-patterns.rs
@@ -1,3 +1,4 @@
#![feature(never_type_fallback)]
#![feature(exhaustive_patterns)]

#![allow(unreachable_code)]
Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/reachable/unreachable-loop-patterns.stderr
@@ -1,17 +1,17 @@
error: unreachable pattern
--> $DIR/unreachable-loop-patterns.rs:17:9
--> $DIR/unreachable-loop-patterns.rs:18:9
|
LL | for _ in unimplemented!() as Void {}
| ^
|
note: lint level defined here
--> $DIR/unreachable-loop-patterns.rs:4:9
--> $DIR/unreachable-loop-patterns.rs:5:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^

error: unreachable pattern
--> $DIR/unreachable-loop-patterns.rs:17:14
--> $DIR/unreachable-loop-patterns.rs:18:14
|
LL | for _ in unimplemented!() as Void {}
| ^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
Expand Up @@ -4,7 +4,7 @@ error: concrete type differs from previous defining opaque type use
LL | / fn bar() -> Foo {
LL | | panic!()
LL | | }
| |_^ expected `&'static str`, got `!`
| |_^ expected `&'static str`, got `()`
|
note: previous use here
--> $DIR/different_defining_uses_never_type.rs:8:1
Expand All @@ -20,7 +20,7 @@ error: concrete type differs from previous defining opaque type use
LL | / fn boo() -> Foo {
LL | | loop {}
LL | | }
| |_^ expected `&'static str`, got `!`
| |_^ expected `&'static str`, got `()`
|
note: previous use here
--> $DIR/different_defining_uses_never_type.rs:8:1
Expand Down

0 comments on commit 6eb0627

Please sign in to comment.