From a4b7ed7a42c716ab9f05e351f003d589124fd55d Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:18:58 +0200 Subject: Adding upstream version 1.68.2+dfsg1. Signed-off-by: Daniel Baumann --- tests/ui/never_type/adjust_never.rs | 10 +++ tests/ui/never_type/auto-traits.rs | 18 ++++ .../ui/never_type/call-fn-never-arg-wrong-type.rs | 11 +++ .../never_type/call-fn-never-arg-wrong-type.stderr | 19 ++++ tests/ui/never_type/call-fn-never-arg.rs | 14 +++ tests/ui/never_type/cast-never.rs | 10 +++ .../defaulted-never-note.fallback.stderr | 20 +++++ tests/ui/never_type/defaulted-never-note.rs | 41 +++++++++ tests/ui/never_type/dispatch_from_dyn_zst.rs | 51 +++++++++++ .../never_type/diverging-fallback-control-flow.rs | 100 +++++++++++++++++++++ .../diverging-fallback-no-leak.fallback.stderr | 22 +++++ tests/ui/never_type/diverging-fallback-no-leak.rs | 19 ++++ .../diverging-fallback-unconstrained-return.rs | 37 ++++++++ tests/ui/never_type/diverging-tuple-parts-39485.rs | 15 ++++ .../never_type/diverging-tuple-parts-39485.stderr | 32 +++++++ tests/ui/never_type/exhaustive_patterns.rs | 21 +++++ tests/ui/never_type/exhaustive_patterns.stderr | 25 ++++++ tests/ui/never_type/expr-empty-ret.rs | 15 ++++ tests/ui/never_type/fallback-closure-ret.rs | 23 +++++ .../fallback-closure-wrap.fallback.stderr | 17 ++++ tests/ui/never_type/fallback-closure-wrap.rs | 30 +++++++ .../never_type/feature-gate-never_type_fallback.rs | 13 +++ .../feature-gate-never_type_fallback.stderr | 19 ++++ tests/ui/never_type/impl-for-never.rs | 27 ++++++ tests/ui/never_type/impl_trait_fallback.rs | 10 +++ tests/ui/never_type/impl_trait_fallback2.rs | 22 +++++ tests/ui/never_type/impl_trait_fallback2.stderr | 19 ++++ tests/ui/never_type/impl_trait_fallback3.rs | 15 ++++ tests/ui/never_type/impl_trait_fallback3.stderr | 9 ++ tests/ui/never_type/impl_trait_fallback4.rs | 24 +++++ tests/ui/never_type/impl_trait_fallback4.stderr | 9 ++ tests/ui/never_type/issue-10176.rs | 9 ++ tests/ui/never_type/issue-10176.stderr | 14 +++ tests/ui/never_type/issue-13352.rs | 9 ++ tests/ui/never_type/issue-13352.stderr | 16 ++++ tests/ui/never_type/issue-2149.rs | 15 ++++ tests/ui/never_type/issue-2149.stderr | 25 ++++++ tests/ui/never_type/issue-44402.rs | 33 +++++++ tests/ui/never_type/issue-51506.rs | 41 +++++++++ tests/ui/never_type/issue-51506.stderr | 16 ++++ tests/ui/never_type/issue-52443.rs | 14 +++ tests/ui/never_type/issue-52443.stderr | 73 +++++++++++++++ tests/ui/never_type/issue-5500-1.rs | 15 ++++ tests/ui/never_type/issue-96335.rs | 5 ++ tests/ui/never_type/issue-96335.stderr | 32 +++++++ tests/ui/never_type/never-assign-dead-code.rs | 12 +++ tests/ui/never_type/never-assign-dead-code.stderr | 33 +++++++ tests/ui/never_type/never-assign-wrong-type.rs | 8 ++ tests/ui/never_type/never-assign-wrong-type.stderr | 14 +++ tests/ui/never_type/never-associated-type.rs | 23 +++++ tests/ui/never_type/never-from-impl-is-reserved.rs | 12 +++ .../never_type/never-from-impl-is-reserved.stderr | 14 +++ tests/ui/never_type/never-result.rs | 21 +++++ tests/ui/never_type/never-type-arg.rs | 17 ++++ tests/ui/never_type/never-type-rvalues.rs | 38 ++++++++ ...er-value-fallback-issue-66757.nofallback.stderr | 13 +++ .../never_type/never-value-fallback-issue-66757.rs | 31 +++++++ tests/ui/never_type/never_coercions.rs | 12 +++ tests/ui/never_type/never_transmute_never.rs | 23 +++++ tests/ui/never_type/return-never-coerce.rs | 18 ++++ tests/ui/never_type/try_from.rs | 37 ++++++++ 61 files changed, 1360 insertions(+) create mode 100644 tests/ui/never_type/adjust_never.rs create mode 100644 tests/ui/never_type/auto-traits.rs create mode 100644 tests/ui/never_type/call-fn-never-arg-wrong-type.rs create mode 100644 tests/ui/never_type/call-fn-never-arg-wrong-type.stderr create mode 100644 tests/ui/never_type/call-fn-never-arg.rs create mode 100644 tests/ui/never_type/cast-never.rs create mode 100644 tests/ui/never_type/defaulted-never-note.fallback.stderr create mode 100644 tests/ui/never_type/defaulted-never-note.rs create mode 100644 tests/ui/never_type/dispatch_from_dyn_zst.rs create mode 100644 tests/ui/never_type/diverging-fallback-control-flow.rs create mode 100644 tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr create mode 100644 tests/ui/never_type/diverging-fallback-no-leak.rs create mode 100644 tests/ui/never_type/diverging-fallback-unconstrained-return.rs create mode 100644 tests/ui/never_type/diverging-tuple-parts-39485.rs create mode 100644 tests/ui/never_type/diverging-tuple-parts-39485.stderr create mode 100644 tests/ui/never_type/exhaustive_patterns.rs create mode 100644 tests/ui/never_type/exhaustive_patterns.stderr create mode 100644 tests/ui/never_type/expr-empty-ret.rs create mode 100644 tests/ui/never_type/fallback-closure-ret.rs create mode 100644 tests/ui/never_type/fallback-closure-wrap.fallback.stderr create mode 100644 tests/ui/never_type/fallback-closure-wrap.rs create mode 100644 tests/ui/never_type/feature-gate-never_type_fallback.rs create mode 100644 tests/ui/never_type/feature-gate-never_type_fallback.stderr create mode 100644 tests/ui/never_type/impl-for-never.rs create mode 100644 tests/ui/never_type/impl_trait_fallback.rs create mode 100644 tests/ui/never_type/impl_trait_fallback2.rs create mode 100644 tests/ui/never_type/impl_trait_fallback2.stderr create mode 100644 tests/ui/never_type/impl_trait_fallback3.rs create mode 100644 tests/ui/never_type/impl_trait_fallback3.stderr create mode 100644 tests/ui/never_type/impl_trait_fallback4.rs create mode 100644 tests/ui/never_type/impl_trait_fallback4.stderr create mode 100644 tests/ui/never_type/issue-10176.rs create mode 100644 tests/ui/never_type/issue-10176.stderr create mode 100644 tests/ui/never_type/issue-13352.rs create mode 100644 tests/ui/never_type/issue-13352.stderr create mode 100644 tests/ui/never_type/issue-2149.rs create mode 100644 tests/ui/never_type/issue-2149.stderr create mode 100644 tests/ui/never_type/issue-44402.rs create mode 100644 tests/ui/never_type/issue-51506.rs create mode 100644 tests/ui/never_type/issue-51506.stderr create mode 100644 tests/ui/never_type/issue-52443.rs create mode 100644 tests/ui/never_type/issue-52443.stderr create mode 100644 tests/ui/never_type/issue-5500-1.rs create mode 100644 tests/ui/never_type/issue-96335.rs create mode 100644 tests/ui/never_type/issue-96335.stderr create mode 100644 tests/ui/never_type/never-assign-dead-code.rs create mode 100644 tests/ui/never_type/never-assign-dead-code.stderr create mode 100644 tests/ui/never_type/never-assign-wrong-type.rs create mode 100644 tests/ui/never_type/never-assign-wrong-type.stderr create mode 100644 tests/ui/never_type/never-associated-type.rs create mode 100644 tests/ui/never_type/never-from-impl-is-reserved.rs create mode 100644 tests/ui/never_type/never-from-impl-is-reserved.stderr create mode 100644 tests/ui/never_type/never-result.rs create mode 100644 tests/ui/never_type/never-type-arg.rs create mode 100644 tests/ui/never_type/never-type-rvalues.rs create mode 100644 tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr create mode 100644 tests/ui/never_type/never-value-fallback-issue-66757.rs create mode 100644 tests/ui/never_type/never_coercions.rs create mode 100644 tests/ui/never_type/never_transmute_never.rs create mode 100644 tests/ui/never_type/return-never-coerce.rs create mode 100644 tests/ui/never_type/try_from.rs (limited to 'tests/ui/never_type') diff --git a/tests/ui/never_type/adjust_never.rs b/tests/ui/never_type/adjust_never.rs new file mode 100644 index 000000000..0d7d2c0ed --- /dev/null +++ b/tests/ui/never_type/adjust_never.rs @@ -0,0 +1,10 @@ +// Test that a variable of type ! can coerce to another type. + +// check-pass + +#![feature(never_type)] + +fn main() { + let x: ! = panic!(); + let y: u32 = x; +} diff --git a/tests/ui/never_type/auto-traits.rs b/tests/ui/never_type/auto-traits.rs new file mode 100644 index 000000000..42ede708e --- /dev/null +++ b/tests/ui/never_type/auto-traits.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(auto_traits)] +#![feature(negative_impls)] +#![feature(never_type)] + +fn main() { + enum Void {} + + auto trait Auto {} + fn assert_auto() {} + assert_auto::(); + assert_auto::(); + + fn assert_send() {} + assert_send::(); + assert_send::(); +} diff --git a/tests/ui/never_type/call-fn-never-arg-wrong-type.rs b/tests/ui/never_type/call-fn-never-arg-wrong-type.rs new file mode 100644 index 000000000..d06637e74 --- /dev/null +++ b/tests/ui/never_type/call-fn-never-arg-wrong-type.rs @@ -0,0 +1,11 @@ +// Test that we can't pass other types for ! + +#![feature(never_type)] + +fn foo(x: !) -> ! { + x +} + +fn main() { + foo("wow"); //~ ERROR mismatched types +} diff --git a/tests/ui/never_type/call-fn-never-arg-wrong-type.stderr b/tests/ui/never_type/call-fn-never-arg-wrong-type.stderr new file mode 100644 index 000000000..fa3db33c9 --- /dev/null +++ b/tests/ui/never_type/call-fn-never-arg-wrong-type.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/call-fn-never-arg-wrong-type.rs:10:9 + | +LL | foo("wow"); + | --- ^^^^^ expected `!`, found `&str` + | | + | arguments to this function are incorrect + | + = note: expected type `!` + found reference `&'static str` +note: function defined here + --> $DIR/call-fn-never-arg-wrong-type.rs:5:4 + | +LL | fn foo(x: !) -> ! { + | ^^^ ---- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/call-fn-never-arg.rs b/tests/ui/never_type/call-fn-never-arg.rs new file mode 100644 index 000000000..9d355817e --- /dev/null +++ b/tests/ui/never_type/call-fn-never-arg.rs @@ -0,0 +1,14 @@ +// Test that we can use a ! for an argument of type ! + +// check-pass + +#![feature(never_type)] +#![allow(unreachable_code)] + +fn foo(x: !) -> ! { + x +} + +fn main() { + foo(panic!("wowzers!")) +} diff --git a/tests/ui/never_type/cast-never.rs b/tests/ui/never_type/cast-never.rs new file mode 100644 index 000000000..0139ebe46 --- /dev/null +++ b/tests/ui/never_type/cast-never.rs @@ -0,0 +1,10 @@ +// Test that we can explicitly cast ! to another type + +// check-pass + +#![feature(never_type)] + +fn main() { + let x: ! = panic!(); + let y: u32 = x as u32; +} diff --git a/tests/ui/never_type/defaulted-never-note.fallback.stderr b/tests/ui/never_type/defaulted-never-note.fallback.stderr new file mode 100644 index 000000000..283aca1b0 --- /dev/null +++ b/tests/ui/never_type/defaulted-never-note.fallback.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied + --> $DIR/defaulted-never-note.rs:30:9 + | +LL | foo(_x); + | --- ^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!` + | | + | required by a bound introduced by this call + | + = help: the trait `ImplementedForUnitButNotNever` is implemented for `()` + = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) + = help: did you intend to use the type `()` here instead? +note: required by a bound in `foo` + --> $DIR/defaulted-never-note.rs:25:11 + | +LL | fn foo(_t: T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/defaulted-never-note.rs b/tests/ui/never_type/defaulted-never-note.rs new file mode 100644 index 000000000..d30ffcd38 --- /dev/null +++ b/tests/ui/never_type/defaulted-never-note.rs @@ -0,0 +1,41 @@ +// revisions: nofallback fallback +//[nofallback] run-pass +//[fallback] check-fail + +// We need to opt into the `never_type_fallback` feature +// to trigger the requirement that this is testing. +#![cfg_attr(fallback, feature(never_type, never_type_fallback))] + +#![allow(unused)] + +trait Deserialize: Sized { + fn deserialize() -> Result; +} + +impl Deserialize for () { + fn deserialize() -> Result<(), String> { + Ok(()) + } +} + +trait ImplementedForUnitButNotNever {} + +impl ImplementedForUnitButNotNever for () {} + +fn foo(_t: T) {} +//[fallback]~^ NOTE required by this bound in `foo` +//[fallback]~| NOTE required by a bound in `foo` +fn smeg() { + let _x = return; + foo(_x); + //[fallback]~^ ERROR the trait bound + //[fallback]~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented + //[fallback]~| HELP trait `ImplementedForUnitButNotNever` is implemented for `()` + //[fallback]~| NOTE this error might have been caused + //[fallback]~| NOTE required by a bound introduced by this call + //[fallback]~| HELP did you intend +} + +fn main() { + smeg(); +} diff --git a/tests/ui/never_type/dispatch_from_dyn_zst.rs b/tests/ui/never_type/dispatch_from_dyn_zst.rs new file mode 100644 index 000000000..764f58ce9 --- /dev/null +++ b/tests/ui/never_type/dispatch_from_dyn_zst.rs @@ -0,0 +1,51 @@ +// run-pass + +#![feature(unsize, dispatch_from_dyn, never_type)] + +#![allow(dead_code)] + +use std::{ + ops::DispatchFromDyn, + marker::{Unsize, PhantomData}, +}; + +struct Zst; +struct NestedZst(PhantomData<()>, Zst); + + +struct WithUnit(Box, ()); +impl DispatchFromDyn> for WithUnit + where T: Unsize {} + +struct WithPhantom(Box, PhantomData<()>); +impl DispatchFromDyn> for WithPhantom + where T: Unsize {} + +struct WithNever(Box, !); +impl DispatchFromDyn> for WithNever + where T: Unsize {} + +struct WithZst(Box, Zst); +impl DispatchFromDyn> for WithZst + where T: Unsize {} + +struct WithNestedZst(Box, NestedZst); +impl DispatchFromDyn> for WithNestedZst + where T: Unsize {} + + +struct Generic(Box, A); +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn>> + for Generic> + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} +impl DispatchFromDyn> for Generic + where T: Unsize {} + + +fn main() {} diff --git a/tests/ui/never_type/diverging-fallback-control-flow.rs b/tests/ui/never_type/diverging-fallback-control-flow.rs new file mode 100644 index 000000000..45a3362fa --- /dev/null +++ b/tests/ui/never_type/diverging-fallback-control-flow.rs @@ -0,0 +1,100 @@ +// revisions: nofallback fallback +// run-pass + +#![allow(dead_code)] +#![allow(unused_assignments)] +#![allow(unused_variables)] +#![allow(unreachable_code)] +// Test various cases where we permit an unconstrained variable +// to fallback based on control-flow. In all of these cases, +// the type variable winds up being the target of both a `!` coercion +// and a coercion from a non-`!` variable, and hence falls back to `()`. +#![cfg_attr(fallback, feature(never_type, never_type_fallback))] + +trait UnitDefault { + fn default() -> Self; +} + +impl UnitDefault for u32 { + fn default() -> Self { + 0 + } +} + +impl UnitDefault for () { + fn default() -> () { + panic!() + } +} + +fn assignment() { + let x; + + if true { + x = UnitDefault::default(); + } else { + x = return; + } +} + +fn assignment_rev() { + let x; + + if true { + x = return; + } else { + x = UnitDefault::default(); + } +} + +fn if_then_else() { + let _x = if true { + UnitDefault::default() + } else { + return; + }; +} + +fn if_then_else_rev() { + let _x = if true { + return; + } else { + UnitDefault::default() + }; +} + +fn match_arm() { + let _x = match Ok(UnitDefault::default()) { + Ok(v) => v, + Err(()) => return, + }; +} + +fn match_arm_rev() { + let _x = match Ok(UnitDefault::default()) { + Err(()) => return, + Ok(v) => v, + }; +} + +fn loop_break() { + let _x = loop { + if false { + break return; + } else { + break UnitDefault::default(); + } + }; +} + +fn loop_break_rev() { + let _x = loop { + if false { + break return; + } else { + break UnitDefault::default(); + } + }; +} + +fn main() {} diff --git a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr new file mode 100644 index 000000000..3215c4669 --- /dev/null +++ b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `!: Test` is not satisfied + --> $DIR/diverging-fallback-no-leak.rs:17:23 + | +LL | unconstrained_arg(return); + | ----------------- ^^^^^^ the trait `Test` is not implemented for `!` + | | + | required by a bound introduced by this call + | + = help: the following other types implement trait `Test`: + () + i32 + = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) + = help: did you intend to use the type `()` here instead? +note: required by a bound in `unconstrained_arg` + --> $DIR/diverging-fallback-no-leak.rs:12:25 + | +LL | fn unconstrained_arg(_: T) {} + | ^^^^ required by this bound in `unconstrained_arg` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/diverging-fallback-no-leak.rs b/tests/ui/never_type/diverging-fallback-no-leak.rs new file mode 100644 index 000000000..03478e19d --- /dev/null +++ b/tests/ui/never_type/diverging-fallback-no-leak.rs @@ -0,0 +1,19 @@ +// revisions: nofallback fallback +//[nofallback] check-pass + +#![cfg_attr(fallback, feature(never_type, never_type_fallback))] + +fn make_unit() {} + +trait Test {} +impl Test for i32 {} +impl Test for () {} + +fn unconstrained_arg(_: T) {} + +fn main() { + // Here the type variable falls back to `!`, + // and hence we get a type error. + unconstrained_arg(return); + //[fallback]~^ ERROR trait bound `!: Test` is not satisfied +} diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs new file mode 100644 index 000000000..7ea97126f --- /dev/null +++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs @@ -0,0 +1,37 @@ +// Variant of diverging-falllback-control-flow that tests +// the specific case of a free function with an unconstrained +// return type. This captures the pattern we saw in the wild +// in the objc crate, where changing the fallback from `!` to `()` +// resulted in unsoundness. +// +// check-pass + +// revisions: nofallback fallback + +#![cfg_attr(fallback, feature(never_type, never_type_fallback))] + + +fn make_unit() {} + +trait UnitReturn {} +impl UnitReturn for i32 {} +impl UnitReturn for () {} + +fn unconstrained_return() -> T { + unsafe { + let make_unit_fn: fn() = make_unit; + let ffi: fn() -> T = std::mem::transmute(make_unit_fn); + ffi() + } +} + +fn main() { + // In Ye Olde Days, the `T` parameter of `unconstrained_return` + // winds up "entangled" with the `!` type that results from + // `panic!`, and hence falls back to `()`. This is kind of unfortunate + // and unexpected. When we introduced the `!` type, the original + // idea was to change that fallback to `!`, but that would have resulted + // in this code no longer compiling (or worse, in some cases it injected + // unsound results). + let _ = if true { unconstrained_return() } else { panic!() }; +} diff --git a/tests/ui/never_type/diverging-tuple-parts-39485.rs b/tests/ui/never_type/diverging-tuple-parts-39485.rs new file mode 100644 index 000000000..0cde61193 --- /dev/null +++ b/tests/ui/never_type/diverging-tuple-parts-39485.rs @@ -0,0 +1,15 @@ +// After #39485, this test used to pass, but that change was reverted +// due to numerous inference failures like #39808, so it now fails +// again. #39485 made it so that diverging types never propagate +// upward; but we now do propagate such types upward in many more +// cases. + +fn g() { + &panic!() //~ ERROR mismatched types +} + +fn f() -> isize { + (return 1, return 2) //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/never_type/diverging-tuple-parts-39485.stderr b/tests/ui/never_type/diverging-tuple-parts-39485.stderr new file mode 100644 index 000000000..52d07ae17 --- /dev/null +++ b/tests/ui/never_type/diverging-tuple-parts-39485.stderr @@ -0,0 +1,32 @@ +error[E0308]: mismatched types + --> $DIR/diverging-tuple-parts-39485.rs:8:5 + | +LL | &panic!() + | ^^^^^^^^^ expected `()`, found reference + | + = note: expected unit type `()` + found reference `&_` +help: a return type might be missing here + | +LL | fn g() -> _ { + | ++++ +help: consider removing the borrow + | +LL - &panic!() +LL + panic!() + | + +error[E0308]: mismatched types + --> $DIR/diverging-tuple-parts-39485.rs:12:5 + | +LL | fn f() -> isize { + | ----- expected `isize` because of return type +LL | (return 1, return 2) + | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple + | + = note: expected type `isize` + found tuple `(!, !)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/exhaustive_patterns.rs b/tests/ui/never_type/exhaustive_patterns.rs new file mode 100644 index 000000000..2e23fa182 --- /dev/null +++ b/tests/ui/never_type/exhaustive_patterns.rs @@ -0,0 +1,21 @@ +// check-fail +// known-bug: #104034 + +#![feature(exhaustive_patterns, never_type)] + +mod inner { + pub struct Wrapper(T); +} + +enum Either { + A(A), + B(inner::Wrapper), +} + +fn foo() -> Either<(), !> { + Either::A(()) +} + +fn main() { + let Either::A(()) = foo(); +} diff --git a/tests/ui/never_type/exhaustive_patterns.stderr b/tests/ui/never_type/exhaustive_patterns.stderr new file mode 100644 index 000000000..40c7c1d10 --- /dev/null +++ b/tests/ui/never_type/exhaustive_patterns.stderr @@ -0,0 +1,25 @@ +error[E0005]: refutable pattern in local binding + --> $DIR/exhaustive_patterns.rs:20:9 + | +LL | let Either::A(()) = foo(); + | ^^^^^^^^^^^^^ pattern `Either::B(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +note: `Either<(), !>` defined here + --> $DIR/exhaustive_patterns.rs:10:6 + | +LL | enum Either { + | ^^^^^^ +LL | A(A), +LL | B(inner::Wrapper), + | - not covered + = note: the matched value is of type `Either<(), !>` +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let Either::A(()) = foo() { todo!() } + | ++ ~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/never_type/expr-empty-ret.rs b/tests/ui/never_type/expr-empty-ret.rs new file mode 100644 index 000000000..ce8ffaf94 --- /dev/null +++ b/tests/ui/never_type/expr-empty-ret.rs @@ -0,0 +1,15 @@ +// run-pass + +#![allow(dead_code)] +// Issue #521 + +// pretty-expanded FIXME #23616 + +fn f() { + let _x = match true { + true => { 10 } + false => { return } + }; +} + +pub fn main() { } diff --git a/tests/ui/never_type/fallback-closure-ret.rs b/tests/ui/never_type/fallback-closure-ret.rs new file mode 100644 index 000000000..5c8ce48cb --- /dev/null +++ b/tests/ui/never_type/fallback-closure-ret.rs @@ -0,0 +1,23 @@ +// This test verifies that never type fallback preserves the following code in a +// compiling state. This pattern is fairly common in the wild, notably seen in +// wasmtime v0.16. Typically this is some closure wrapper that expects a +// collection of 'known' signatures, and -> ! is not included in that set. +// +// This test is specifically targeted by the unit type fallback when +// encountering a set of obligations like `?T: Foo` and `Trait::Projection = +// ?T`. In the code below, these are `R: Bar` and `Fn::Output = R`. +// +// revisions: nofallback fallback +// check-pass + +#![cfg_attr(fallback, feature(never_type_fallback))] + +trait Bar { } +impl Bar for () { } +impl Bar for u32 { } + +fn foo(_: impl Fn() -> R) {} + +fn main() { + foo(|| panic!()); +} diff --git a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr new file mode 100644 index 000000000..a0f790dba --- /dev/null +++ b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -0,0 +1,17 @@ +error[E0271]: expected `[closure@fallback-closure-wrap.rs:18:40]` to be a closure that returns `()`, but it returns `!` + --> $DIR/fallback-closure-wrap.rs:18:31 + | +LL | let error = Closure::wrap(Box::new(move || { + | _______________________________^ +LL | | +LL | | panic!("Can't connect to server."); +LL | | }) as Box); + | |______^ expected `()`, found `!` + | + = note: expected unit type `()` + found type `!` + = note: required for the cast from `[closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47]` to the object type `dyn FnMut()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/never_type/fallback-closure-wrap.rs b/tests/ui/never_type/fallback-closure-wrap.rs new file mode 100644 index 000000000..f88355bb2 --- /dev/null +++ b/tests/ui/never_type/fallback-closure-wrap.rs @@ -0,0 +1,30 @@ +// This is a minified example from Crater breakage observed when attempting to +// stabilize never type, nstoddard/webgl-gui @ 22f0169f. +// +// This particular test case currently fails as the inference to `()` rather +// than `!` happens as a result of an `as` cast, which is not currently tracked. +// Crater did not find many cases of this occurring, but it is included for +// awareness. +// +// revisions: nofallback fallback +//[nofallback] check-pass +//[fallback] check-fail + +#![cfg_attr(fallback, feature(never_type_fallback))] + +use std::marker::PhantomData; + +fn main() { + let error = Closure::wrap(Box::new(move || { + //[fallback]~^ to be a closure that returns `()`, but it returns `!` + panic!("Can't connect to server."); + }) as Box); +} + +struct Closure(PhantomData); + +impl Closure { + fn wrap(data: Box) -> Closure { + todo!() + } +} diff --git a/tests/ui/never_type/feature-gate-never_type_fallback.rs b/tests/ui/never_type/feature-gate-never_type_fallback.rs new file mode 100644 index 000000000..7d0208411 --- /dev/null +++ b/tests/ui/never_type/feature-gate-never_type_fallback.rs @@ -0,0 +1,13 @@ +// 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() { + foo(panic!()) //~ ERROR +} + +fn foo(_: impl T) {} diff --git a/tests/ui/never_type/feature-gate-never_type_fallback.stderr b/tests/ui/never_type/feature-gate-never_type_fallback.stderr new file mode 100644 index 000000000..2db1cc4b7 --- /dev/null +++ b/tests/ui/never_type/feature-gate-never_type_fallback.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `(): T` is not satisfied + --> $DIR/feature-gate-never_type_fallback.rs:10:9 + | +LL | foo(panic!()) + | --- ^^^^^^^^ + | | | + | | the trait `T` is not implemented for `()` + | | this tail expression is of type `()` + | required by a bound introduced by this call + | +note: required by a bound in `foo` + --> $DIR/feature-gate-never_type_fallback.rs:13:16 + | +LL | fn foo(_: impl T) {} + | ^ required by this bound in `foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/impl-for-never.rs b/tests/ui/never_type/impl-for-never.rs new file mode 100644 index 000000000..9423f0885 --- /dev/null +++ b/tests/ui/never_type/impl-for-never.rs @@ -0,0 +1,27 @@ +// run-pass + +#![feature(never_type)] + +// Test that we can call static methods on ! both directly and when it appears in a generic + +trait StringifyType { + fn stringify_type() -> &'static str; +} + +impl StringifyType for ! { + fn stringify_type() -> &'static str { + "!" + } +} + +fn maybe_stringify(opt: Option) -> &'static str { + match opt { + Some(_) => T::stringify_type(), + None => "none", + } +} + +fn main() { + println!("! is {}", ::stringify_type()); + println!("None is {}", maybe_stringify(None::)); +} diff --git a/tests/ui/never_type/impl_trait_fallback.rs b/tests/ui/never_type/impl_trait_fallback.rs new file mode 100644 index 000000000..cc9520c1b --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback.rs @@ -0,0 +1,10 @@ +// check-pass + +fn main() {} + +trait T {} +impl T for () {} + +fn should_ret_unit() -> impl T { + panic!() +} diff --git a/tests/ui/never_type/impl_trait_fallback2.rs b/tests/ui/never_type/impl_trait_fallback2.rs new file mode 100644 index 000000000..12c187b9e --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback2.rs @@ -0,0 +1,22 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait T {} +impl T for i32 {} + +fn should_ret_unit() -> impl T { + //~^ ERROR `(): T` is not satisfied + panic!() +} + +type Foo = impl T; + +fn a() -> Foo { + //~^ ERROR `(): T` is not satisfied + panic!() +} + +fn b() -> Foo { + 42 +} diff --git a/tests/ui/never_type/impl_trait_fallback2.stderr b/tests/ui/never_type/impl_trait_fallback2.stderr new file mode 100644 index 000000000..78cc83bdb --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback2.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `(): T` is not satisfied + --> $DIR/impl_trait_fallback2.rs:8:25 + | +LL | fn should_ret_unit() -> impl T { + | ^^^^^^ the trait `T` is not implemented for `()` + | + = help: the trait `T` is implemented for `i32` + +error[E0277]: the trait bound `(): T` is not satisfied + --> $DIR/impl_trait_fallback2.rs:15:11 + | +LL | fn a() -> Foo { + | ^^^ the trait `T` is not implemented for `()` + | + = help: the trait `T` is implemented for `i32` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/impl_trait_fallback3.rs b/tests/ui/never_type/impl_trait_fallback3.rs new file mode 100644 index 000000000..ed645b823 --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback3.rs @@ -0,0 +1,15 @@ +#![feature(type_alias_impl_trait)] + +fn main() {} + +trait T { + type Assoc; +} + +type Foo = impl T; + +fn a() -> Foo { + //~^ ERROR the trait bound `(): T` is not satisfied + // This is not a defining use, it doesn't actually constrain the opaque type. + panic!() +} diff --git a/tests/ui/never_type/impl_trait_fallback3.stderr b/tests/ui/never_type/impl_trait_fallback3.stderr new file mode 100644 index 000000000..5d5d216fb --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback3.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `(): T` is not satisfied + --> $DIR/impl_trait_fallback3.rs:11:11 + | +LL | fn a() -> Foo { + | ^^^ the trait `T` is not implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/impl_trait_fallback4.rs b/tests/ui/never_type/impl_trait_fallback4.rs new file mode 100644 index 000000000..fe62773fa --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback4.rs @@ -0,0 +1,24 @@ +#![feature(type_alias_impl_trait)] + +trait T { + type Assoc: Cake; +} + +trait Cake: std::fmt::Display { + fn cake() -> Self; +} + +type Foo = impl T; + +fn foo() -> impl T { + //~^ ERROR `(): T` is not satisfied + panic!() +} + +fn a() -> Foo { + foo() +} + +fn main() { + println!("{}", ::Assoc::cake()); +} diff --git a/tests/ui/never_type/impl_trait_fallback4.stderr b/tests/ui/never_type/impl_trait_fallback4.stderr new file mode 100644 index 000000000..f2e216e90 --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback4.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `(): T` is not satisfied + --> $DIR/impl_trait_fallback4.rs:13:13 + | +LL | fn foo() -> impl T { + | ^^^^^^ the trait `T` is not implemented for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/issue-10176.rs b/tests/ui/never_type/issue-10176.rs new file mode 100644 index 000000000..6277aa05e --- /dev/null +++ b/tests/ui/never_type/issue-10176.rs @@ -0,0 +1,9 @@ +fn f() -> isize { + (return 1, return 2) +//~^ ERROR mismatched types +//~| expected type `isize` +//~| found tuple `(!, !)` +//~| expected `isize`, found tuple +} + +fn main() {} diff --git a/tests/ui/never_type/issue-10176.stderr b/tests/ui/never_type/issue-10176.stderr new file mode 100644 index 000000000..cd5361ffa --- /dev/null +++ b/tests/ui/never_type/issue-10176.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-10176.rs:2:5 + | +LL | fn f() -> isize { + | ----- expected `isize` because of return type +LL | (return 1, return 2) + | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found tuple + | + = note: expected type `isize` + found tuple `(!, !)` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/issue-13352.rs b/tests/ui/never_type/issue-13352.rs new file mode 100644 index 000000000..9c884a33c --- /dev/null +++ b/tests/ui/never_type/issue-13352.rs @@ -0,0 +1,9 @@ +fn foo(_: Box) {} + +fn main() { + foo(loop { + std::process::exit(0); + }); + 2_usize + (loop {}); + //~^ ERROR E0277 +} diff --git a/tests/ui/never_type/issue-13352.stderr b/tests/ui/never_type/issue-13352.stderr new file mode 100644 index 000000000..2d22da0b4 --- /dev/null +++ b/tests/ui/never_type/issue-13352.stderr @@ -0,0 +1,16 @@ +error[E0277]: cannot add `()` to `usize` + --> $DIR/issue-13352.rs:7:13 + | +LL | 2_usize + (loop {}); + | ^ no implementation for `usize + ()` + | + = help: the trait `Add<()>` is not implemented for `usize` + = help: the following other types implement trait `Add`: + <&'a usize as Add> + <&usize as Add<&usize>> + > + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/issue-2149.rs b/tests/ui/never_type/issue-2149.rs new file mode 100644 index 000000000..d6426d2cf --- /dev/null +++ b/tests/ui/never_type/issue-2149.rs @@ -0,0 +1,15 @@ +trait VecMonad { + fn bind(&self, f: F) where F: FnMut(A) -> Vec; +} + +impl VecMonad for Vec { + fn bind(&self, mut f: F) where F: FnMut(A) -> Vec { + let mut r = panic!(); + for elt in self { r = r + f(*elt); } + //~^ ERROR E0277 + } +} +fn main() { + ["hi"].bind(|x| [x] ); + //~^ ERROR no method named `bind` found +} diff --git a/tests/ui/never_type/issue-2149.stderr b/tests/ui/never_type/issue-2149.stderr new file mode 100644 index 000000000..58fe2edb1 --- /dev/null +++ b/tests/ui/never_type/issue-2149.stderr @@ -0,0 +1,25 @@ +error[E0277]: cannot add `Vec` to `()` + --> $DIR/issue-2149.rs:8:33 + | +LL | for elt in self { r = r + f(*elt); } + | ^ no implementation for `() + Vec` + | + = help: the trait `Add>` is not implemented for `()` + +error[E0599]: no method named `bind` found for array `[&str; 1]` in the current scope + --> $DIR/issue-2149.rs:13:12 + | +LL | ["hi"].bind(|x| [x] ); + | ^^^^ method not found in `[&str; 1]` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `VecMonad` defines an item `bind`, perhaps you need to implement it + --> $DIR/issue-2149.rs:1:1 + | +LL | trait VecMonad { + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/issue-44402.rs b/tests/ui/never_type/issue-44402.rs new file mode 100644 index 000000000..699e480df --- /dev/null +++ b/tests/ui/never_type/issue-44402.rs @@ -0,0 +1,33 @@ +// check-pass + +#![allow(dead_code)] +#![feature(never_type)] +#![feature(exhaustive_patterns)] + +// Regression test for inhabitedness check. The old +// cache used to cause us to incorrectly decide +// that `test_b` was invalid. + +struct Foo { + field1: !, + field2: Option<&'static Bar>, +} + +struct Bar { + field1: &'static Foo +} + +fn test_a() { + let x: Option = None; + match x { None => () } +} + +fn test_b() { + let x: Option = None; + match x { + Some(_) => (), + None => () + } +} + +fn main() { } diff --git a/tests/ui/never_type/issue-51506.rs b/tests/ui/never_type/issue-51506.rs new file mode 100644 index 000000000..d0fe6a0f5 --- /dev/null +++ b/tests/ui/never_type/issue-51506.rs @@ -0,0 +1,41 @@ +#![feature(never_type, specialization)] +#![allow(incomplete_features)] + +use std::iter::{self, Empty}; + +trait Trait { + type Out: Iterator; + + fn f(&self) -> Option; +} + +impl Trait for T { + default type Out = !; //~ ERROR: `!` is not an iterator + + default fn f(&self) -> Option { + None + } +} + +struct X; + +impl Trait for X { + type Out = Empty; + + fn f(&self) -> Option { + Some(iter::empty()) + } +} + +fn f(a: T) { + if let Some(iter) = a.f() { + println!("Some"); + for x in iter { + println!("x = {}", x); + } + } +} + +pub fn main() { + f(10); +} diff --git a/tests/ui/never_type/issue-51506.stderr b/tests/ui/never_type/issue-51506.stderr new file mode 100644 index 000000000..293ec3a72 --- /dev/null +++ b/tests/ui/never_type/issue-51506.stderr @@ -0,0 +1,16 @@ +error[E0277]: `!` is not an iterator + --> $DIR/issue-51506.rs:13:24 + | +LL | default type Out = !; + | ^ `!` is not an iterator + | + = help: the trait `Iterator` is not implemented for `!` +note: required by a bound in `Trait::Out` + --> $DIR/issue-51506.rs:7:15 + | +LL | type Out: Iterator; + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::Out` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/issue-52443.rs b/tests/ui/never_type/issue-52443.rs new file mode 100644 index 000000000..0498a8a16 --- /dev/null +++ b/tests/ui/never_type/issue-52443.rs @@ -0,0 +1,14 @@ +fn main() { + [(); & { loop { continue } } ]; //~ ERROR mismatched types + + [(); loop { break }]; //~ ERROR mismatched types + + [(); {while true {break}; 0}]; + //~^ WARN denote infinite loops with + + [(); { for _ in 0usize.. {}; 0}]; + //~^ ERROR `for` is not allowed in a `const` + //~| ERROR cannot convert + //~| ERROR mutable references + //~| ERROR cannot call +} diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/issue-52443.stderr new file mode 100644 index 000000000..33b7a9185 --- /dev/null +++ b/tests/ui/never_type/issue-52443.stderr @@ -0,0 +1,73 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/issue-52443.rs:6:11 + | +LL | [(); {while true {break}; 0}]; + | ^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +error[E0658]: `for` is not allowed in a `const` + --> $DIR/issue-52443.rs:9:12 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #87575 for more information + = help: add `#![feature(const_for)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/issue-52443.rs:2:10 + | +LL | [(); & { loop { continue } } ]; + | ^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference + | + = note: expected type `usize` + found reference `&_` +help: consider removing the borrow + | +LL - [(); & { loop { continue } } ]; +LL + [(); { loop { continue } } ]; + | + +error[E0308]: mismatched types + --> $DIR/issue-52443.rs:4:17 + | +LL | [(); loop { break }]; + | ^^^^^ + | | + | expected `usize`, found `()` + | help: give it a value of the expected type: `break 42` + +error[E0015]: cannot convert `RangeFrom` into an iterator in constants + --> $DIR/issue-52443.rs:9:21 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^ + | +note: impl defined here, but it is not `const` + --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error[E0658]: mutable references are not allowed in constants + --> $DIR/issue-52443.rs:9:21 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^ + | + = note: see issue #57349 for more information + = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable + +error[E0015]: cannot call non-const fn ` as Iterator>::next` in constants + --> $DIR/issue-52443.rs:9:21 + | +LL | [(); { for _ in 0usize.. {}; 0}]; + | ^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + +error: aborting due to 6 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0015, E0308, E0658. +For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/never_type/issue-5500-1.rs b/tests/ui/never_type/issue-5500-1.rs new file mode 100644 index 000000000..98d6e1a14 --- /dev/null +++ b/tests/ui/never_type/issue-5500-1.rs @@ -0,0 +1,15 @@ +// MIR doesn't generate an error because the assignment isn't reachable. This +// is OK because the test is here to check that the compiler doesn't ICE (cf. +// #5500). + +// check-pass + +struct TrieMapIterator<'a> { + node: &'a usize +} + +fn main() { + let a = 5; + let _iter = TrieMapIterator{node: &a}; + _iter.node = &panic!() +} diff --git a/tests/ui/never_type/issue-96335.rs b/tests/ui/never_type/issue-96335.rs new file mode 100644 index 000000000..411a7c9df --- /dev/null +++ b/tests/ui/never_type/issue-96335.rs @@ -0,0 +1,5 @@ +fn main() { + 0.....{loop{}1}; + //~^ ERROR unexpected token + //~| ERROR mismatched types +} diff --git a/tests/ui/never_type/issue-96335.stderr b/tests/ui/never_type/issue-96335.stderr new file mode 100644 index 000000000..e148b983e --- /dev/null +++ b/tests/ui/never_type/issue-96335.stderr @@ -0,0 +1,32 @@ +error: unexpected token: `...` + --> $DIR/issue-96335.rs:2:6 + | +LL | 0.....{loop{}1}; + | ^^^ + | +help: use `..` for an exclusive range + | +LL | 0....{loop{}1}; + | ~~ +help: or `..=` for an inclusive range + | +LL | 0..=..{loop{}1}; + | ~~~ + +error[E0308]: mismatched types + --> $DIR/issue-96335.rs:2:9 + | +LL | 0.....{loop{}1}; + | ----^^^^^^^^^^^ + | | | + | | expected integer, found struct `RangeTo` + | arguments to this function are incorrect + | + = note: expected type `{integer}` + found struct `RangeTo<{integer}>` +note: associated function defined here + --> $SRC_DIR/core/src/ops/range.rs:LL:COL + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/never-assign-dead-code.rs b/tests/ui/never_type/never-assign-dead-code.rs new file mode 100644 index 000000000..7bb7c8709 --- /dev/null +++ b/tests/ui/never_type/never-assign-dead-code.rs @@ -0,0 +1,12 @@ +// Test that an assignment of type ! makes the rest of the block dead code. + +// check-pass + +#![feature(never_type)] +#![warn(unused)] + +fn main() { + let x: ! = panic!("aah"); //~ WARN unused + drop(x); //~ WARN unreachable + //~^ WARN unreachable +} diff --git a/tests/ui/never_type/never-assign-dead-code.stderr b/tests/ui/never_type/never-assign-dead-code.stderr new file mode 100644 index 000000000..521b82023 --- /dev/null +++ b/tests/ui/never_type/never-assign-dead-code.stderr @@ -0,0 +1,33 @@ +warning: unreachable statement + --> $DIR/never-assign-dead-code.rs:10:5 + | +LL | let x: ! = panic!("aah"); + | ------------- any code following this expression is unreachable +LL | drop(x); + | ^^^^^^^^ unreachable statement + | +note: the lint level is defined here + --> $DIR/never-assign-dead-code.rs:6:9 + | +LL | #![warn(unused)] + | ^^^^^^ + = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]` + +warning: unreachable call + --> $DIR/never-assign-dead-code.rs:10:5 + | +LL | drop(x); + | ^^^^ - any code following this expression is unreachable + | | + | unreachable call + +warning: unused variable: `x` + --> $DIR/never-assign-dead-code.rs:9:9 + | +LL | let x: ! = panic!("aah"); + | ^ help: if this is intentional, prefix it with an underscore: `_x` + | + = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]` + +warning: 3 warnings emitted + diff --git a/tests/ui/never_type/never-assign-wrong-type.rs b/tests/ui/never_type/never-assign-wrong-type.rs new file mode 100644 index 000000000..67e26f566 --- /dev/null +++ b/tests/ui/never_type/never-assign-wrong-type.rs @@ -0,0 +1,8 @@ +// Test that we can't use another type in place of ! + +#![feature(never_type)] +#![deny(warnings)] + +fn main() { + let x: ! = "hello"; //~ ERROR mismatched types +} diff --git a/tests/ui/never_type/never-assign-wrong-type.stderr b/tests/ui/never_type/never-assign-wrong-type.stderr new file mode 100644 index 000000000..ce34d9483 --- /dev/null +++ b/tests/ui/never_type/never-assign-wrong-type.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/never-assign-wrong-type.rs:7:16 + | +LL | let x: ! = "hello"; + | - ^^^^^^^ expected `!`, found `&str` + | | + | expected due to this + | + = note: expected type `!` + found reference `&'static str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/never-associated-type.rs b/tests/ui/never_type/never-associated-type.rs new file mode 100644 index 000000000..3bb917c93 --- /dev/null +++ b/tests/ui/never_type/never-associated-type.rs @@ -0,0 +1,23 @@ +// Test that we can use ! as an associated type. + +// check-pass + +#![feature(never_type)] + +trait Foo { + type Wow; + + fn smeg(&self) -> Self::Wow; +} + +struct Blah; +impl Foo for Blah { + type Wow = !; + fn smeg(&self) -> ! { + panic!("kapow!"); + } +} + +fn main() { + Blah.smeg(); +} diff --git a/tests/ui/never_type/never-from-impl-is-reserved.rs b/tests/ui/never_type/never-from-impl-is-reserved.rs new file mode 100644 index 000000000..9d16015bd --- /dev/null +++ b/tests/ui/never_type/never-from-impl-is-reserved.rs @@ -0,0 +1,12 @@ +// check that the `for T: From` impl is reserved + +#![feature(never_type)] + +pub struct MyFoo; +pub trait MyTrait {} + +impl MyTrait for MyFoo {} +// This will conflict with the first impl if we impl `for T: From`. +impl MyTrait for T where T: From {} //~ ERROR conflicting implementation + +fn main() {} diff --git a/tests/ui/never_type/never-from-impl-is-reserved.stderr b/tests/ui/never_type/never-from-impl-is-reserved.stderr new file mode 100644 index 000000000..f9f7c787e --- /dev/null +++ b/tests/ui/never_type/never-from-impl-is-reserved.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `MyFoo` + --> $DIR/never-from-impl-is-reserved.rs:10:1 + | +LL | impl MyTrait for MyFoo {} + | ---------------------- first implementation here +LL | // This will conflict with the first impl if we impl `for T: From`. +LL | impl MyTrait for T where T: From {} + | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyFoo` + | + = note: permitting this impl would forbid us from adding `impl From for T` later; see rust-lang/rust#64715 for details + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/never_type/never-result.rs b/tests/ui/never_type/never-result.rs new file mode 100644 index 000000000..35af37910 --- /dev/null +++ b/tests/ui/never_type/never-result.rs @@ -0,0 +1,21 @@ +// run-pass + +#![allow(unused_variables)] +#![allow(unreachable_code)] + +// Test that we can extract a ! through pattern matching then use it as several different types. + +#![feature(never_type)] + +fn main() { + let x: Result = Ok(123); + match x { + Ok(z) => (), + Err(y) => { + let q: u32 = y; + let w: i32 = y; + let e: String = y; + y + }, + } +} diff --git a/tests/ui/never_type/never-type-arg.rs b/tests/ui/never_type/never-type-arg.rs new file mode 100644 index 000000000..13cd59e6a --- /dev/null +++ b/tests/ui/never_type/never-type-arg.rs @@ -0,0 +1,17 @@ +// Test that we can use ! as an argument to a trait impl. + +// check-pass + +#![feature(never_type)] + +struct Wub; + +impl PartialEq for Wub { + fn eq(&self, other: &!) -> bool { + *other + } +} + +fn main() { + let _ = Wub == panic!("oh no!"); +} diff --git a/tests/ui/never_type/never-type-rvalues.rs b/tests/ui/never_type/never-type-rvalues.rs new file mode 100644 index 000000000..9ccc73dbf --- /dev/null +++ b/tests/ui/never_type/never-type-rvalues.rs @@ -0,0 +1,38 @@ +// run-pass + +#![feature(never_type)] +#![allow(dead_code)] +#![allow(path_statements)] +#![allow(unreachable_patterns)] + +fn never_direct(x: !) { + x; +} + +fn never_ref_pat(ref x: !) { + *x; +} + +fn never_ref(x: &!) { + let &y = x; + y; +} + +fn never_pointer(x: *const !) { + unsafe { + *x; + } +} + +fn never_slice(x: &[!]) { + x[0]; +} + +fn never_match(x: Result<(), !>) { + match x { + Ok(_) => {}, + Err(_) => {}, + } +} + +pub fn main() { } diff --git a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr new file mode 100644 index 000000000..06e902bca --- /dev/null +++ b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr @@ -0,0 +1,13 @@ +error[E0277]: the trait bound `E: From<()>` is not satisfied + --> $DIR/never-value-fallback-issue-66757.rs:28:26 + | +LL | >::from(never); + | -------------------- ^^^^^ the trait `From<()>` is not implemented for `E` + | | + | required by a bound introduced by this call + | + = help: the trait `From` is implemented for `E` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/never-value-fallback-issue-66757.rs b/tests/ui/never_type/never-value-fallback-issue-66757.rs new file mode 100644 index 000000000..fc6fe6eb5 --- /dev/null +++ b/tests/ui/never_type/never-value-fallback-issue-66757.rs @@ -0,0 +1,31 @@ +// Regression test for #66757 +// +// Test than when you have a `!` value (e.g., the local variable +// never) and an uninferred variable (here the argument to `From`) it +// doesn't fallback to `()` but rather `!`. +// +// revisions: nofallback fallback +//[fallback] run-pass +//[nofallback] check-fail + +#![feature(never_type)] + +#![cfg_attr(fallback, feature(never_type_fallback))] + +struct E; + +impl From for E { + fn from(_: !) -> E { + E + } +} + +#[allow(unreachable_code)] +#[allow(dead_code)] +#[allow(unused_must_use)] +fn foo(never: !) { + >::from(never); // Ok + >::from(never); //[nofallback]~ ERROR trait bound `E: From<()>` is not satisfied +} + +fn main() { } diff --git a/tests/ui/never_type/never_coercions.rs b/tests/ui/never_type/never_coercions.rs new file mode 100644 index 000000000..105c38635 --- /dev/null +++ b/tests/ui/never_type/never_coercions.rs @@ -0,0 +1,12 @@ +// run-pass +// Test that having something of type ! doesn't screw up type-checking and that it coerces to the +// LUB type of the other match arms. + +fn main() { + let v: Vec = Vec::new(); + match 0u32 { + 0 => &v, + 1 => return, + _ => &v[..], + }; +} diff --git a/tests/ui/never_type/never_transmute_never.rs b/tests/ui/never_type/never_transmute_never.rs new file mode 100644 index 000000000..fce3ced9a --- /dev/null +++ b/tests/ui/never_type/never_transmute_never.rs @@ -0,0 +1,23 @@ +// check-pass + +#![crate_type="lib"] + +#![feature(never_type)] +#![allow(dead_code)] +#![allow(unreachable_code)] +#![allow(unused_variables)] + +struct Foo; + +pub fn f(x: !) -> ! { + x +} + +pub fn ub() { + // This is completely undefined behaviour, + // but we still want to make sure it compiles. + let x: ! = unsafe { + std::mem::transmute::(Foo) + }; + f(x) +} diff --git a/tests/ui/never_type/return-never-coerce.rs b/tests/ui/never_type/return-never-coerce.rs new file mode 100644 index 000000000..d615940ef --- /dev/null +++ b/tests/ui/never_type/return-never-coerce.rs @@ -0,0 +1,18 @@ +// Test that ! coerces to other types. + +// run-fail +// error-pattern:aah! +// ignore-emscripten no processes + +fn call_another_fn T>(f: F) -> T { + f() +} + +fn wub() -> ! { + panic!("aah!"); +} + +fn main() { + let x: i32 = call_another_fn(wub); + let y: u32 = wub(); +} diff --git a/tests/ui/never_type/try_from.rs b/tests/ui/never_type/try_from.rs new file mode 100644 index 000000000..50451576f --- /dev/null +++ b/tests/ui/never_type/try_from.rs @@ -0,0 +1,37 @@ +// run-pass +// This test relies on `TryFrom` being blanket impl for all `T: Into` +// and `TryInto` being blanket impl for all `U: TryFrom` + +// This test was added to show the motivation for doing this +// over `TryFrom` being blanket impl for all `T: From` + +#![feature(never_type)] + +use std::convert::{TryInto, Infallible}; + +struct Foo { + t: T, +} + +// This fails to compile due to coherence restrictions +// as of Rust version 1.32.x, therefore it could not be used +// instead of the `Into` version of the impl, and serves as +// motivation for a blanket impl for all `T: Into`, instead +// of a blanket impl for all `T: From` +/* +impl From> for Box { + fn from(foo: Foo) -> Box { + Box::new(foo.t) + } +} +*/ + +impl Into> for Foo { + fn into(self) -> Vec { + vec![self.t] + } +} + +pub fn main() { + let _: Result, Infallible> = Foo { t: 10 }.try_into(); +} -- cgit v1.2.3