Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_feature/src/removed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ declare_features! (
Some("removed in favor of full type_alias_impl_trait"), 87564),
/// Make `mut` not reset the binding mode on edition >= 2024.
(removed, mut_preserve_binding_mode_2024, "1.80.0", Some(123076), Some("superseded by `ref_pat_eat_one_layer_2024`"), 125168),
/// 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),
(removed, needs_allocator, "1.4.0", Some(27389),
Some("subsumed by `#![feature(allocator_internals)]`")),
/// Allows use of unary negate on unsigned integers, e.g., -e for e: u8
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]`.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
318 changes: 73 additions & 245 deletions compiler/rustc_hir_typeck/src/fallback.rs

Large diffs are not rendered by default.

14 changes: 5 additions & 9 deletions compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 used for diagnostics.
pub(super) never_type_fallback_has_occurred: Cell<bool>,

pub(super) diverging_fallback_behavior: DivergingFallbackBehavior,
pub(super) diverging_block_behavior: DivergingBlockBehavior,
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
}
Expand All @@ -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),
_ => {
Expand Down
5 changes: 0 additions & 5 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_trait_selection/src/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 never_type_fallback_has_occurred: bool,

pub normalize_fn_sig: Box<dyn Fn(ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx> + 'a>,

Expand All @@ -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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -539,13 +539,14 @@ 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)
});
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 \
Expand Down
3 changes: 2 additions & 1 deletion tests/ui/binding/empty-types-in-patterns.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//@ run-pass
//@ edition: 2024

#![feature(never_type, never_type_fallback)]
#![feature(never_type)]
#![feature(exhaustive_patterns)]

#![allow(unreachable_patterns)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
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 `()`
|
= 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 `()`
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/coercion/coerce-issue-49593-box-never.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/never_type/defaulted-never-note.fallback.stderr
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
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 `!`
| |
| 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)
= 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`
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/never_type/defaulted-never-note.nofallback.stderr
Original file line number Diff line number Diff line change
@@ -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);
| ^^
Expand Down
8 changes: 2 additions & 6 deletions tests/ui/never_type/defaulted-never-note.rs
Original file line number Diff line number Diff line change
@@ -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>;
Expand Down

This file was deleted.

102 changes: 0 additions & 102 deletions tests/ui/never_type/diverging-fallback-control-flow.rs

This file was deleted.

2 changes: 1 addition & 1 deletion tests/ui/never_type/diverging-fallback-no-leak.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/rust-lang/rust/issues/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: 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`.
Loading
Loading