Auto merge of #148871 - WaffleLapkin:never-simplifications, r=lcnr

Remove context dependant `!` fallback

... and minor cleanup.

r? lcnr
This commit is contained in:
bors 2025-11-28 09:16:14 +00:00
commit d645a4c9c5
39 changed files with 307 additions and 713 deletions

View file

@ -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),

View file

@ -594,8 +594,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]`.

View file

@ -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) {

View file

@ -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,
@ -35,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::diverging_fallback_has_occurred`]
/// if the never type fallback has occurred.
pub(super) fn type_inference_fallback(&self) {
debug!(
"type-inference-fallback start obligations: {:#?}",
@ -53,34 +49,10 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
let fallback_occurred = self.fallback_types();
if !fallback_occurred {
return;
if fallback_occurred {
// if fallback occurred, previously stalled goals may make progress again
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 {
@ -91,8 +63,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
return false;
}
let diverging_fallback = self
.calculate_diverging_fallback(&unresolved_variables, self.diverging_fallback_behavior);
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.
@ -100,31 +72,33 @@ 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
}
// 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::diverging_fallback_has_occurred`] if never type fallback
/// is performed during this call.
fn fallback_if_possible(
&self,
ty: Ty<'tcx>,
diverging_fallback: &UnordMap<Ty<'tcx>, Ty<'tcx>>,
diverging_fallback: &UnordSet<Ty<'tcx>>,
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
@ -148,93 +122,34 @@ 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) => fallback_ty,
None => return false,
},
_ if diverging_fallback.contains(&ty) => {
self.diverging_fallback_has_occurred.set(true);
diverging_fallback_ty
}
_ => return false,
};
debug!("fallback_if_possible(ty={:?}): defaulting to `{:?}`", ty, fallback);
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
}
/// 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>],
behavior: DivergingFallbackBehavior,
) -> UnordMap<Ty<'tcx>, Ty<'tcx>> {
) -> (UnordSet<Ty<'tcx>>, 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();
@ -267,9 +182,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,54 +193,21 @@ 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::<Vec<_>>()
);
// 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 mut diverging_fallback = UnordSet::with_capacity(diverging_vids.len());
let unsafe_infer_vars = OnceCell::new();
self.lint_obligations_broken_by_never_type_fallback_change(
behavior,
&diverging_vids,
&coercion_graph,
);
@ -335,90 +215,17 @@ 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();
self.lint_never_type_fallback_flowing_into_unsafe_code(
&unsafe_infer_vars,
&coercion_graph,
root_vid,
);
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(
&unsafe_infer_vars,
&coercion_graph,
root_vid,
);
diverging_fallback.insert(diverging_ty, ty);
};
match behavior {
DivergingFallbackBehavior::ToUnit => {
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\")`: {:?}",
diverging_vid
);
fallback_to(self.tcx.types.never);
}
DivergingFallbackBehavior::NoFallback => {
debug!(
"no fallback - `rustc_never_type_mode = \"no_fallback\"`: {:?}",
diverging_vid
);
}
}
diverging_fallback.insert(diverging_ty);
}
diverging_fallback
(diverging_fallback, diverging_fallback_ty)
}
fn lint_never_type_fallback_flowing_into_unsafe_code(
@ -470,11 +277,10 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
fn lint_obligations_broken_by_never_type_fallback_change(
&self,
behavior: DivergingFallbackBehavior,
diverging_vids: &[ty::TyVid],
coercions: &VecGraph<ty::TyVid, true>,
) {
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() {

View file

@ -115,7 +115,9 @@ pub(crate) struct FnCtxt<'a, 'tcx> {
pub(super) root_ctxt: &'a TypeckRootCtxt<'tcx>,
pub(super) fallback_has_occurred: Cell<bool>,
/// True if a divirging inference variable has been set to `()`/`!` because
/// of never type fallback. This is only used for diagnostics.
pub(super) diverging_fallback_has_occurred: Cell<bool>,
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),
diverging_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(),
diverging_fallback_has_occurred: self.diverging_fallback_has_occurred.get(),
normalize_fn_sig: Box::new(|fn_sig| {
if fn_sig.has_escaping_bound_vars() {
return fn_sig;
@ -505,11 +507,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 +533,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),
_ => {

View file

@ -1,35 +1,19 @@
use std::cell::{Cell, RefCell};
use std::ops::Deref;
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_data_structures::unord::UnordSet;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::{self as hir, HirId, HirIdMap, LangItem};
use rustc_hir::{self as hir, HirId, HirIdMap};
use rustc_infer::infer::{InferCtxt, InferOk, OpaqueTypeStorageEntries, TyCtxtInferExt};
use rustc_middle::span_bug;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode};
use rustc_span::Span;
use rustc_span::def_id::LocalDefIdMap;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::{
self, FulfillmentError, PredicateObligation, TraitEngine, TraitEngineExt as _,
};
use tracing::{debug, instrument};
use rustc_trait_selection::traits::{self, FulfillmentError, TraitEngine, TraitEngineExt as _};
use tracing::instrument;
use super::callee::DeferredCallResolution;
#[derive(Debug, Default, Copy, Clone)]
pub(crate) struct InferVarInfo {
/// This is true if we identified that this Ty (`?T`) is found in a `?T: Foo`
/// obligation, where:
///
/// * `Foo` is not `Sized`
/// * `(): Foo` may be satisfied
pub self_in_trait: bool,
/// This is true if we identified that this Ty (`?T`) is found in a `<_ as
/// _>::AssocType = ?T`
pub output: bool,
}
/// Data shared between a "typeck root" and its nested bodies,
/// e.g. closures defined within the function. For example:
/// ```ignore (illustrative)
@ -83,8 +67,6 @@ pub(crate) struct TypeckRootCtxt<'tcx> {
/// we record that type variable here. This is later used to inform
/// fallback. See the `fallback` module for details.
pub(super) diverging_type_vars: RefCell<UnordSet<Ty<'tcx>>>,
pub(super) infer_var_info: RefCell<UnordMap<ty::TyVid, InferVarInfo>>,
}
impl<'tcx> Deref for TypeckRootCtxt<'tcx> {
@ -119,7 +101,6 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
deferred_asm_checks: RefCell::new(Vec::new()),
deferred_repeat_expr_checks: RefCell::new(Vec::new()),
diverging_type_vars: RefCell::new(Default::default()),
infer_var_info: RefCell::new(Default::default()),
}
}
@ -129,8 +110,6 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
span_bug!(obligation.cause.span, "escaping bound vars in predicate {:?}", obligation);
}
self.update_infer_var_info(&obligation);
self.fulfillment_cx.borrow_mut().register_predicate_obligation(self, obligation);
}
@ -147,46 +126,4 @@ impl<'tcx> TypeckRootCtxt<'tcx> {
self.register_predicates(infer_ok.obligations);
infer_ok.value
}
fn update_infer_var_info(&self, obligation: &PredicateObligation<'tcx>) {
let infer_var_info = &mut self.infer_var_info.borrow_mut();
// (*) binder skipped
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(tpred)) =
obligation.predicate.kind().skip_binder()
&& let Some(ty) =
self.shallow_resolve(tpred.self_ty()).ty_vid().map(|t| self.root_var(t))
&& !self.tcx.is_lang_item(tpred.trait_ref.def_id, LangItem::Sized)
{
let new_self_ty = self.tcx.types.unit;
// Then construct a new obligation with Self = () added
// to the ParamEnv, and see if it holds.
let o = obligation.with(
self.tcx,
obligation.predicate.kind().rebind(
// (*) binder moved here
ty::PredicateKind::Clause(ty::ClauseKind::Trait(
tpred.with_replaced_self_ty(self.tcx, new_self_ty),
)),
),
);
// Don't report overflow errors. Otherwise equivalent to may_hold.
if let Ok(result) = self.probe(|_| self.evaluate_obligation(&o))
&& result.may_apply()
{
infer_var_info.entry(ty).or_default().self_in_trait = true;
}
}
if let ty::PredicateKind::Clause(ty::ClauseKind::Projection(predicate)) =
obligation.predicate.kind().skip_binder()
// If the projection predicate (Foo::Bar == X) has X as a non-TyVid,
// we need to make it into one.
&& let Some(vid) = predicate.term.as_type().and_then(|ty| ty.ty_vid())
{
debug!("infer_var_info: {:?}.output = true", vid);
infer_var_info.entry(vid).or_default().output = true;
}
}
}

