Skip to content
Merged
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
26 changes: 26 additions & 0 deletions compiler/rustc_incremental/src/persist/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,11 +721,37 @@ pub(crate) fn garbage_collect_session_directories(sess: &Session) -> io::Result<
}
}

let current_session_directory_name =
session_directory.file_name().expect("session directory is not `..`");

// Now garbage collect the valid session directories.
let deletion_candidates =
lock_file_to_session_dir.items().filter_map(|(lock_file_name, directory_name)| {
debug!("garbage_collect_session_directories() - inspecting: {}", directory_name);

if directory_name.as_str() == current_session_directory_name {
// Skipping our own directory is, unfortunately, important for correctness.
//
// To summarize #147821: we will try to lock directories before deciding they can be
// garbage collected, but the ability of `flock::Lock` to detect a lock held *by the
// same process* varies across file locking APIs. Then, if our own session directory
// has become old enough to be eligible for GC, we are beholden to platform-specific
// details about detecting the our own lock on the session directory.
//
// POSIX `fcntl(F_SETLK)`-style file locks are maintained across a process. On
// systems where this is the mechanism for `flock::Lock`, there is no way to
// discover if an `flock::Lock` has been created in the same process on the same
// file. Attempting to set a lock on the lockfile again will succeed, even if the
// lock was set by another thread, on another file descriptor. Then we would
// garbage collect our own live directory, unable to tell it was locked perhaps by
// this same thread.
//
// It's not clear that `flock::Lock` can be fixed for this in general, and our own
// incremental session directory is the only one which this process may own, so skip
// it here and avoid the problem. We know it's not garbage anyway: we're using it.
return None;
}

let Ok(timestamp) = extract_timestamp_from_session_dir(directory_name) else {
debug!(
"found session-dir with malformed timestamp: {}",
Expand Down
30 changes: 23 additions & 7 deletions compiler/rustc_lint/src/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,13 +273,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
expr: &hir::Expr<'_>,
span: Span,
) -> Option<MustUsePath> {
if ty.is_unit()
|| !ty.is_inhabited_from(
cx.tcx,
cx.tcx.parent_module(expr.hir_id).to_def_id(),
cx.typing_env(),
)
{
if ty.is_unit() {
return Some(MustUsePath::Suppressed);
}
let parent_mod_did = cx.tcx.parent_module(expr.hir_id).to_def_id();
let is_uninhabited =
|t: Ty<'tcx>| !t.is_inhabited_from(cx.tcx, parent_mod_did, cx.typing_env());
if is_uninhabited(ty) {
return Some(MustUsePath::Suppressed);
}

Expand All @@ -293,6 +293,22 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
is_ty_must_use(cx, pinned_ty, expr, span)
.map(|inner| MustUsePath::Pinned(Box::new(inner)))
}
// Suppress warnings on `Result<(), Uninhabited>` (e.g. `Result<(), !>`).
ty::Adt(def, args)
if cx.tcx.is_diagnostic_item(sym::Result, def.did())
&& args.type_at(0).is_unit()
&& is_uninhabited(args.type_at(1)) =>
{
Some(MustUsePath::Suppressed)
}
// Suppress warnings on `ControlFlow<Uninhabited, ()>` (e.g. `ControlFlow<!, ()>`).
ty::Adt(def, args)
if cx.tcx.is_diagnostic_item(sym::ControlFlow, def.did())
&& args.type_at(1).is_unit()
&& is_uninhabited(args.type_at(0)) =>
{
Some(MustUsePath::Suppressed)
}
ty::Adt(def, _) => is_def_must_use(cx, def.did(), span),
ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => {
elaborate(cx.tcx, cx.tcx.explicit_item_self_bounds(def).iter_identity_copied())
Expand Down
7 changes: 3 additions & 4 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4065,7 +4065,6 @@ declare_lint! {
/// ### Example
///
/// ```rust,compile_fail
/// #![deny(never_type_fallback_flowing_into_unsafe)]
/// fn main() {
/// if true {
/// // return has type `!` which, is some cases, causes never type fallback
Expand Down Expand Up @@ -4100,7 +4099,7 @@ declare_lint! {
/// [`!`]: https://doc.rust-lang.org/core/primitive.never.html
/// [`()`]: https://doc.rust-lang.org/core/primitive.unit.html
pub NEVER_TYPE_FALLBACK_FLOWING_INTO_UNSAFE,
Warn,
Deny,
"never type fallback affecting unsafe function calls",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::EditionAndFutureReleaseSemanticsChange(Edition::Edition2024),
Expand All @@ -4122,7 +4121,7 @@ declare_lint! {
/// ### Example
///
/// ```rust,compile_fail,edition2021
/// #![deny(dependency_on_unit_never_type_fallback)]
/// # #![deny(dependency_on_unit_never_type_fallback)]
/// fn main() {
/// if true {
/// // return has type `!` which, is some cases, causes never type fallback
Expand Down Expand Up @@ -4155,7 +4154,7 @@ declare_lint! {
///
/// See [Tracking Issue for making `!` fall back to `!`](https://github.com/rust-lang/rust/issues/123748).
pub DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK,
Warn,
Deny,
"never type fallback affecting unsafe function calls",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::EditionAndFutureReleaseError(Edition::Edition2024),
Expand Down
22 changes: 10 additions & 12 deletions tests/ui/editions/never-type-fallback-breaking.e2021.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
//@[e2021] edition: 2021
//@[e2024] edition: 2024
//
//@[e2021] run-pass
//@[e2021] run-rustfix
//@[e2024] check-fail

fn main() {
m();
Expand All @@ -16,8 +14,8 @@ fn main() {
}

fn m() {
//[e2021]~^ WARN this function depends on never type fallback being `()`
//[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
//[e2021]~^ error: this function depends on never type fallback being `()`
//[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
let x: () = match true {
true => Default::default(),
//[e2024]~^ error: the trait bound `!: Default` is not satisfied
Expand All @@ -28,8 +26,8 @@ fn m() {
}

fn q() -> Option<()> {
//[e2021]~^ WARN this function depends on never type fallback being `()`
//[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
//[e2021]~^ error: this function depends on never type fallback being `()`
//[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
fn deserialize<T: Default>() -> Option<T> {
Some(T::default())
}
Expand All @@ -45,8 +43,8 @@ fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result<T, ()> {
Err(())
}
fn meow() -> Result<(), ()> {
//[e2021]~^ WARN this function depends on never type fallback being `()`
//[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
//[e2021]~^ error: this function depends on never type fallback being `()`
//[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
help::<(), _>(1)?;
//[e2024]~^ error: the trait bound `(): From<!>` is not satisfied
Ok(())
Expand All @@ -57,8 +55,8 @@ pub fn takes_apit<T>(_y: impl Fn() -> T) -> Result<T, ()> {
}

pub fn fallback_return() -> Result<(), ()> {
//[e2021]~^ WARN this function depends on never type fallback being `()`
//[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
//[e2021]~^ error: this function depends on never type fallback being `()`
//[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
takes_apit::<()>(|| Default::default())?;
//[e2024]~^ error: the trait bound `!: Default` is not satisfied
Ok(())
Expand All @@ -71,8 +69,8 @@ fn mk<T>() -> Result<T, ()> {
fn takes_apit2(_x: impl Default) {}

fn fully_apit() -> Result<(), ()> {
//[e2021]~^ WARN this function depends on never type fallback being `()`
//[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
//[e2021]~^ error: this function depends on never type fallback being `()`
//[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
takes_apit2(mk::<()>()?);
//[e2024]~^ error: the trait bound `!: Default` is not satisfied
Ok(())
Expand Down
Loading
Loading