From 55621a180e563166034a9b57d70e779c7f61d1f8 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Fri, 26 Sep 2025 17:43:25 +0200 Subject: [PATCH 1/8] remove support for context dependant `!` fallback The code supporting it is extremely confusing. At the same time, we have no plans to use this scheme, so there is no value in supporting it. --- compiler/rustc_hir_typeck/src/fallback.rs | 95 +------------------- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 6 -- 2 files changed, 3 insertions(+), 98 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 15e502a600561..d94b6cdcba612 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -2,10 +2,9 @@ use std::cell::OnceCell; use std::ops::ControlFlow; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::graph::iterate::DepthFirstSearch; use rustc_data_structures::graph::vec_graph::VecGraph; use rustc_data_structures::graph::{self}; -use rustc_data_structures::unord::{UnordBag, UnordMap, UnordSet}; +use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; @@ -18,15 +17,12 @@ use rustc_span::{DUMMY_SP, Span}; use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; use tracing::debug; -use crate::typeck_root_ctxt::InferVarInfo; use crate::{FnCtxt, errors}; #[derive(Copy, Clone)] pub(crate) enum DivergingFallbackBehavior { /// Always fallback to `()` (aka "always spontaneous decay") ToUnit, - /// Sometimes fallback to `!`, but mainly fallback to `()` so that most of the crates are not broken. - ContextDependent, /// Always fallback to `!` (which should be equivalent to never falling back + not making /// never-to-any coercions unless necessary) ToNever, @@ -267,9 +263,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // type variable. These will typically default to `!`, unless // we find later that they are *also* reachable from some // other type variable outside this set. - let mut roots_reachable_from_diverging = DepthFirstSearch::new(&coercion_graph); let mut diverging_vids = vec![]; - let mut non_diverging_vids = vec![]; for unsolved_vid in unsolved_vids { let root_vid = self.root_var(unsolved_vid); debug!( @@ -280,49 +274,17 @@ impl<'tcx> FnCtxt<'_, 'tcx> { ); if diverging_roots.contains(&root_vid) { diverging_vids.push(unsolved_vid); - roots_reachable_from_diverging.push_start_node(root_vid); debug!( "calculate_diverging_fallback: root_vid={:?} reaches {:?}", root_vid, graph::depth_first_search(&coercion_graph, root_vid).collect::>() ); - - // drain the iterator to visit all nodes reachable from this node - roots_reachable_from_diverging.complete_search(); - } else { - non_diverging_vids.push(unsolved_vid); } } - debug!( - "calculate_diverging_fallback: roots_reachable_from_diverging={:?}", - roots_reachable_from_diverging, - ); - - // Find all type variables N0 that are not reachable from a - // diverging variable, and then compute the set reachable from - // N0, which we call N. These are the *non-diverging* type - // variables. (Note that this set consists of "root variables".) - let mut roots_reachable_from_non_diverging = DepthFirstSearch::new(&coercion_graph); - for &non_diverging_vid in &non_diverging_vids { - let root_vid = self.root_var(non_diverging_vid); - if roots_reachable_from_diverging.visited(root_vid) { - continue; - } - roots_reachable_from_non_diverging.push_start_node(root_vid); - roots_reachable_from_non_diverging.complete_search(); - } - debug!( - "calculate_diverging_fallback: roots_reachable_from_non_diverging={:?}", - roots_reachable_from_non_diverging, - ); - debug!("obligations: {:#?}", self.fulfillment_cx.borrow_mut().pending_obligations()); - // For each diverging variable, figure out whether it can - // reach a member of N. If so, it falls back to `()`. Else - // `!`. let mut diverging_fallback = UnordMap::with_capacity(diverging_vids.len()); let unsafe_infer_vars = OnceCell::new(); @@ -335,21 +297,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> { for &diverging_vid in &diverging_vids { let diverging_ty = Ty::new_var(self.tcx, diverging_vid); let root_vid = self.root_var(diverging_vid); - let can_reach_non_diverging = graph::depth_first_search(&coercion_graph, root_vid) - .any(|n| roots_reachable_from_non_diverging.visited(n)); - - let infer_var_infos: UnordBag<_> = self - .infer_var_info - .borrow() - .items() - .filter(|&(vid, _)| self.infcx.root_var(*vid) == root_vid) - .map(|(_, info)| *info) - .collect(); - - let found_infer_var_info = InferVarInfo { - self_in_trait: infer_var_infos.items().any(|info| info.self_in_trait), - output: infer_var_infos.items().any(|info| info.output), - }; let mut fallback_to = |ty| { self.lint_never_type_fallback_flowing_into_unsafe_code( @@ -366,52 +313,16 @@ impl<'tcx> FnCtxt<'_, 'tcx> { debug!("fallback to () - legacy: {:?}", diverging_vid); fallback_to(self.tcx.types.unit); } - DivergingFallbackBehavior::ContextDependent => { - if found_infer_var_info.self_in_trait && found_infer_var_info.output { - // This case falls back to () to ensure that the code pattern in - // tests/ui/never_type/fallback-closure-ret.rs continues to - // compile when never_type_fallback is enabled. - // - // This rule is not readily explainable from first principles, - // but is rather intended as a patchwork fix to ensure code - // which compiles before the stabilization of never type - // fallback continues to work. - // - // Typically this pattern is encountered in a function taking a - // closure as a parameter, where the return type of that closure - // (checked by `relationship.output`) is expected to implement - // some trait (checked by `relationship.self_in_trait`). This - // can come up in non-closure cases too, so we do not limit this - // rule to specifically `FnOnce`. - // - // When the closure's body is something like `panic!()`, the - // return type would normally be inferred to `!`. However, it - // needs to fall back to `()` in order to still compile, as the - // trait is specifically implemented for `()` but not `!`. - // - // For details on the requirements for these relationships to be - // set, see the relationship finding module in - // compiler/rustc_trait_selection/src/traits/relationships.rs. - debug!("fallback to () - found trait and projection: {:?}", diverging_vid); - fallback_to(self.tcx.types.unit); - } else if can_reach_non_diverging { - debug!("fallback to () - reached non-diverging: {:?}", diverging_vid); - fallback_to(self.tcx.types.unit); - } else { - debug!("fallback to ! - all diverging: {:?}", diverging_vid); - fallback_to(self.tcx.types.never); - } - } DivergingFallbackBehavior::ToNever => { debug!( - "fallback to ! - `rustc_never_type_mode = \"fallback_to_never\")`: {:?}", + "fallback to ! - `rustc_never_type_options::falback = \"never\")`: {:?}", diverging_vid ); fallback_to(self.tcx.types.never); } DivergingFallbackBehavior::NoFallback => { debug!( - "no fallback - `rustc_never_type_mode = \"no_fallback\"`: {:?}", + "no fallback - `rustc_never_type_options::fallback = \"no\"`: {:?}", diverging_vid ); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index d4236aad8e671..c42a276b86acb 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -505,11 +505,6 @@ fn default_fallback(tcx: TyCtxt<'_>) -> DivergingFallbackBehavior { return DivergingFallbackBehavior::ToNever; } - // `feature(never_type_fallback)`: fallback to `!` or `()` trying to not break stuff - if tcx.features().never_type_fallback() { - return DivergingFallbackBehavior::ContextDependent; - } - // Otherwise: fallback to `()` DivergingFallbackBehavior::ToUnit } @@ -536,7 +531,6 @@ fn parse_never_type_options_attr( let mode = item.value_str().unwrap(); match mode { sym::unit => fallback = Some(DivergingFallbackBehavior::ToUnit), - sym::niko => fallback = Some(DivergingFallbackBehavior::ContextDependent), sym::never => fallback = Some(DivergingFallbackBehavior::ToNever), sym::no => fallback = Some(DivergingFallbackBehavior::NoFallback), _ => { From a75c8577843c704e60edfbb4623736e51dfaa76b Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Fri, 26 Sep 2025 17:43:25 +0200 Subject: [PATCH 2/8] doc fixes --- compiler/rustc_hir_typeck/src/fallback.rs | 30 +++++++++---------- .../traits/fulfillment_errors.rs | 1 + 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index d94b6cdcba612..0ff3ceb68ad06 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -102,21 +102,21 @@ impl<'tcx> FnCtxt<'_, 'tcx> { fallback_occurred } - // Tries to apply a fallback to `ty` if it is an unsolved variable. - // - // - Unconstrained ints are replaced with `i32`. - // - // - Unconstrained floats are replaced with `f64`. - // - // - Non-numerics may get replaced with `()` or `!`, depending on - // how they were categorized by `calculate_diverging_fallback` - // (and the setting of `#![feature(never_type_fallback)]`). - // - // Fallback becomes very dubious if we have encountered - // type-checking errors. In that case, fallback to Error. - // - // Sets `FnCtxt::fallback_has_occurred` if fallback is performed - // during this call. + /// Tries to apply a fallback to `ty` if it is an unsolved variable. + /// + /// - Unconstrained ints are replaced with `i32`. + /// + /// - Unconstrained floats are replaced with `f64`. + /// + /// - Non-numerics may get replaced with `()` or `!`, depending on how they + /// were categorized by [`Self::calculate_diverging_fallback`], crate's + /// edition, and the setting of `#![rustc_never_type_options(fallback = ...)]`. + /// + /// Fallback becomes very dubious if we have encountered + /// type-checking errors. In that case, fallback to Error. + /// + /// Sets [`FnCtxt::fallback_has_occurred`] if fallback is performed + /// during this call. fn fallback_if_possible( &self, ty: Ty<'tcx>, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 27eb614bae138..e28ccc000683b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -546,6 +546,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }); let unit_obligation = obligation.with(tcx, predicate); if self.predicate_may_hold(&unit_obligation) { + // FIXME: make a new issue for this err.note( "this error might have been caused by changes to \ Rust's type-inference algorithm (see issue #48950 \ From 7735e5af63df2a18715c4d8d46dbedc1a2cadd50 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sat, 27 Sep 2025 18:06:59 +0200 Subject: [PATCH 3/8] track never type fallback specifically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the only diagnostic that was using this field specifically сares for the never type fallback, not the integer fallback. --- compiler/rustc_hir_typeck/src/fallback.rs | 14 ++++++++------ compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 8 +++++--- .../src/error_reporting/mod.rs | 4 ++-- .../error_reporting/traits/fulfillment_errors.rs | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 0ff3ceb68ad06..513785454c40e 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -31,8 +31,8 @@ pub(crate) enum DivergingFallbackBehavior { } impl<'tcx> FnCtxt<'_, 'tcx> { - /// Performs type inference fallback, setting `FnCtxt::fallback_has_occurred` - /// if fallback has occurred. + /// Performs type inference fallback, setting [`FnCtxt::never_type_fallback_has_occurred`] + /// if the never type fallback has occurred. pub(super) fn type_inference_fallback(&self) { debug!( "type-inference-fallback start obligations: {:#?}", @@ -115,8 +115,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> { /// Fallback becomes very dubious if we have encountered /// type-checking errors. In that case, fallback to Error. /// - /// Sets [`FnCtxt::fallback_has_occurred`] if fallback is performed - /// during this call. + /// Sets [`FnCtxt::never_type_fallback_has_occurred`] if never type fallback + /// is performed during this call. fn fallback_if_possible( &self, ty: Ty<'tcx>, @@ -145,7 +145,10 @@ impl<'tcx> FnCtxt<'_, 'tcx> { ty::Infer(ty::IntVar(_)) => self.tcx.types.i32, ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64, _ => match diverging_fallback.get(&ty) { - Some(&fallback_ty) => fallback_ty, + Some(&fallback_ty) => { + self.never_type_fallback_has_occurred.set(true); + fallback_ty + } None => return false, }, }; @@ -153,7 +156,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> { let span = ty.ty_vid().map_or(DUMMY_SP, |vid| self.infcx.type_var_origin(vid).span); self.demand_eqtype(span, ty, fallback); - self.fallback_has_occurred.set(true); true } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index c42a276b86acb..0dad17bde79d0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -115,7 +115,9 @@ pub(crate) struct FnCtxt<'a, 'tcx> { pub(super) root_ctxt: &'a TypeckRootCtxt<'tcx>, - pub(super) fallback_has_occurred: Cell, + /// True if a divirging inference variable has been set to `()`/`!` because + /// of never type fallback. This is used for diagnostics. + pub(super) never_type_fallback_has_occurred: Cell, pub(super) diverging_fallback_behavior: DivergingFallbackBehavior, pub(super) diverging_block_behavior: DivergingBlockBehavior, @@ -153,7 +155,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { by_id: Default::default(), }), root_ctxt, - fallback_has_occurred: Cell::new(false), + never_type_fallback_has_occurred: Cell::new(false), diverging_fallback_behavior, diverging_block_behavior, trait_ascriptions: Default::default(), @@ -190,7 +192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { TypeErrCtxt { infcx: &self.infcx, typeck_results: Some(self.typeck_results.borrow()), - fallback_has_occurred: self.fallback_has_occurred.get(), + never_type_fallback_has_occurred: self.never_type_fallback_has_occurred.get(), normalize_fn_sig: Box::new(|fn_sig| { if fn_sig.has_escaping_bound_vars() { return fn_sig; diff --git a/compiler/rustc_trait_selection/src/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/mod.rs index cce20b05c79aa..1d7ab6006b6b8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/mod.rs @@ -21,7 +21,7 @@ pub struct TypeErrCtxt<'a, 'tcx> { pub infcx: &'a InferCtxt<'tcx>, pub typeck_results: Option>>, - pub fallback_has_occurred: bool, + pub never_type_fallback_has_occurred: bool, pub normalize_fn_sig: Box) -> ty::PolyFnSig<'tcx> + 'a>, @@ -36,7 +36,7 @@ impl<'tcx> InferCtxt<'tcx> { TypeErrCtxt { infcx: self, typeck_results: None, - fallback_has_occurred: false, + never_type_fallback_has_occurred: false, normalize_fn_sig: Box::new(|fn_sig| fn_sig), autoderef_steps: Box::new(|ty| { debug_assert!(false, "shouldn't be using autoderef_steps outside of typeck"); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index e28ccc000683b..56ace88e47cf3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -539,7 +539,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // variable that used to fallback to `()` now falling back to `!`. Issue a // note informing about the change in behaviour. if leaf_trait_predicate.skip_binder().self_ty().is_never() - && self.fallback_has_occurred + && self.never_type_fallback_has_occurred { let predicate = leaf_trait_predicate.map_bound(|trait_pred| { trait_pred.with_replaced_self_ty(self.tcx, tcx.types.unit) From a137c21278cb3ed3b66102ed31e9518afa750840 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sat, 27 Sep 2025 18:31:49 +0200 Subject: [PATCH 4/8] remove an unnecessary negation I think in this case the early return is harder to read than just an if. "if fallback hasn't occured we don't do..." --- compiler/rustc_hir_typeck/src/fallback.rs | 52 +++++++++++------------ 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 513785454c40e..89ebd4418022d 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -49,34 +49,32 @@ impl<'tcx> FnCtxt<'_, 'tcx> { let fallback_occurred = self.fallback_types(); - if !fallback_occurred { - return; + if fallback_occurred { + // We now see if we can make progress. This might cause us to + // unify inference variables for opaque types, since we may + // have unified some other type variables during the first + // phase of fallback. This means that we only replace + // inference variables with their underlying opaque types as a + // last resort. + // + // In code like this: + // + // ```rust + // type MyType = impl Copy; + // fn produce() -> MyType { true } + // fn bad_produce() -> MyType { panic!() } + // ``` + // + // we want to unify the opaque inference variable in `bad_produce` + // with the diverging fallback for `panic!` (e.g. `()` or `!`). + // This will produce a nice error message about conflicting concrete + // types for `MyType`. + // + // If we had tried to fallback the opaque inference variable to `MyType`, + // we will generate a confusing type-check error that does not explicitly + // refer to opaque types. + self.select_obligations_where_possible(|_| {}); } - - // We now see if we can make progress. This might cause us to - // unify inference variables for opaque types, since we may - // have unified some other type variables during the first - // phase of fallback. This means that we only replace - // inference variables with their underlying opaque types as a - // last resort. - // - // In code like this: - // - // ```rust - // type MyType = impl Copy; - // fn produce() -> MyType { true } - // fn bad_produce() -> MyType { panic!() } - // ``` - // - // we want to unify the opaque inference variable in `bad_produce` - // with the diverging fallback for `panic!` (e.g. `()` or `!`). - // This will produce a nice error message about conflicting concrete - // types for `MyType`. - // - // If we had tried to fallback the opaque inference variable to `MyType`, - // we will generate a confusing type-check error that does not explicitly - // refer to opaque types. - self.select_obligations_where_possible(|_| {}); } fn fallback_types(&self) -> bool { From 60ade218b32f20d13119beb50bd40809b6f67f81 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sat, 27 Sep 2025 18:33:16 +0200 Subject: [PATCH 5/8] remove an outdated comment this is about context dependant case which I removed a few commits back --- compiler/rustc_hir_typeck/src/fallback.rs | 67 ----------------------- 1 file changed, 67 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index 89ebd4418022d..a6f8575a08dad 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -157,73 +157,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> { true } - /// The "diverging fallback" system is rather complicated. This is - /// a result of our need to balance 'do the right thing' with - /// backwards compatibility. - /// - /// "Diverging" type variables are variables created when we - /// coerce a `!` type into an unbound type variable `?X`. If they - /// never wind up being constrained, the "right and natural" thing - /// is that `?X` should "fallback" to `!`. This means that e.g. an - /// expression like `Some(return)` will ultimately wind up with a - /// type like `Option` (presuming it is not assigned or - /// constrained to have some other type). - /// - /// However, the fallback used to be `()` (before the `!` type was - /// added). Moreover, there are cases where the `!` type 'leaks - /// out' from dead code into type variables that affect live - /// code. The most common case is something like this: - /// - /// ```rust - /// # fn foo() -> i32 { 4 } - /// match foo() { - /// 22 => Default::default(), // call this type `?D` - /// _ => return, // return has type `!` - /// } // call the type of this match `?M` - /// ``` - /// - /// Here, coercing the type `!` into `?M` will create a diverging - /// type variable `?X` where `?X <: ?M`. We also have that `?D <: - /// ?M`. If `?M` winds up unconstrained, then `?X` will - /// fallback. If it falls back to `!`, then all the type variables - /// will wind up equal to `!` -- this includes the type `?D` - /// (since `!` doesn't implement `Default`, we wind up a "trait - /// not implemented" error in code like this). But since the - /// original fallback was `()`, this code used to compile with `?D - /// = ()`. This is somewhat surprising, since `Default::default()` - /// on its own would give an error because the types are - /// insufficiently constrained. - /// - /// Our solution to this dilemma is to modify diverging variables - /// so that they can *either* fallback to `!` (the default) or to - /// `()` (the backwards compatibility case). We decide which - /// fallback to use based on whether there is a coercion pattern - /// like this: - /// - /// ```ignore (not-rust) - /// ?Diverging -> ?V - /// ?NonDiverging -> ?V - /// ?V != ?NonDiverging - /// ``` - /// - /// Here `?Diverging` represents some diverging type variable and - /// `?NonDiverging` represents some non-diverging type - /// variable. `?V` can be any type variable (diverging or not), so - /// long as it is not equal to `?NonDiverging`. - /// - /// Intuitively, what we are looking for is a case where a - /// "non-diverging" type variable (like `?M` in our example above) - /// is coerced *into* some variable `?V` that would otherwise - /// fallback to `!`. In that case, we make `?V` fallback to `!`, - /// along with anything that would flow into `?V`. - /// - /// The algorithm we use: - /// * Identify all variables that are coerced *into* by a - /// diverging variable. Do this by iterating over each - /// diverging, unsolved variable and finding all variables - /// reachable from there. Call that set `D`. - /// * Walk over all unsolved, non-diverging variables, and find - /// any variable that has an edge into `D`. fn calculate_diverging_fallback( &self, unresolved_variables: &[Ty<'tcx>], From 9bf596b171710e73003cf2204b3afa637a06704b Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sat, 27 Sep 2025 18:36:22 +0200 Subject: [PATCH 6/8] don't pass `self.<...>` as an argument to a method on the same type... --- compiler/rustc_hir_typeck/src/fallback.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index a6f8575a08dad..ef579b3877233 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -85,8 +85,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { return false; } - let diverging_fallback = self - .calculate_diverging_fallback(&unresolved_variables, self.diverging_fallback_behavior); + let diverging_fallback = self.calculate_diverging_fallback(&unresolved_variables); // We do fallback in two passes, to try to generate // better error messages. @@ -160,7 +159,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> { fn calculate_diverging_fallback( &self, unresolved_variables: &[Ty<'tcx>], - behavior: DivergingFallbackBehavior, ) -> UnordMap, Ty<'tcx>> { debug!("calculate_diverging_fallback({:?})", unresolved_variables); @@ -222,7 +220,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> { let unsafe_infer_vars = OnceCell::new(); self.lint_obligations_broken_by_never_type_fallback_change( - behavior, &diverging_vids, &coercion_graph, ); @@ -241,7 +238,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { diverging_fallback.insert(diverging_ty, ty); }; - match behavior { + match self.diverging_fallback_behavior { DivergingFallbackBehavior::ToUnit => { debug!("fallback to () - legacy: {:?}", diverging_vid); fallback_to(self.tcx.types.unit); @@ -314,11 +311,10 @@ impl<'tcx> FnCtxt<'_, 'tcx> { fn lint_obligations_broken_by_never_type_fallback_change( &self, - behavior: DivergingFallbackBehavior, diverging_vids: &[ty::TyVid], coercions: &VecGraph, ) { - let DivergingFallbackBehavior::ToUnit = behavior else { return }; + let DivergingFallbackBehavior::ToUnit = self.diverging_fallback_behavior else { return }; // Fallback happens if and only if there are diverging variables if diverging_vids.is_empty() { From a7b102ac0b7efa968b0e1834d02acc6830120ece Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Sat, 27 Sep 2025 18:51:51 +0200 Subject: [PATCH 7/8] don't recompute diverging fallback type ... now that it's always the same for a certain crate --- compiler/rustc_hir_typeck/src/fallback.rs | 70 ++++++++++------------- 1 file changed, 29 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index ef579b3877233..3ce16ca790543 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -85,7 +85,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> { return false; } - let diverging_fallback = self.calculate_diverging_fallback(&unresolved_variables); + let (diverging_fallback, diverging_fallback_ty) = + self.calculate_diverging_fallback(&unresolved_variables); // We do fallback in two passes, to try to generate // better error messages. @@ -93,7 +94,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> { let mut fallback_occurred = false; for ty in unresolved_variables { debug!("unsolved_variable = {:?}", ty); - fallback_occurred |= self.fallback_if_possible(ty, &diverging_fallback); + fallback_occurred |= + self.fallback_if_possible(ty, &diverging_fallback, diverging_fallback_ty); } fallback_occurred @@ -117,7 +119,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> { fn fallback_if_possible( &self, ty: Ty<'tcx>, - diverging_fallback: &UnordMap, Ty<'tcx>>, + diverging_fallback: &UnordSet>, + diverging_fallback_ty: Ty<'tcx>, ) -> bool { // Careful: we do NOT shallow-resolve `ty`. We know that `ty` // is an unsolved variable, and we determine its fallback @@ -141,13 +144,11 @@ impl<'tcx> FnCtxt<'_, 'tcx> { _ if let Some(e) = self.tainted_by_errors() => Ty::new_error(self.tcx, e), ty::Infer(ty::IntVar(_)) => self.tcx.types.i32, ty::Infer(ty::FloatVar(_)) => self.tcx.types.f64, - _ => match diverging_fallback.get(&ty) { - Some(&fallback_ty) => { - self.never_type_fallback_has_occurred.set(true); - fallback_ty - } - None => return false, - }, + _ if diverging_fallback.contains(&ty) => { + self.never_type_fallback_has_occurred.set(true); + diverging_fallback_ty + } + _ => return false, }; debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback); @@ -159,9 +160,18 @@ impl<'tcx> FnCtxt<'_, 'tcx> { fn calculate_diverging_fallback( &self, unresolved_variables: &[Ty<'tcx>], - ) -> UnordMap, Ty<'tcx>> { + ) -> (UnordSet>, Ty<'tcx>) { debug!("calculate_diverging_fallback({:?})", unresolved_variables); + let diverging_fallback_ty = match self.diverging_fallback_behavior { + DivergingFallbackBehavior::ToUnit => self.tcx.types.unit, + DivergingFallbackBehavior::ToNever => self.tcx.types.never, + DivergingFallbackBehavior::NoFallback => { + // the type doesn't matter, since no fallback will occur + return (UnordSet::new(), self.tcx.types.unit); + } + }; + // Construct a coercion graph where an edge `A -> B` indicates // a type variable is that is coerced let coercion_graph = self.create_coercion_graph(); @@ -216,7 +226,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { debug!("obligations: {:#?}", self.fulfillment_cx.borrow_mut().pending_obligations()); - let mut diverging_fallback = UnordMap::with_capacity(diverging_vids.len()); + let mut diverging_fallback = UnordSet::with_capacity(diverging_vids.len()); let unsafe_infer_vars = OnceCell::new(); self.lint_obligations_broken_by_never_type_fallback_change( @@ -228,38 +238,16 @@ impl<'tcx> FnCtxt<'_, 'tcx> { let diverging_ty = Ty::new_var(self.tcx, diverging_vid); let root_vid = self.root_var(diverging_vid); - let mut fallback_to = |ty| { - self.lint_never_type_fallback_flowing_into_unsafe_code( - &unsafe_infer_vars, - &coercion_graph, - root_vid, - ); - - diverging_fallback.insert(diverging_ty, ty); - }; + self.lint_never_type_fallback_flowing_into_unsafe_code( + &unsafe_infer_vars, + &coercion_graph, + root_vid, + ); - match self.diverging_fallback_behavior { - DivergingFallbackBehavior::ToUnit => { - debug!("fallback to () - legacy: {:?}", diverging_vid); - fallback_to(self.tcx.types.unit); - } - DivergingFallbackBehavior::ToNever => { - debug!( - "fallback to ! - `rustc_never_type_options::falback = \"never\")`: {:?}", - diverging_vid - ); - fallback_to(self.tcx.types.never); - } - DivergingFallbackBehavior::NoFallback => { - debug!( - "no fallback - `rustc_never_type_options::fallback = \"no\"`: {:?}", - diverging_vid - ); - } - } + diverging_fallback.insert(diverging_ty); } - diverging_fallback + (diverging_fallback, diverging_fallback_ty) } fn lint_never_type_fallback_flowing_into_unsafe_code( From 6b36e86fd0d9588965348e8bd3d28298b9504e7a Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Wed, 12 Nov 2025 17:05:25 +0100 Subject: [PATCH 8/8] remove `feature(never_type_fallback)` --- compiler/rustc_feature/src/removed.rs | 2 + compiler/rustc_feature/src/unstable.rs | 2 - .../src/collect/type_of/opaque.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 5 - tests/ui/binding/empty-types-in-patterns.rs | 3 +- ...ce-issue-49593-box-never.nofallback.stderr | 4 +- .../coercion/coerce-issue-49593-box-never.rs | 3 +- .../defaulted-never-note.fallback.stderr | 6 +- .../defaulted-never-note.nofallback.stderr | 4 +- tests/ui/never_type/defaulted-never-note.rs | 8 +- ...ng-fallback-control-flow.nofallback.stderr | 36 ------- .../diverging-fallback-control-flow.rs | 102 ------------------ .../never_type/diverging-fallback-no-leak.rs | 2 +- ...lback-unconstrained-return.fallback.stderr | 24 +++++ ...ack-unconstrained-return.nofallback.stderr | 8 +- ...diverging-fallback-unconstrained-return.rs | 8 +- .../fallback-closure-ret.fallback.stderr | 24 +++++ .../fallback-closure-ret.nofallback.stderr | 4 +- tests/ui/never_type/fallback-closure-ret.rs | 17 ++- .../fallback-closure-wrap.fallback.stderr | 6 +- tests/ui/never_type/fallback-closure-wrap.rs | 3 +- .../feature-gate-never_type_fallback.rs | 13 --- .../feature-gate-never_type_fallback.stderr | 22 ---- ...lue-fallback-issue-66757.nofallback.stderr | 4 +- .../never-value-fallback-issue-66757.rs | 3 +- .../empty-types.exhaustive_patterns.stderr | 100 ++++++++--------- .../usefulness/empty-types.never_pats.stderr | 88 +++++++-------- .../usefulness/empty-types.normal.stderr | 86 +++++++-------- tests/ui/pattern/usefulness/empty-types.rs | 3 +- tests/ui/pattern/usefulness/uninhabited.rs | 2 +- .../ui/reachable/unreachable-loop-patterns.rs | 1 - .../unreachable-loop-patterns.stderr | 4 +- 32 files changed, 227 insertions(+), 372 deletions(-) delete mode 100644 tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr delete mode 100644 tests/ui/never_type/diverging-fallback-control-flow.rs create mode 100644 tests/ui/never_type/diverging-fallback-unconstrained-return.fallback.stderr create mode 100644 tests/ui/never_type/fallback-closure-ret.fallback.stderr delete mode 100644 tests/ui/never_type/feature-gate-never_type_fallback.rs delete mode 100644 tests/ui/never_type/feature-gate-never_type_fallback.stderr diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index a7584df8927ed..cd61facb39bb1 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -189,6 +189,8 @@ declare_features! ( Some("subsumed by `#![feature(allocator_internals)]`")), /// Allows use of unary negate on unsigned integers, e.g., -e for e: u8 (removed, negate_unsigned, "1.0.0", Some(29645), None), + /// Allows diverging expressions to fall back to `!` rather than `()`. + (removed, never_type_fallback, "CURRENT_RUSTC_VERSION", Some(65992), Some("removed in favor of unconditional fallback"), 148871), /// Allows `#[no_coverage]` on functions. /// The feature was renamed to `coverage_attribute` and the attribute to `#[coverage(on|off)]` (removed, no_coverage, "1.74.0", Some(84605), Some("renamed to `coverage_attribute`"), 114656), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index f51bc7031c31d..79ec11a11e1f9 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -596,8 +596,6 @@ declare_features! ( (incomplete, never_patterns, "1.76.0", Some(118155)), /// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more. (unstable, never_type, "1.13.0", Some(35121)), - /// Allows diverging expressions to fall back to `!` rather than `()`. - (unstable, never_type_fallback, "1.41.0", Some(65992)), /// Switch `..` syntax to use the new (`Copy + IntoIterator`) range types. (unstable, new_range, "1.86.0", Some(123741)), /// Allows `#![no_core]`. diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 03216d009c2e7..b31da6b387299 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -265,7 +265,7 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( // so we can just make the hidden type be `!`. // For backwards compatibility reasons, we fall back to // `()` until we the diverging default is changed. - EarlyBinder::bind(Ty::new_diverging_default(tcx)) + EarlyBinder::bind(tcx.types.unit) } } DefiningScopeKind::MirBorrowck => match tcx.mir_borrowck(owner_def_id) { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d8f16ef5561db..e71bb9b6bb267 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -878,11 +878,6 @@ impl<'tcx> Ty<'tcx> { Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, tcx.types.str_) } - #[inline] - pub fn new_diverging_default(tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - if tcx.features().never_type_fallback() { tcx.types.never } else { tcx.types.unit } - } - // lang and diagnostic tys fn new_generic_adt(tcx: TyCtxt<'tcx>, wrapper_def_id: DefId, ty_param: Ty<'tcx>) -> Ty<'tcx> { diff --git a/tests/ui/binding/empty-types-in-patterns.rs b/tests/ui/binding/empty-types-in-patterns.rs index 48a8c4197241e..c6765a1cecef5 100644 --- a/tests/ui/binding/empty-types-in-patterns.rs +++ b/tests/ui/binding/empty-types-in-patterns.rs @@ -1,6 +1,7 @@ //@ run-pass +//@ edition: 2024 -#![feature(never_type, never_type_fallback)] +#![feature(never_type)] #![feature(exhaustive_patterns)] #![allow(unreachable_patterns)] diff --git a/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr b/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr index 7222af43b0137..b1c4b067305f4 100644 --- a/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr +++ b/tests/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied - --> $DIR/coerce-issue-49593-box-never.rs:18:5 + --> $DIR/coerce-issue-49593-box-never.rs:17:5 | LL | Box::<_ /* ! */>::new(x) | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` @@ -7,7 +7,7 @@ LL | Box::<_ /* ! */>::new(x) = note: required for the cast from `Box<()>` to `Box<(dyn std::error::Error + 'static)>` error[E0277]: the trait bound `(): std::error::Error` is not satisfied - --> $DIR/coerce-issue-49593-box-never.rs:24:5 + --> $DIR/coerce-issue-49593-box-never.rs:23:5 | LL | raw_ptr_box::<_ /* ! */>(x) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` diff --git a/tests/ui/coercion/coerce-issue-49593-box-never.rs b/tests/ui/coercion/coerce-issue-49593-box-never.rs index e556959204590..6706d07e1f764 100644 --- a/tests/ui/coercion/coerce-issue-49593-box-never.rs +++ b/tests/ui/coercion/coerce-issue-49593-box-never.rs @@ -1,9 +1,8 @@ //@ revisions: nofallback fallback +//@[fallback] edition: 2024 //@[fallback] check-pass #![feature(never_type)] -#![cfg_attr(fallback, feature(never_type_fallback))] -#![allow(unreachable_code)] use std::error::Error; use std::mem; diff --git a/tests/ui/never_type/defaulted-never-note.fallback.stderr b/tests/ui/never_type/defaulted-never-note.fallback.stderr index 560a53a7a04b6..ab80b138a2fbc 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:31:9 + --> $DIR/defaulted-never-note.rs:27:9 | LL | foo(_x); | --- ^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!` @@ -7,14 +7,14 @@ LL | foo(_x); | required by a bound introduced by this call | help: the trait `ImplementedForUnitButNotNever` is implemented for `()` - --> $DIR/defaulted-never-note.rs:24:1 + --> $DIR/defaulted-never-note.rs:20:1 | LL | impl ImplementedForUnitButNotNever for () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) = help: you might have intended to use the type `()` here instead note: required by a bound in `foo` - --> $DIR/defaulted-never-note.rs:26:11 + --> $DIR/defaulted-never-note.rs:22:11 | LL | fn foo(_t: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` diff --git a/tests/ui/never_type/defaulted-never-note.nofallback.stderr b/tests/ui/never_type/defaulted-never-note.nofallback.stderr index 05e5f6d35580e..f084985153c6b 100644 --- a/tests/ui/never_type/defaulted-never-note.nofallback.stderr +++ b/tests/ui/never_type/defaulted-never-note.nofallback.stderr @@ -1,13 +1,13 @@ Future incompatibility report: Future breakage diagnostic: warning: this function depends on never type fallback being `()` - --> $DIR/defaulted-never-note.rs:29:1 + --> $DIR/defaulted-never-note.rs:25:1 | LL | fn smeg() { | ^^^^^^^^^ | = help: specify the types explicitly note: in edition 2024, the requirement `!: ImplementedForUnitButNotNever` will fail - --> $DIR/defaulted-never-note.rs:31:9 + --> $DIR/defaulted-never-note.rs:27:9 | LL | foo(_x); | ^^ diff --git a/tests/ui/never_type/defaulted-never-note.rs b/tests/ui/never_type/defaulted-never-note.rs index 63647d596c170..71b3e0bcf80a7 100644 --- a/tests/ui/never_type/defaulted-never-note.rs +++ b/tests/ui/never_type/defaulted-never-note.rs @@ -1,13 +1,9 @@ //@ revisions: nofallback fallback +//@[fallback] edition: 2024 //@[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)] -#![expect(dependency_on_unit_never_type_fallback)] +#![expect(dependency_on_unit_never_type_fallback, unused)] trait Deserialize: Sized { fn deserialize() -> Result; diff --git a/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr b/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr deleted file mode 100644 index 49930e0d3449a..0000000000000 --- a/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr +++ /dev/null @@ -1,36 +0,0 @@ -Future incompatibility report: Future breakage diagnostic: -warning: this function depends on never type fallback being `()` - --> $DIR/diverging-fallback-control-flow.rs:32:1 - | -LL | fn assignment() { - | ^^^^^^^^^^^^^^^ - | - = help: specify the types explicitly -note: in edition 2024, the requirement `!: UnitDefault` will fail - --> $DIR/diverging-fallback-control-flow.rs:36:13 - | -LL | x = UnitDefault::default(); - | ^^^^^^^^^^^^^^^^^^^^^^ -help: use `()` annotations to avoid fallback changes - | -LL | let x: (); - | ++++ - -Future breakage diagnostic: -warning: this function depends on never type fallback being `()` - --> $DIR/diverging-fallback-control-flow.rs:42:1 - | -LL | fn assignment_rev() { - | ^^^^^^^^^^^^^^^^^^^ - | - = help: specify the types explicitly -note: in edition 2024, the requirement `!: UnitDefault` will fail - --> $DIR/diverging-fallback-control-flow.rs:48:13 - | -LL | x = UnitDefault::default(); - | ^^^^^^^^^^^^^^^^^^^^^^ -help: use `()` annotations to avoid fallback changes - | -LL | let x: (); - | ++++ - diff --git a/tests/ui/never_type/diverging-fallback-control-flow.rs b/tests/ui/never_type/diverging-fallback-control-flow.rs deleted file mode 100644 index c00c97ecb143a..0000000000000 --- a/tests/ui/never_type/diverging-fallback-control-flow.rs +++ /dev/null @@ -1,102 +0,0 @@ -//@ revisions: nofallback fallback -//@ check-pass - -#![allow(dead_code)] -#![allow(unused_assignments)] -#![allow(unused_variables)] -#![allow(unreachable_code)] -#![cfg_attr(nofallback, expect(dependency_on_unit_never_type_fallback))] - -// 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.rs b/tests/ui/never_type/diverging-fallback-no-leak.rs index b00802d172496..d2bc064e4fd56 100644 --- a/tests/ui/never_type/diverging-fallback-no-leak.rs +++ b/tests/ui/never_type/diverging-fallback-no-leak.rs @@ -1,7 +1,7 @@ //@ revisions: nofallback fallback +//@[fallback] edition: 2024 //@[nofallback] check-pass -#![cfg_attr(fallback, feature(never_type, never_type_fallback))] #![cfg_attr(nofallback, expect(dependency_on_unit_never_type_fallback))] fn make_unit() {} diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.fallback.stderr b/tests/ui/never_type/diverging-fallback-unconstrained-return.fallback.stderr new file mode 100644 index 0000000000000..2a81d0032856c --- /dev/null +++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.fallback.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `!: UnitReturn` is not satisfied + --> $DIR/diverging-fallback-unconstrained-return.rs:37:23 + | +LL | let _ = if true { unconstrained_return() } else { panic!() }; + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `UnitReturn` is not implemented for `!` + | +help: the following other types implement trait `UnitReturn` + --> $DIR/diverging-fallback-unconstrained-return.rs:15:1 + | +LL | impl UnitReturn for i32 {} + | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` +LL | impl UnitReturn for () {} + | ^^^^^^^^^^^^^^^^^^^^^^ `()` + = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) + = help: you might have intended to use the type `()` here instead +note: required by a bound in `unconstrained_return` + --> $DIR/diverging-fallback-unconstrained-return.rs:18:28 + | +LL | fn unconstrained_return() -> T { + | ^^^^^^^^^^ required by this bound in `unconstrained_return` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr b/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr index 1a6ea52246201..eb79cf5dd1559 100644 --- a/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr +++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr @@ -1,5 +1,5 @@ error: this function depends on never type fallback being `()` - --> $DIR/diverging-fallback-unconstrained-return.rs:28:1 + --> $DIR/diverging-fallback-unconstrained-return.rs:26:1 | LL | fn main() { | ^^^^^^^^^ @@ -8,7 +8,7 @@ LL | fn main() { = note: for more information, see = help: specify the types explicitly note: in edition 2024, the requirement `!: UnitReturn` will fail - --> $DIR/diverging-fallback-unconstrained-return.rs:39:23 + --> $DIR/diverging-fallback-unconstrained-return.rs:37:23 | LL | let _ = if true { unconstrained_return() } else { panic!() }; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ error: aborting due to 1 previous error Future incompatibility report: Future breakage diagnostic: error: this function depends on never type fallback being `()` - --> $DIR/diverging-fallback-unconstrained-return.rs:28:1 + --> $DIR/diverging-fallback-unconstrained-return.rs:26:1 | LL | fn main() { | ^^^^^^^^^ @@ -31,7 +31,7 @@ LL | fn main() { = note: for more information, see = help: specify the types explicitly note: in edition 2024, the requirement `!: UnitReturn` will fail - --> $DIR/diverging-fallback-unconstrained-return.rs:39:23 + --> $DIR/diverging-fallback-unconstrained-return.rs:37:23 | LL | let _ = if true { unconstrained_return() } else { panic!() }; | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs index 62042912f03ae..565fac34bd786 100644 --- a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs +++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs @@ -4,12 +4,10 @@ // in the objc crate, where changing the fallback from `!` to `()` // resulted in unsoundness. // -//@[fallback] check-pass - //@ revisions: nofallback fallback +//@[fallback] edition: 2024 -#![cfg_attr(fallback, feature(never_type, never_type_fallback))] -#![allow(unit_bindings)] +#![expect(unit_bindings)] fn make_unit() {} @@ -36,5 +34,5 @@ fn main() { // 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!() }; + let _ = if true { unconstrained_return() } else { panic!() }; //[fallback]~ error: the trait bound `!: UnitReturn` is not satisfied } diff --git a/tests/ui/never_type/fallback-closure-ret.fallback.stderr b/tests/ui/never_type/fallback-closure-ret.fallback.stderr new file mode 100644 index 0000000000000..f43c81b981bac --- /dev/null +++ b/tests/ui/never_type/fallback-closure-ret.fallback.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `!: Bar` is not satisfied + --> $DIR/fallback-closure-ret.rs:18:5 + | +LL | foo(|| panic!()); + | ^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `!` + | +help: the following other types implement trait `Bar` + --> $DIR/fallback-closure-ret.rs:12:1 + | +LL | impl Bar for () {} + | ^^^^^^^^^^^^^^^ `()` +LL | impl Bar for u32 {} + | ^^^^^^^^^^^^^^^^ `u32` + = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 for more information) + = help: you might have intended to use the type `()` here instead +note: required by a bound in `foo` + --> $DIR/fallback-closure-ret.rs:15:11 + | +LL | fn foo(_: impl Fn() -> R) {} + | ^^^ required by this bound in `foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr index 3c5c24853d687..fd7f5fea02196 100644 --- a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr +++ b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr @@ -1,13 +1,13 @@ Future incompatibility report: Future breakage diagnostic: warning: this function depends on never type fallback being `()` - --> $DIR/fallback-closure-ret.rs:22:1 + --> $DIR/fallback-closure-ret.rs:17:1 | LL | fn main() { | ^^^^^^^^^ | = help: specify the types explicitly note: in edition 2024, the requirement `!: Bar` will fail - --> $DIR/fallback-closure-ret.rs:23:5 + --> $DIR/fallback-closure-ret.rs:18:5 | LL | foo(|| panic!()); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/never_type/fallback-closure-ret.rs b/tests/ui/never_type/fallback-closure-ret.rs index 0d92b39d42d7b..4f2bc16e7d568 100644 --- a/tests/ui/never_type/fallback-closure-ret.rs +++ b/tests/ui/never_type/fallback-closure-ret.rs @@ -1,16 +1,11 @@ -// 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`. +// This test used to test that this pattern is not broken by context dependant +// never type fallback. However, it got removed, so now this is an example of +// expected breakage from the never type fallback change. // //@ revisions: nofallback fallback -//@ check-pass +//@[nofallback] check-pass +//@[fallback] edition: 2024 -#![cfg_attr(fallback, feature(never_type_fallback))] #![cfg_attr(nofallback, expect(dependency_on_unit_never_type_fallback))] trait Bar {} @@ -20,5 +15,5 @@ impl Bar for u32 {} fn foo(_: impl Fn() -> R) {} fn main() { - foo(|| panic!()); + foo(|| panic!()); //[fallback]~ error: the trait bound `!: Bar` is not satisfied } diff --git a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr index afb929454c7da..e3d8718682fb7 100644 --- a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr +++ b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -1,5 +1,5 @@ -error[E0271]: expected `{closure@fallback-closure-wrap.rs:18:40}` to return `()`, but it returns `!` - --> $DIR/fallback-closure-wrap.rs:19:9 +error[E0271]: expected `{closure@fallback-closure-wrap.rs:17:40}` to return `()`, but it returns `!` + --> $DIR/fallback-closure-wrap.rs:18:9 | LL | let error = Closure::wrap(Box::new(move || { | ------- this closure @@ -8,7 +8,7 @@ LL | panic!("Can't connect to server."); | = note: expected unit type `()` found type `!` - = note: required for the cast from `Box<{closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47}>` to `Box` + = note: required for the cast from `Box<{closure@$DIR/fallback-closure-wrap.rs:17:40: 17:47}>` to `Box` error: aborting due to 1 previous error diff --git a/tests/ui/never_type/fallback-closure-wrap.rs b/tests/ui/never_type/fallback-closure-wrap.rs index 106b82b5f781b..77546bb93c28d 100644 --- a/tests/ui/never_type/fallback-closure-wrap.rs +++ b/tests/ui/never_type/fallback-closure-wrap.rs @@ -7,11 +7,10 @@ // awareness. // //@ revisions: nofallback fallback +//@[fallback] edition: 2024 //@[nofallback] check-pass //@[fallback] check-fail -#![cfg_attr(fallback, feature(never_type_fallback))] - use std::marker::PhantomData; fn main() { diff --git a/tests/ui/never_type/feature-gate-never_type_fallback.rs b/tests/ui/never_type/feature-gate-never_type_fallback.rs deleted file mode 100644 index 7d02084118001..0000000000000 --- a/tests/ui/never_type/feature-gate-never_type_fallback.rs +++ /dev/null @@ -1,13 +0,0 @@ -// 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 deleted file mode 100644 index 8dbd43e121bb9..0000000000000 --- a/tests/ui/never_type/feature-gate-never_type_fallback.stderr +++ /dev/null @@ -1,22 +0,0 @@ -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 `()` - | | - | required by a bound introduced by this call - | -help: this trait has no implementations, consider adding one - --> $DIR/feature-gate-never_type_fallback.rs:7:1 - | -LL | trait T {} - | ^^^^^^^ -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 1 previous error - -For more information about this error, try `rustc --explain E0277`. 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 index 199f113ddc496..d00118cd61da2 100644 --- a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr +++ b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr @@ -1,12 +1,12 @@ error[E0277]: the trait bound `E: From<()>` is not satisfied - --> $DIR/never-value-fallback-issue-66757.rs:28:6 + --> $DIR/never-value-fallback-issue-66757.rs:27:6 | LL | >::from(never); | ^ unsatisfied trait bound | help: the trait `From<()>` is not implemented for `E` but trait `From` is implemented for it - --> $DIR/never-value-fallback-issue-66757.rs:17:1 + --> $DIR/never-value-fallback-issue-66757.rs:16:1 | LL | impl From for E { | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/never_type/never-value-fallback-issue-66757.rs b/tests/ui/never_type/never-value-fallback-issue-66757.rs index 636757c70ec51..a113d1b13a4ae 100644 --- a/tests/ui/never_type/never-value-fallback-issue-66757.rs +++ b/tests/ui/never_type/never-value-fallback-issue-66757.rs @@ -5,13 +5,12 @@ // doesn't fallback to `()` but rather `!`. // //@ revisions: nofallback fallback +//@[fallback] edition: 2024 //@[fallback] run-pass //@[nofallback] check-fail #![feature(never_type)] -#![cfg_attr(fallback, feature(never_type_fallback))] - struct E; impl From for E { diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr index d241f417553fc..a9fc99a5f41fd 100644 --- a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/empty-types.rs:49:9 + --> $DIR/empty-types.rs:48:9 | LL | _ => {} | ^------ @@ -9,13 +9,13 @@ LL | _ => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here - --> $DIR/empty-types.rs:15:9 + --> $DIR/empty-types.rs:14:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:52:9 + --> $DIR/empty-types.rs:51:9 | LL | _x => {} | ^^------ @@ -26,7 +26,7 @@ LL | _x => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `&!` is non-empty - --> $DIR/empty-types.rs:56:11 + --> $DIR/empty-types.rs:55:11 | LL | match ref_never {} | ^^^^^^^^^ @@ -41,7 +41,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:70:9 + --> $DIR/empty-types.rs:69:9 | LL | (_, _) => {} | ^^^^^^------ @@ -52,7 +52,7 @@ LL | (_, _) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:76:9 + --> $DIR/empty-types.rs:75:9 | LL | _ => {} | ^------ @@ -63,7 +63,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:79:9 + --> $DIR/empty-types.rs:78:9 | LL | (_, _) => {} | ^^^^^^------ @@ -74,7 +74,7 @@ LL | (_, _) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:83:9 + --> $DIR/empty-types.rs:82:9 | LL | _ => {} | ^------ @@ -85,7 +85,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Ok(_)` not covered - --> $DIR/empty-types.rs:87:11 + --> $DIR/empty-types.rs:86:11 | LL | match res_u32_never {} | ^^^^^^^^^^^^^ pattern `Ok(_)` not covered @@ -104,7 +104,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:94:9 + --> $DIR/empty-types.rs:93:9 | LL | Err(_) => {} | ^^^^^^------ @@ -115,7 +115,7 @@ LL | Err(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:99:9 + --> $DIR/empty-types.rs:98:9 | LL | Err(_) => {} | ^^^^^^------ @@ -126,7 +126,7 @@ LL | Err(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered - --> $DIR/empty-types.rs:96:11 + --> $DIR/empty-types.rs:95:11 | LL | match res_u32_never { | ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered @@ -144,7 +144,7 @@ LL ~ Ok(1_u32..=u32::MAX) => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:102:9 + --> $DIR/empty-types.rs:101:9 | LL | let Ok(_x) = res_u32_never.as_ref(); | ^^^^^^ pattern `Err(_)` not covered @@ -158,7 +158,7 @@ LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() }; | ++++++++++++++++ error: unreachable pattern - --> $DIR/empty-types.rs:112:9 + --> $DIR/empty-types.rs:111:9 | LL | _ => {} | ^------ @@ -169,7 +169,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:115:9 + --> $DIR/empty-types.rs:114:9 | LL | Ok(_) => {} | ^^^^^------ @@ -180,7 +180,7 @@ LL | Ok(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:118:9 + --> $DIR/empty-types.rs:117:9 | LL | Ok(_) => {} | ^^^^^------ @@ -191,7 +191,7 @@ LL | Ok(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:119:9 + --> $DIR/empty-types.rs:118:9 | LL | _ => {} | ^------ @@ -202,7 +202,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:122:9 + --> $DIR/empty-types.rs:121:9 | LL | Ok(_) => {} | ^^^^^------ @@ -213,7 +213,7 @@ LL | Ok(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:123:9 + --> $DIR/empty-types.rs:122:9 | LL | Err(_) => {} | ^^^^^^------ @@ -224,7 +224,7 @@ LL | Err(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:132:13 + --> $DIR/empty-types.rs:131:13 | LL | _ => {} | ^------ @@ -235,7 +235,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:135:13 + --> $DIR/empty-types.rs:134:13 | LL | _ if false => {} | ^--------------- @@ -246,7 +246,7 @@ LL | _ if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:143:13 + --> $DIR/empty-types.rs:142:13 | LL | Some(_) => {} | ^^^^^^^------ @@ -257,7 +257,7 @@ LL | Some(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:147:13 + --> $DIR/empty-types.rs:146:13 | LL | None => {} | ---- matches all the relevant values @@ -265,7 +265,7 @@ LL | _ => {} | ^ no value can reach this error: unreachable pattern - --> $DIR/empty-types.rs:199:13 + --> $DIR/empty-types.rs:198:13 | LL | _ => {} | ^------ @@ -276,7 +276,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:204:13 + --> $DIR/empty-types.rs:203:13 | LL | _ => {} | ^------ @@ -287,7 +287,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:209:13 + --> $DIR/empty-types.rs:208:13 | LL | _ => {} | ^------ @@ -298,7 +298,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:214:13 + --> $DIR/empty-types.rs:213:13 | LL | _ => {} | ^------ @@ -309,7 +309,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:220:13 + --> $DIR/empty-types.rs:219:13 | LL | _ => {} | ^------ @@ -320,7 +320,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:281:9 + --> $DIR/empty-types.rs:280:9 | LL | _ => {} | ^------ @@ -331,7 +331,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:284:9 + --> $DIR/empty-types.rs:283:9 | LL | (_, _) => {} | ^^^^^^------ @@ -342,7 +342,7 @@ LL | (_, _) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:287:9 + --> $DIR/empty-types.rs:286:9 | LL | Ok(_) => {} | ^^^^^------ @@ -353,7 +353,7 @@ LL | Ok(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:288:9 + --> $DIR/empty-types.rs:287:9 | LL | Err(_) => {} | ^^^^^^------ @@ -364,7 +364,7 @@ LL | Err(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty - --> $DIR/empty-types.rs:327:11 + --> $DIR/empty-types.rs:326:11 | LL | match slice_never {} | ^^^^^^^^^^^ @@ -378,7 +378,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `&[]` not covered - --> $DIR/empty-types.rs:338:11 + --> $DIR/empty-types.rs:337:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[]` not covered @@ -391,7 +391,7 @@ LL + &[] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` not covered - --> $DIR/empty-types.rs:352:11 + --> $DIR/empty-types.rs:351:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[]` not covered @@ -405,7 +405,7 @@ LL + &[] => todo!() | error[E0004]: non-exhaustive patterns: type `[!]` is non-empty - --> $DIR/empty-types.rs:359:11 + --> $DIR/empty-types.rs:358:11 | LL | match *slice_never {} | ^^^^^^^^^^^^ @@ -419,7 +419,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:368:9 + --> $DIR/empty-types.rs:367:9 | LL | _ => {} | ^------ @@ -430,7 +430,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:371:9 + --> $DIR/empty-types.rs:370:9 | LL | [_, _, _] => {} | ^^^^^^^^^------ @@ -441,7 +441,7 @@ LL | [_, _, _] => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:374:9 + --> $DIR/empty-types.rs:373:9 | LL | [_, ..] => {} | ^^^^^^^------ @@ -452,7 +452,7 @@ LL | [_, ..] => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty - --> $DIR/empty-types.rs:388:11 + --> $DIR/empty-types.rs:387:11 | LL | match array_0_never {} | ^^^^^^^^^^^^^ @@ -466,7 +466,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:395:9 + --> $DIR/empty-types.rs:394:9 | LL | [] => {} | -- matches all the relevant values @@ -474,7 +474,7 @@ LL | _ => {} | ^ no value can reach this error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/empty-types.rs:397:11 + --> $DIR/empty-types.rs:396:11 | LL | match array_0_never { | ^^^^^^^^^^^^^ pattern `[]` not covered @@ -488,7 +488,7 @@ LL + [] => todo!() | error: unreachable pattern - --> $DIR/empty-types.rs:416:9 + --> $DIR/empty-types.rs:415:9 | LL | Some(_) => {} | ^^^^^^^------ @@ -499,7 +499,7 @@ LL | Some(_) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:421:9 + --> $DIR/empty-types.rs:420:9 | LL | Some(_a) => {} | ^^^^^^^^------ @@ -510,7 +510,7 @@ LL | Some(_a) => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:426:9 + --> $DIR/empty-types.rs:425:9 | LL | None => {} | ---- matches all the relevant values @@ -519,7 +519,7 @@ LL | _ => {} | ^ no value can reach this error: unreachable pattern - --> $DIR/empty-types.rs:431:9 + --> $DIR/empty-types.rs:430:9 | LL | None => {} | ---- matches all the relevant values @@ -528,7 +528,7 @@ LL | _a => {} | ^^ no value can reach this error: unreachable pattern - --> $DIR/empty-types.rs:603:9 + --> $DIR/empty-types.rs:602:9 | LL | _ => {} | ^------ @@ -539,7 +539,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:606:9 + --> $DIR/empty-types.rs:605:9 | LL | _x => {} | ^^------ @@ -550,7 +550,7 @@ LL | _x => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:609:9 + --> $DIR/empty-types.rs:608:9 | LL | _ if false => {} | ^--------------- @@ -561,7 +561,7 @@ LL | _ if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:612:9 + --> $DIR/empty-types.rs:611:9 | LL | _x if false => {} | ^^--------------- diff --git a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr index ea63d7ba1afd1..9b4052f05f6b4 100644 --- a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr +++ b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr @@ -1,5 +1,5 @@ warning: the feature `never_patterns` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/empty-types.rs:12:33 + --> $DIR/empty-types.rs:11:33 | LL | #![cfg_attr(never_pats, feature(never_patterns))] | ^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![cfg_attr(never_pats, feature(never_patterns))] = note: `#[warn(incomplete_features)]` on by default error: unreachable pattern - --> $DIR/empty-types.rs:49:9 + --> $DIR/empty-types.rs:48:9 | LL | _ => {} | ^------ @@ -18,13 +18,13 @@ LL | _ => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here - --> $DIR/empty-types.rs:15:9 + --> $DIR/empty-types.rs:14:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:52:9 + --> $DIR/empty-types.rs:51:9 | LL | _x => {} | ^^------ @@ -35,7 +35,7 @@ LL | _x => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `&!` is non-empty - --> $DIR/empty-types.rs:56:11 + --> $DIR/empty-types.rs:55:11 | LL | match ref_never {} | ^^^^^^^^^ @@ -50,7 +50,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:83:9 + --> $DIR/empty-types.rs:82:9 | LL | _ => {} | ^------ @@ -61,7 +61,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Ok(_)` not covered - --> $DIR/empty-types.rs:87:11 + --> $DIR/empty-types.rs:86:11 | LL | match res_u32_never {} | ^^^^^^^^^^^^^ pattern `Ok(_)` not covered @@ -80,7 +80,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered - --> $DIR/empty-types.rs:96:11 + --> $DIR/empty-types.rs:95:11 | LL | match res_u32_never { | ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered @@ -98,7 +98,7 @@ LL ~ Ok(1_u32..=u32::MAX) => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:102:9 + --> $DIR/empty-types.rs:101:9 | LL | let Ok(_x) = res_u32_never.as_ref(); | ^^^^^^ pattern `Err(_)` not covered @@ -112,7 +112,7 @@ LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() }; | ++++++++++++++++ error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:106:9 + --> $DIR/empty-types.rs:105:9 | LL | let Ok(_x) = &res_u32_never; | ^^^^^^ pattern `&Err(!)` not covered @@ -126,7 +126,7 @@ LL | let Ok(_x) = &res_u32_never else { todo!() }; | ++++++++++++++++ error: unreachable pattern - --> $DIR/empty-types.rs:132:13 + --> $DIR/empty-types.rs:131:13 | LL | _ => {} | ^------ @@ -137,7 +137,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:135:13 + --> $DIR/empty-types.rs:134:13 | LL | _ if false => {} | ^--------------- @@ -148,7 +148,7 @@ LL | _ if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Some(!)` not covered - --> $DIR/empty-types.rs:156:15 + --> $DIR/empty-types.rs:155:15 | LL | match *ref_opt_void { | ^^^^^^^^^^^^^ pattern `Some(!)` not covered @@ -167,7 +167,7 @@ LL + Some(!) | error: unreachable pattern - --> $DIR/empty-types.rs:199:13 + --> $DIR/empty-types.rs:198:13 | LL | _ => {} | ^------ @@ -178,7 +178,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:204:13 + --> $DIR/empty-types.rs:203:13 | LL | _ => {} | ^------ @@ -189,7 +189,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:209:13 + --> $DIR/empty-types.rs:208:13 | LL | _ => {} | ^------ @@ -200,7 +200,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:214:13 + --> $DIR/empty-types.rs:213:13 | LL | _ => {} | ^------ @@ -211,7 +211,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:220:13 + --> $DIR/empty-types.rs:219:13 | LL | _ => {} | ^------ @@ -222,7 +222,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:281:9 + --> $DIR/empty-types.rs:280:9 | LL | _ => {} | ^------ @@ -233,7 +233,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:297:13 + --> $DIR/empty-types.rs:296:13 | LL | let Ok(_) = *ptr_result_never_err; | ^^^^^ pattern `Err(!)` not covered @@ -247,7 +247,7 @@ LL | if let Ok(_) = *ptr_result_never_err { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:316:11 + --> $DIR/empty-types.rs:315:11 | LL | match *x {} | ^^ @@ -261,7 +261,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty - --> $DIR/empty-types.rs:318:11 + --> $DIR/empty-types.rs:317:11 | LL | match *x {} | ^^ @@ -275,7 +275,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `Ok(!)` and `Err(!)` not covered - --> $DIR/empty-types.rs:320:11 + --> $DIR/empty-types.rs:319:11 | LL | match *x {} | ^^ patterns `Ok(!)` and `Err(!)` not covered @@ -297,7 +297,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty - --> $DIR/empty-types.rs:322:11 + --> $DIR/empty-types.rs:321:11 | LL | match *x {} | ^^ @@ -311,7 +311,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty - --> $DIR/empty-types.rs:327:11 + --> $DIR/empty-types.rs:326:11 | LL | match slice_never {} | ^^^^^^^^^^^ @@ -325,7 +325,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `&[!, ..]` not covered - --> $DIR/empty-types.rs:329:11 + --> $DIR/empty-types.rs:328:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[!, ..]` not covered @@ -339,7 +339,7 @@ LL + &[!, ..] | error[E0004]: non-exhaustive patterns: `&[]`, `&[!]` and `&[!, !]` not covered - --> $DIR/empty-types.rs:338:11 + --> $DIR/empty-types.rs:337:11 | LL | match slice_never { | ^^^^^^^^^^^ patterns `&[]`, `&[!]` and `&[!, !]` not covered @@ -352,7 +352,7 @@ LL + &[] | &[!] | &[!, !] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` and `&[!, ..]` not covered - --> $DIR/empty-types.rs:352:11 + --> $DIR/empty-types.rs:351:11 | LL | match slice_never { | ^^^^^^^^^^^ patterns `&[]` and `&[!, ..]` not covered @@ -366,7 +366,7 @@ LL + &[] | &[!, ..] => todo!() | error[E0004]: non-exhaustive patterns: type `[!]` is non-empty - --> $DIR/empty-types.rs:359:11 + --> $DIR/empty-types.rs:358:11 | LL | match *slice_never {} | ^^^^^^^^^^^^ @@ -380,7 +380,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty - --> $DIR/empty-types.rs:388:11 + --> $DIR/empty-types.rs:387:11 | LL | match array_0_never {} | ^^^^^^^^^^^^^ @@ -394,7 +394,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:395:9 + --> $DIR/empty-types.rs:394:9 | LL | [] => {} | -- matches all the relevant values @@ -402,7 +402,7 @@ LL | _ => {} | ^ no value can reach this error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/empty-types.rs:397:11 + --> $DIR/empty-types.rs:396:11 | LL | match array_0_never { | ^^^^^^^^^^^^^ pattern `[]` not covered @@ -416,7 +416,7 @@ LL + [] => todo!() | error[E0004]: non-exhaustive patterns: `&Some(!)` not covered - --> $DIR/empty-types.rs:451:11 + --> $DIR/empty-types.rs:450:11 | LL | match ref_opt_never { | ^^^^^^^^^^^^^ pattern `&Some(!)` not covered @@ -435,7 +435,7 @@ LL + &Some(!) | error[E0004]: non-exhaustive patterns: `Some(!)` not covered - --> $DIR/empty-types.rs:492:11 + --> $DIR/empty-types.rs:491:11 | LL | match *ref_opt_never { | ^^^^^^^^^^^^^^ pattern `Some(!)` not covered @@ -454,7 +454,7 @@ LL + Some(!) | error[E0004]: non-exhaustive patterns: `Err(!)` not covered - --> $DIR/empty-types.rs:540:11 + --> $DIR/empty-types.rs:539:11 | LL | match *ref_res_never { | ^^^^^^^^^^^^^^ pattern `Err(!)` not covered @@ -473,7 +473,7 @@ LL + Err(!) | error[E0004]: non-exhaustive patterns: `Err(!)` not covered - --> $DIR/empty-types.rs:551:11 + --> $DIR/empty-types.rs:550:11 | LL | match *ref_res_never { | ^^^^^^^^^^^^^^ pattern `Err(!)` not covered @@ -492,7 +492,7 @@ LL + Err(!) | error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:570:11 + --> $DIR/empty-types.rs:569:11 | LL | match *ref_tuple_half_never {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -506,7 +506,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:603:9 + --> $DIR/empty-types.rs:602:9 | LL | _ => {} | ^------ @@ -517,7 +517,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:606:9 + --> $DIR/empty-types.rs:605:9 | LL | _x => {} | ^^------ @@ -528,7 +528,7 @@ LL | _x => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:609:9 + --> $DIR/empty-types.rs:608:9 | LL | _ if false => {} | ^--------------- @@ -539,7 +539,7 @@ LL | _ if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:612:9 + --> $DIR/empty-types.rs:611:9 | LL | _x if false => {} | ^^--------------- @@ -550,7 +550,7 @@ LL | _x if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `&!` not covered - --> $DIR/empty-types.rs:637:11 + --> $DIR/empty-types.rs:636:11 | LL | match ref_never { | ^^^^^^^^^ pattern `&!` not covered @@ -566,7 +566,7 @@ LL + &! | error[E0004]: non-exhaustive patterns: `Ok(!)` not covered - --> $DIR/empty-types.rs:653:11 + --> $DIR/empty-types.rs:652:11 | LL | match *ref_result_never { | ^^^^^^^^^^^^^^^^^ pattern `Ok(!)` not covered @@ -585,7 +585,7 @@ LL + Ok(!) | error[E0004]: non-exhaustive patterns: `Some(!)` not covered - --> $DIR/empty-types.rs:673:11 + --> $DIR/empty-types.rs:672:11 | LL | match *x { | ^^ pattern `Some(!)` not covered diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr index a1a44e7774428..df3277b3f6d15 100644 --- a/tests/ui/pattern/usefulness/empty-types.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr @@ -1,5 +1,5 @@ error: unreachable pattern - --> $DIR/empty-types.rs:49:9 + --> $DIR/empty-types.rs:48:9 | LL | _ => {} | ^------ @@ -9,13 +9,13 @@ LL | _ => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here - --> $DIR/empty-types.rs:15:9 + --> $DIR/empty-types.rs:14:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/empty-types.rs:52:9 + --> $DIR/empty-types.rs:51:9 | LL | _x => {} | ^^------ @@ -26,7 +26,7 @@ LL | _x => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: type `&!` is non-empty - --> $DIR/empty-types.rs:56:11 + --> $DIR/empty-types.rs:55:11 | LL | match ref_never {} | ^^^^^^^^^ @@ -41,7 +41,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:83:9 + --> $DIR/empty-types.rs:82:9 | LL | _ => {} | ^------ @@ -52,7 +52,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Ok(_)` not covered - --> $DIR/empty-types.rs:87:11 + --> $DIR/empty-types.rs:86:11 | LL | match res_u32_never {} | ^^^^^^^^^^^^^ pattern `Ok(_)` not covered @@ -71,7 +71,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered - --> $DIR/empty-types.rs:96:11 + --> $DIR/empty-types.rs:95:11 | LL | match res_u32_never { | ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered @@ -89,7 +89,7 @@ LL ~ Ok(1_u32..=u32::MAX) => todo!() | error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:102:9 + --> $DIR/empty-types.rs:101:9 | LL | let Ok(_x) = res_u32_never.as_ref(); | ^^^^^^ pattern `Err(_)` not covered @@ -103,7 +103,7 @@ LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() }; | ++++++++++++++++ error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:106:9 + --> $DIR/empty-types.rs:105:9 | LL | let Ok(_x) = &res_u32_never; | ^^^^^^ pattern `&Err(_)` not covered @@ -117,7 +117,7 @@ LL | let Ok(_x) = &res_u32_never else { todo!() }; | ++++++++++++++++ error: unreachable pattern - --> $DIR/empty-types.rs:132:13 + --> $DIR/empty-types.rs:131:13 | LL | _ => {} | ^------ @@ -128,7 +128,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:135:13 + --> $DIR/empty-types.rs:134:13 | LL | _ if false => {} | ^--------------- @@ -139,7 +139,7 @@ LL | _ if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:156:15 + --> $DIR/empty-types.rs:155:15 | LL | match *ref_opt_void { | ^^^^^^^^^^^^^ pattern `Some(_)` not covered @@ -158,7 +158,7 @@ LL + Some(_) => todo!() | error: unreachable pattern - --> $DIR/empty-types.rs:199:13 + --> $DIR/empty-types.rs:198:13 | LL | _ => {} | ^------ @@ -169,7 +169,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:204:13 + --> $DIR/empty-types.rs:203:13 | LL | _ => {} | ^------ @@ -180,7 +180,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:209:13 + --> $DIR/empty-types.rs:208:13 | LL | _ => {} | ^------ @@ -191,7 +191,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:214:13 + --> $DIR/empty-types.rs:213:13 | LL | _ => {} | ^------ @@ -202,7 +202,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:220:13 + --> $DIR/empty-types.rs:219:13 | LL | _ => {} | ^------ @@ -213,7 +213,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:281:9 + --> $DIR/empty-types.rs:280:9 | LL | _ => {} | ^------ @@ -224,7 +224,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:297:13 + --> $DIR/empty-types.rs:296:13 | LL | let Ok(_) = *ptr_result_never_err; | ^^^^^ pattern `Err(_)` not covered @@ -238,7 +238,7 @@ LL | if let Ok(_) = *ptr_result_never_err { todo!() }; | ++ +++++++++++ error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:316:11 + --> $DIR/empty-types.rs:315:11 | LL | match *x {} | ^^ @@ -252,7 +252,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty - --> $DIR/empty-types.rs:318:11 + --> $DIR/empty-types.rs:317:11 | LL | match *x {} | ^^ @@ -266,7 +266,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered - --> $DIR/empty-types.rs:320:11 + --> $DIR/empty-types.rs:319:11 | LL | match *x {} | ^^ patterns `Ok(_)` and `Err(_)` not covered @@ -288,7 +288,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty - --> $DIR/empty-types.rs:322:11 + --> $DIR/empty-types.rs:321:11 | LL | match *x {} | ^^ @@ -302,7 +302,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty - --> $DIR/empty-types.rs:327:11 + --> $DIR/empty-types.rs:326:11 | LL | match slice_never {} | ^^^^^^^^^^^ @@ -316,7 +316,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered - --> $DIR/empty-types.rs:329:11 + --> $DIR/empty-types.rs:328:11 | LL | match slice_never { | ^^^^^^^^^^^ pattern `&[_, ..]` not covered @@ -330,7 +330,7 @@ LL + &[_, ..] => todo!() | error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered - --> $DIR/empty-types.rs:338:11 + --> $DIR/empty-types.rs:337:11 | LL | match slice_never { | ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered @@ -343,7 +343,7 @@ LL + &[] | &[_] | &[_, _] => todo!() | error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered - --> $DIR/empty-types.rs:352:11 + --> $DIR/empty-types.rs:351:11 | LL | match slice_never { | ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered @@ -357,7 +357,7 @@ LL + &[] | &[_, ..] => todo!() | error[E0004]: non-exhaustive patterns: type `[!]` is non-empty - --> $DIR/empty-types.rs:359:11 + --> $DIR/empty-types.rs:358:11 | LL | match *slice_never {} | ^^^^^^^^^^^^ @@ -371,7 +371,7 @@ LL ~ } | error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty - --> $DIR/empty-types.rs:388:11 + --> $DIR/empty-types.rs:387:11 | LL | match array_0_never {} | ^^^^^^^^^^^^^ @@ -385,7 +385,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:395:9 + --> $DIR/empty-types.rs:394:9 | LL | [] => {} | -- matches all the relevant values @@ -393,7 +393,7 @@ LL | _ => {} | ^ no value can reach this error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/empty-types.rs:397:11 + --> $DIR/empty-types.rs:396:11 | LL | match array_0_never { | ^^^^^^^^^^^^^ pattern `[]` not covered @@ -407,7 +407,7 @@ LL + [] => todo!() | error[E0004]: non-exhaustive patterns: `&Some(_)` not covered - --> $DIR/empty-types.rs:451:11 + --> $DIR/empty-types.rs:450:11 | LL | match ref_opt_never { | ^^^^^^^^^^^^^ pattern `&Some(_)` not covered @@ -426,7 +426,7 @@ LL + &Some(_) => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:492:11 + --> $DIR/empty-types.rs:491:11 | LL | match *ref_opt_never { | ^^^^^^^^^^^^^^ pattern `Some(_)` not covered @@ -445,7 +445,7 @@ LL + Some(_) => todo!() | error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/empty-types.rs:540:11 + --> $DIR/empty-types.rs:539:11 | LL | match *ref_res_never { | ^^^^^^^^^^^^^^ pattern `Err(_)` not covered @@ -464,7 +464,7 @@ LL + Err(_) => todo!() | error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/empty-types.rs:551:11 + --> $DIR/empty-types.rs:550:11 | LL | match *ref_res_never { | ^^^^^^^^^^^^^^ pattern `Err(_)` not covered @@ -483,7 +483,7 @@ LL + Err(_) => todo!() | error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:570:11 + --> $DIR/empty-types.rs:569:11 | LL | match *ref_tuple_half_never {} | ^^^^^^^^^^^^^^^^^^^^^ @@ -497,7 +497,7 @@ LL ~ } | error: unreachable pattern - --> $DIR/empty-types.rs:603:9 + --> $DIR/empty-types.rs:602:9 | LL | _ => {} | ^------ @@ -508,7 +508,7 @@ LL | _ => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:606:9 + --> $DIR/empty-types.rs:605:9 | LL | _x => {} | ^^------ @@ -519,7 +519,7 @@ LL | _x => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:609:9 + --> $DIR/empty-types.rs:608:9 | LL | _ if false => {} | ^--------------- @@ -530,7 +530,7 @@ LL | _ if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error: unreachable pattern - --> $DIR/empty-types.rs:612:9 + --> $DIR/empty-types.rs:611:9 | LL | _x if false => {} | ^^--------------- @@ -541,7 +541,7 @@ LL | _x if false => {} = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types error[E0004]: non-exhaustive patterns: `&_` not covered - --> $DIR/empty-types.rs:637:11 + --> $DIR/empty-types.rs:636:11 | LL | match ref_never { | ^^^^^^^^^ pattern `&_` not covered @@ -557,7 +557,7 @@ LL + &_ => todo!() | error[E0004]: non-exhaustive patterns: `Ok(_)` not covered - --> $DIR/empty-types.rs:653:11 + --> $DIR/empty-types.rs:652:11 | LL | match *ref_result_never { | ^^^^^^^^^^^^^^^^^ pattern `Ok(_)` not covered @@ -576,7 +576,7 @@ LL + Ok(_) => todo!() | error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:673:11 + --> $DIR/empty-types.rs:672:11 | LL | match *x { | ^^ pattern `Some(_)` not covered diff --git a/tests/ui/pattern/usefulness/empty-types.rs b/tests/ui/pattern/usefulness/empty-types.rs index 9e5f273a39052..a503295fc8741 100644 --- a/tests/ui/pattern/usefulness/empty-types.rs +++ b/tests/ui/pattern/usefulness/empty-types.rs @@ -1,4 +1,5 @@ //@ revisions: normal exhaustive_patterns never_pats +//@ edition: 2024 // // This tests correct handling of empty types in exhaustiveness checking. // @@ -6,8 +7,6 @@ // valid data, namely dereferences and union field accesses. In these cases, empty arms can // generally not be omitted, except with `exhaustive_patterns` which ignores this.. #![feature(never_type)] -// This feature is useful to avoid `!` falling back to `()` all the time. -#![feature(never_type_fallback)] #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] #![cfg_attr(never_pats, feature(never_patterns))] //[never_pats]~^ WARN the feature `never_patterns` is incomplete diff --git a/tests/ui/pattern/usefulness/uninhabited.rs b/tests/ui/pattern/usefulness/uninhabited.rs index 0e2793fb4487b..2e2c7cae65cbc 100644 --- a/tests/ui/pattern/usefulness/uninhabited.rs +++ b/tests/ui/pattern/usefulness/uninhabited.rs @@ -1,10 +1,10 @@ //@ check-pass +//@ edition: 2024 //@ aux-build:empty.rs // // This tests plays with matching and uninhabited types. This also serves as a test for the // `Ty::is_inhabited_from` function. #![feature(never_type)] -#![feature(never_type_fallback)] #![deny(unreachable_patterns)] macro_rules! assert_empty { diff --git a/tests/ui/reachable/unreachable-loop-patterns.rs b/tests/ui/reachable/unreachable-loop-patterns.rs index 9be37ecf2bb27..d401012aad6c5 100644 --- a/tests/ui/reachable/unreachable-loop-patterns.rs +++ b/tests/ui/reachable/unreachable-loop-patterns.rs @@ -1,5 +1,4 @@ #![feature(exhaustive_patterns)] -#![feature(never_type, never_type_fallback)] #![allow(unreachable_code)] #![deny(unreachable_patterns)] diff --git a/tests/ui/reachable/unreachable-loop-patterns.stderr b/tests/ui/reachable/unreachable-loop-patterns.stderr index 290f45700b2e4..03959ac160695 100644 --- a/tests/ui/reachable/unreachable-loop-patterns.stderr +++ b/tests/ui/reachable/unreachable-loop-patterns.stderr @@ -1,12 +1,12 @@ error: unreachable pattern - --> $DIR/unreachable-loop-patterns.rs:17:9 + --> $DIR/unreachable-loop-patterns.rs:16:9 | LL | for _ in unimplemented!() as Void {} | ^ matches no values because `Void` is uninhabited | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types note: the lint level is defined here - --> $DIR/unreachable-loop-patterns.rs:4:9 + --> $DIR/unreachable-loop-patterns.rs:3:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^