View file

@ -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> {

View file

@ -21,7 +21,7 @@ pub struct TypeErrCtxt<'a, 'tcx> {
pub infcx: &'a InferCtxt<'tcx>,
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
pub fallback_has_occurred: bool,
pub diverging_fallback_has_occurred: bool,
pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,
@ -36,7 +36,7 @@ impl<'tcx> InferCtxt<'tcx> {
TypeErrCtxt {
infcx: self,
typeck_results: None,
fallback_has_occurred: false,
diverging_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");

View file

@ -541,7 +541,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.diverging_fallback_has_occurred
{
let predicate = leaf_trait_predicate.map_bound(|trait_pred| {
trait_pred.with_replaced_self_ty(self.tcx, tcx.types.unit)
@ -550,8 +550,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
if self.predicate_may_hold(&unit_obligation) {
err.note(
"this error might have been caused by changes to \
Rust's type-inference algorithm (see issue #48950 \
<https://github.com/rust-lang/rust/issues/48950> \
Rust's type-inference algorithm (see issue #148922 \
<https://github.com/rust-lang/rust/issues/148922> \
for more information)",
);
err.help("you might have intended to use the type `()` here instead");

View file

@ -1,6 +1,7 @@
//@ run-pass
//@ edition: 2024
#![feature(never_type, never_type_fallback)]
#![feature(never_type)]
#![feature(exhaustive_patterns)]
#![allow(unreachable_patterns)]

View file

@ -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 `()`

View file

@ -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;

View file

@ -4,7 +4,7 @@ error[E0277]: the trait bound `!: Default` is not satisfied
LL | true => Default::default(),
| ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!`
|
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #148922 <https://github.com/rust-lang/rust/issues/148922> for more information)
= help: you might have intended to use the type `()` here instead
error[E0277]: the trait bound `!: Default` is not satisfied
@ -13,7 +13,7 @@ error[E0277]: the trait bound `!: Default` is not satisfied
LL | deserialize()?;
| ^^^^^^^^^^^^^ the trait `Default` is not implemented for `!`
|
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #148922 <https://github.com/rust-lang/rust/issues/148922> for more information)
= help: you might have intended to use the type `()` here instead
note: required by a bound in `deserialize`
--> $DIR/never-type-fallback-breaking.rs:31:23
@ -50,7 +50,7 @@ error[E0277]: the trait bound `!: Default` is not satisfied
LL | takes_apit(|| Default::default())?;
| ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!`
|
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #148922 <https://github.com/rust-lang/rust/issues/148922> for more information)
= help: you might have intended to use the type `()` here instead
error[E0277]: the trait bound `!: Default` is not satisfied
@ -61,7 +61,7 @@ LL | takes_apit2(mk()?);
| |
| required by a bound introduced by this call
|
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #148922 <https://github.com/rust-lang/rust/issues/148922> for more information)
= help: you might have intended to use the type `()` here instead
note: required by a bound in `takes_apit2`
--> $DIR/never-type-fallback-breaking.rs:69:25

View file

@ -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 <https://github.com/rust-lang/rust/issues/48950> for more information)
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #148922 <https://github.com/rust-lang/rust/issues/148922> 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: ImplementedForUnitButNotNever>(_t: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`

View file

@ -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);
| ^^

View file

@ -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<Self, String>;

View file

@ -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: ();
| ++++

View file

@ -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() {}

View file

@ -13,7 +13,7 @@ LL | impl Test for i32 {}
| ^^^^^^^^^^^^^^^^^ `i32`
LL | impl Test for () {}
| ^^^^^^^^^^^^^^^^ `()`
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
= note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #148922 <https://github.com/rust-lang/rust/issues/148922> for more information)
= help: you might have intended to use the type `()` here instead
note: required by a bound in `unconstrained_arg`
--> $DIR/diverging-fallback-no-leak.rs:13:25

View file

@ -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() {}

View file

@ -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 #148922 <https://github.com/rust-lang/rust/issues/148922> 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: UnitReturn>() -> 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`.

View file

@ -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 <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html>
= 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 <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html>
= 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!() };
| ^^^^^^^^^^^^^^^^^^^^^^

View file

@ -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
}

View file

@ -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 #148922 <https://github.com/rust-lang/rust/issues/148922> 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<R: Bar>(_: 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`.

View file

@ -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!());
| ^^^^^^^^^^^^^^^^

View file

@ -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<R: Bar>(_: impl Fn() -> R) {}
fn main() {
foo(|| panic!());
foo(|| panic!()); //[fallback]~ error: the trait bound `!: Bar` is not satisfied
}

View file

@ -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<dyn FnMut()>`
= note: required for the cast from `Box<{closure@$DIR/fallback-closure-wrap.rs:17:40: 17:47}>` to `Box<dyn FnMut()>`
error: aborting due to 1 previous error

View file

@ -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() {

View file

@ -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) {}

View file

@ -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`.

View file

@ -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 | <E as From<_>>::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 {
| ^^^^^^^^^^^^^^^^^^

View file

@ -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 {

View file

@ -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,18 @@ 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(_) => {}
| ^^^^^------
| |
| matches no values because `Result<!, !>` is uninhabited
| help: remove the match arm
|
= 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:117:9
|
LL | Ok(_) => {}
| ^^^^^------
@ -182,17 +193,6 @@ LL | Ok(_) => {}
error: unreachable pattern
--> $DIR/empty-types.rs:118:9
|
LL | Ok(_) => {}
| ^^^^^------
| |
| matches no values because `Result<!, !>` is uninhabited
| help: remove the match arm
|
= 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
|
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 => {}
| ^^---------------

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 {

View file

@ -1,5 +1,4 @@
#![feature(exhaustive_patterns)]
#![feature(never_type, never_type_fallback)]
#![allow(unreachable_code)]
#![deny(unreachable_patterns)]

View file

@ -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)]
| ^^^^^^^^^^^^^^^^^^^^