diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 6f499947d5cd4..3ab319a037b49 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -44,6 +44,9 @@ hir_typeck_convert_using_method = try using `{$sugg}` to convert `{$found}` to ` hir_typeck_ctor_is_private = tuple struct constructor `{$def}` is private +hir_typeck_dependency_on_unit_never_type_fallback = this function depends on never type fallback being `()` + .help = specify the types explicitly + hir_typeck_deref_is_empty = this expression `Deref`s to `{$deref_ty}` which implements `is_empty` hir_typeck_expected_default_return_type = expected `()` because of default return type diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 3f12f25265454..6dd34024fd1df 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -183,6 +183,11 @@ pub enum NeverTypeFallbackFlowingIntoUnsafe { Deref, } +#[derive(LintDiagnostic)] +#[help] +#[diag(hir_typeck_dependency_on_unit_never_type_fallback)] +pub struct DependencyOnUnitNeverTypeFallback {} + #[derive(Subdiagnostic)] #[multipart_suggestion( hir_typeck_add_missing_parentheses_in_range, diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 5ba67c52ef297..dbc329a12bfe6 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -14,6 +14,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable}; use rustc_session::lint; use rustc_span::DUMMY_SP; use rustc_span::{def_id::LocalDefId, Span}; +use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; #[derive(Copy, Clone)] pub enum DivergingFallbackBehavior { @@ -344,6 +345,9 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // `!`. let mut diverging_fallback = UnordMap::with_capacity(diverging_vids.len()); let unsafe_infer_vars = OnceCell::new(); + + self.lint_obligations_broken_by_never_type_fallback_change(behavior, &diverging_vids); + for &diverging_vid in &diverging_vids { let diverging_ty = Ty::new_var(self.tcx, diverging_vid); let root_vid = self.root_var(diverging_vid); @@ -468,6 +472,52 @@ impl<'tcx> FnCtxt<'_, 'tcx> { } } + fn lint_obligations_broken_by_never_type_fallback_change( + &self, + behavior: DivergingFallbackBehavior, + diverging_vids: &[ty::TyVid], + ) { + let DivergingFallbackBehavior::FallbackToUnit = behavior else { return }; + + // Fallback happens if and only if there are diverging variables + if diverging_vids.is_empty() { + return; + } + + // Returns errors which happen if fallback is set to `fallback` + let remaining_errors_if_fallback_to = |fallback| { + self.probe(|_| { + let obligations = self.fulfillment_cx.borrow().pending_obligations(); + let ocx = ObligationCtxt::new(&self.infcx); + ocx.register_obligations(obligations.iter().cloned()); + + for &diverging_vid in diverging_vids { + let diverging_ty = Ty::new_var(self.tcx, diverging_vid); + + ocx.eq(&ObligationCause::dummy(), self.param_env, diverging_ty, fallback) + .expect("expected diverging var to be unconstrained"); + } + + ocx.select_where_possible() + }) + }; + + // If we have no errors with `fallback = ()`, but *do* have errors with `fallback = !`, + // then this code will be broken by the never type fallback change.qba + let unit_errors = remaining_errors_if_fallback_to(self.tcx.types.unit); + if unit_errors.is_empty() + && let never_errors = remaining_errors_if_fallback_to(self.tcx.types.never) + && !never_errors.is_empty() + { + self.tcx.emit_node_span_lint( + lint::builtin::DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK, + self.tcx.local_def_id_to_hir_id(self.body_id), + self.tcx.def_span(self.body_id), + errors::DependencyOnUnitNeverTypeFallback {}, + ) + } + } + /// Returns a graph whose nodes are (unresolved) inference variables and where /// an edge `?A -> ?B` indicates that the variable `?A` is coerced to `?B`. fn create_coercion_graph(&self) -> VecGraph { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 726bd0de1299f..6ba8457c0a970 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -34,6 +34,7 @@ declare_lint_pass! { CONST_EVALUATABLE_UNCHECKED, CONST_ITEM_MUTATION, DEAD_CODE, + DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK, DEPRECATED, DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, DEPRECATED_IN_FUTURE, @@ -4195,6 +4196,59 @@ declare_lint! { report_in_external_macro } +declare_lint! { + /// The `dependency_on_unit_never_type_fallback` lint detects cases where code compiles with + /// [never type fallback] being [`()`], but will stop compiling with fallback being [`!`]. + /// + /// [never type fallback]: https://doc.rust-lang.org/nightly/core/primitive.never.html#never-type-fallback + /// [`!`]: https://doc.rust-lang.org/core/primitive.never.html + /// [`()`]: https://doc.rust-lang.org/core/primitive.unit.html + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(dependency_on_unit_never_type_fallback)] + /// fn main() { + /// if true { + /// // return has type `!` which, is some cases, causes never type fallback + /// return + /// } else { + /// // the type produced by this call is not specified explicitly, + /// // so it will be inferred from the previous branch + /// Default::default() + /// }; + /// // depending on the fallback, this may compile (because `()` implements `Default`), + /// // or it may not (because `!` does not implement `Default`) + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Due to historic reasons never type fallback was `()`, meaning that `!` got spontaneously + /// coerced to `()`. There are plans to change that, but they may make the code such as above + /// not compile. Instead of depending on the fallback, you should specify the type explicitly: + /// ``` + /// if true { + /// return + /// } else { + /// // type is explicitly specified, fallback can't hurt us no more + /// <() as Default>::default() + /// }; + /// ``` + /// + /// See [Tracking Issue for making `!` fall back to `!`](https://github.com/rust-lang/rust/issues/123748). + pub DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK, + Warn, + "never type fallback affecting unsafe function calls", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reference: "issue #123748 ", + }; + report_in_external_macro +} + declare_lint! { /// The `byte_slice_in_packed_struct_with_derive` lint detects cases where a byte slice field /// (`[u8]`) or string slice field (`str`) is used in a `packed` struct that derives one or diff --git a/src/tools/clippy/tests/ui/new_ret_no_self.rs b/src/tools/clippy/tests/ui/new_ret_no_self.rs index b944f531ef660..175b14d815a2c 100644 --- a/src/tools/clippy/tests/ui/new_ret_no_self.rs +++ b/src/tools/clippy/tests/ui/new_ret_no_self.rs @@ -390,9 +390,7 @@ mod issue7344 { impl RetImplTraitSelf2 { // should not trigger lint - fn new(t: T) -> impl Trait2<(), Self> { - unimplemented!() - } + fn new(t: T) -> impl Trait2<(), Self> {} } struct RetImplTraitNoSelf2(T); @@ -401,7 +399,6 @@ mod issue7344 { // should trigger lint fn new(t: T) -> impl Trait2<(), i32> { //~^ ERROR: methods called `new` usually return `Self` - unimplemented!() } } diff --git a/src/tools/clippy/tests/ui/new_ret_no_self.stderr b/src/tools/clippy/tests/ui/new_ret_no_self.stderr index d440a9f45fcdb..3597ad65838f6 100644 --- a/src/tools/clippy/tests/ui/new_ret_no_self.stderr +++ b/src/tools/clippy/tests/ui/new_ret_no_self.stderr @@ -96,11 +96,10 @@ LL | | } | |_________^ error: methods called `new` usually return `Self` - --> tests/ui/new_ret_no_self.rs:402:9 + --> tests/ui/new_ret_no_self.rs:400:9 | LL | / fn new(t: T) -> impl Trait2<(), i32> { LL | | -LL | | unimplemented!() LL | | } | |_________^ diff --git a/tests/ui/delegation/not-supported.rs b/tests/ui/delegation/not-supported.rs index 5f78de97638b5..25d7a4cb89557 100644 --- a/tests/ui/delegation/not-supported.rs +++ b/tests/ui/delegation/not-supported.rs @@ -70,12 +70,16 @@ mod opaque { pub fn opaque_arg(_: impl Trait) -> i32 { 0 } pub fn opaque_ret() -> impl Trait { unimplemented!() } + //~^ warn: this function depends on never type fallback being `()` + //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! } reuse to_reuse::opaque_arg; //~^ ERROR delegation with early bound generics is not supported yet trait ToReuse { fn opaque_ret() -> impl Trait { unimplemented!() } + //~^ warn: this function depends on never type fallback being `()` + //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! } // FIXME: Inherited `impl Trait`s create query cycles when used inside trait impls. diff --git a/tests/ui/delegation/not-supported.stderr b/tests/ui/delegation/not-supported.stderr index e2cb04f977b1e..339a8418b33a2 100644 --- a/tests/ui/delegation/not-supported.stderr +++ b/tests/ui/delegation/not-supported.stderr @@ -107,7 +107,7 @@ LL | reuse Trait::foo2 { &self.0 } | ^^^^ error: delegation with early bound generics is not supported yet - --> $DIR/not-supported.rs:74:21 + --> $DIR/not-supported.rs:76:21 | LL | pub fn opaque_arg(_: impl Trait) -> i32 { 0 } | --------------------------------------- callee defined here @@ -115,46 +115,67 @@ LL | pub fn opaque_arg(_: impl Trait) -> i32 { 0 } LL | reuse to_reuse::opaque_arg; | ^^^^^^^^^^ -error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` - --> $DIR/not-supported.rs:83:25 +warning: this function depends on never type fallback being `()` + --> $DIR/not-supported.rs:80:9 + | +LL | fn opaque_ret() -> impl Trait { unimplemented!() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #123748 + = help: specify the types explicitly + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default + +error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` + --> $DIR/not-supported.rs:87:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ | note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/not-supported.rs:83:25 + --> $DIR/not-supported.rs:87:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle -note: cycle used when checking that `opaque::` is well-formed - --> $DIR/not-supported.rs:82:5 + = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::` is well-formed + --> $DIR/not-supported.rs:86:5 | LL | impl ToReuse for u8 { | ^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` - --> $DIR/not-supported.rs:86:24 +warning: this function depends on never type fallback being `()` + --> $DIR/not-supported.rs:72:9 + | +LL | pub fn opaque_ret() -> impl Trait { unimplemented!() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #123748 + = help: specify the types explicitly + +error[E0391]: cycle detected when computing type of `opaque::::{synthetic#0}` + --> $DIR/not-supported.rs:90:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ | note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/not-supported.rs:86:24 + --> $DIR/not-supported.rs:90:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle -note: cycle used when checking that `opaque::` is well-formed - --> $DIR/not-supported.rs:85:5 + = note: ...which again requires computing type of `opaque::::{synthetic#0}`, completing the cycle +note: cycle used when checking that `opaque::` is well-formed + --> $DIR/not-supported.rs:89:5 | LL | impl ToReuse for u16 { | ^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: recursive delegation is not supported yet - --> $DIR/not-supported.rs:99:22 + --> $DIR/not-supported.rs:103:22 | LL | pub reuse to_reuse2::foo; | --- callee defined here @@ -162,7 +183,7 @@ LL | pub reuse to_reuse2::foo; LL | reuse to_reuse1::foo; | ^^^ -error: aborting due to 16 previous errors +error: aborting due to 16 previous errors; 2 warnings emitted Some errors have detailed explanations: E0049, E0195, E0391. For more information about an error, try `rustc --explain E0049`. diff --git a/tests/ui/never_type/defaulted-never-note.fallback.stderr b/tests/ui/never_type/defaulted-never-note.fallback.stderr index 92fa9068cfd5e..fe9a924f64a0f 100644 --- a/tests/ui/never_type/defaulted-never-note.fallback.stderr +++ b/tests/ui/never_type/defaulted-never-note.fallback.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied - --> $DIR/defaulted-never-note.rs:30:9 + --> $DIR/defaulted-never-note.rs:32:9 | LL | foo(_x); | --- ^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!` diff --git a/tests/ui/never_type/defaulted-never-note.nofallback.stderr b/tests/ui/never_type/defaulted-never-note.nofallback.stderr new file mode 100644 index 0000000000000..b69b8dda8f1ee --- /dev/null +++ b/tests/ui/never_type/defaulted-never-note.nofallback.stderr @@ -0,0 +1,13 @@ +warning: this function depends on never type fallback being `()` + --> $DIR/defaulted-never-note.rs:28:1 + | +LL | fn smeg() { + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #123748 + = help: specify the types explicitly + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/never_type/defaulted-never-note.rs b/tests/ui/never_type/defaulted-never-note.rs index f4e5273b33a76..40861e73b393c 100644 --- a/tests/ui/never_type/defaulted-never-note.rs +++ b/tests/ui/never_type/defaulted-never-note.rs @@ -26,6 +26,8 @@ fn foo(_t: T) {} //[fallback]~^ NOTE required by this bound in `foo` //[fallback]~| NOTE required by a bound in `foo` fn smeg() { + //[nofallback]~^ warn: this function depends on never type fallback being `()` + //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! let _x = return; foo(_x); //[fallback]~^ ERROR the trait bound diff --git a/tests/ui/never_type/dependency-on-fallback-to-unit.rs b/tests/ui/never_type/dependency-on-fallback-to-unit.rs new file mode 100644 index 0000000000000..5448d0be2c6de --- /dev/null +++ b/tests/ui/never_type/dependency-on-fallback-to-unit.rs @@ -0,0 +1,28 @@ +//@ check-pass + +fn main() { + def(); + _ = question_mark(); +} + +fn def() { + //~^ warn: this function depends on never type fallback being `()` + //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + match true { + false => <_>::default(), + true => return, + }; +} + +// +// +fn question_mark() -> Result<(), ()> { + //~^ warn: this function depends on never type fallback being `()` + //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + deserialize()?; + Ok(()) +} + +fn deserialize() -> Result { + Ok(T::default()) +} diff --git a/tests/ui/never_type/dependency-on-fallback-to-unit.stderr b/tests/ui/never_type/dependency-on-fallback-to-unit.stderr new file mode 100644 index 0000000000000..36c82b6d1bf64 --- /dev/null +++ b/tests/ui/never_type/dependency-on-fallback-to-unit.stderr @@ -0,0 +1,23 @@ +warning: this function depends on never type fallback being `()` + --> $DIR/dependency-on-fallback-to-unit.rs:8:1 + | +LL | fn def() { + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #123748 + = help: specify the types explicitly + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default + +warning: this function depends on never type fallback being `()` + --> $DIR/dependency-on-fallback-to-unit.rs:19:1 + | +LL | fn question_mark() -> Result<(), ()> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #123748 + = help: specify the types explicitly + +warning: 2 warnings emitted + diff --git a/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr b/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr new file mode 100644 index 0000000000000..5fbdc04ed3b80 --- /dev/null +++ b/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr @@ -0,0 +1,23 @@ +warning: this function depends on never type fallback being `()` + --> $DIR/diverging-fallback-control-flow.rs:30:1 + | +LL | fn assignment() { + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #123748 + = help: specify the types explicitly + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default + +warning: this function depends on never type fallback being `()` + --> $DIR/diverging-fallback-control-flow.rs:42:1 + | +LL | fn assignment_rev() { + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #123748 + = help: specify the types explicitly + +warning: 2 warnings emitted + diff --git a/tests/ui/never_type/diverging-fallback-control-flow.rs b/tests/ui/never_type/diverging-fallback-control-flow.rs index e209a9908850a..575e2e9273cf4 100644 --- a/tests/ui/never_type/diverging-fallback-control-flow.rs +++ b/tests/ui/never_type/diverging-fallback-control-flow.rs @@ -28,6 +28,8 @@ impl UnitDefault for () { } fn assignment() { + //[nofallback]~^ warn: this function depends on never type fallback being `()` + //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! let x; if true { @@ -38,6 +40,8 @@ fn assignment() { } fn assignment_rev() { + //[nofallback]~^ warn: this function depends on never type fallback being `()` + //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! let x; if true { diff --git a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr index 01abf2e17f1e8..c5463814475c7 100644 --- a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr +++ b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `!: Test` is not satisfied - --> $DIR/diverging-fallback-no-leak.rs:17:23 + --> $DIR/diverging-fallback-no-leak.rs:20:23 | LL | unconstrained_arg(return); | ----------------- ^^^^^^ the trait `Test` is not implemented for `!` diff --git a/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr new file mode 100644 index 0000000000000..d11097323b3fb --- /dev/null +++ b/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr @@ -0,0 +1,13 @@ +warning: this function depends on never type fallback being `()` + --> $DIR/diverging-fallback-no-leak.rs:14:1 + | +LL | fn main() { + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #123748 + = help: specify the types explicitly + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/never_type/diverging-fallback-no-leak.rs b/tests/ui/never_type/diverging-fallback-no-leak.rs index 425437da2077b..c6d59c7f2738f 100644 --- a/tests/ui/never_type/diverging-fallback-no-leak.rs +++ b/tests/ui/never_type/diverging-fallback-no-leak.rs @@ -12,6 +12,9 @@ impl Test for () {} fn unconstrained_arg(_: T) {} fn main() { + //[nofallback]~^ warn: this function depends on never type fallback being `()` + //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + // Here the type variable falls back to `!`, // and hence we get a type error. unconstrained_arg(return); diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr b/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr new file mode 100644 index 0000000000000..750bcfb7f89dc --- /dev/null +++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr @@ -0,0 +1,13 @@ +warning: this function depends on never type fallback being `()` + --> $DIR/diverging-fallback-unconstrained-return.rs:28:1 + | +LL | fn main() { + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #123748 + = help: specify the types explicitly + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs index aeb6ee6e26efd..927991db5138d 100644 --- a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs +++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs @@ -26,6 +26,9 @@ fn unconstrained_return() -> T { } fn main() { + //[nofallback]~^ warn: this function depends on never type fallback being `()` + //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + // 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 diff --git a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr new file mode 100644 index 0000000000000..9f0b9f6daeae3 --- /dev/null +++ b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr @@ -0,0 +1,13 @@ +warning: this function depends on never type fallback being `()` + --> $DIR/fallback-closure-ret.rs:21:1 + | +LL | fn main() { + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #123748 + = help: specify the types explicitly + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/never_type/fallback-closure-ret.rs b/tests/ui/never_type/fallback-closure-ret.rs index dcf38e03a137e..30f9ac54d0bbb 100644 --- a/tests/ui/never_type/fallback-closure-ret.rs +++ b/tests/ui/never_type/fallback-closure-ret.rs @@ -12,12 +12,14 @@ #![cfg_attr(fallback, feature(never_type_fallback))] -trait Bar { } -impl Bar for () { } -impl Bar for u32 { } +trait Bar {} +impl Bar for () {} +impl Bar for u32 {} fn foo(_: impl Fn() -> R) {} fn main() { + //[nofallback]~^ warn: this function depends on never type fallback being `()` + //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! foo(|| panic!()); } diff --git a/tests/ui/never_type/impl_trait_fallback.rs b/tests/ui/never_type/impl_trait_fallback.rs index ce06f8f7817ff..fbe13dbe2acee 100644 --- a/tests/ui/never_type/impl_trait_fallback.rs +++ b/tests/ui/never_type/impl_trait_fallback.rs @@ -6,5 +6,7 @@ trait T {} impl T for () {} fn should_ret_unit() -> impl T { + //~^ warn: this function depends on never type fallback being `()` + //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! panic!() } diff --git a/tests/ui/never_type/impl_trait_fallback.stderr b/tests/ui/never_type/impl_trait_fallback.stderr new file mode 100644 index 0000000000000..8763894033243 --- /dev/null +++ b/tests/ui/never_type/impl_trait_fallback.stderr @@ -0,0 +1,13 @@ +warning: this function depends on never type fallback being `()` + --> $DIR/impl_trait_fallback.rs:8:1 + | +LL | fn should_ret_unit() -> impl T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #123748 + = help: specify the types explicitly + = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default + +warning: 1 warning emitted +