Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make cenum_impl_drop_cast a hard error #135964

Merged
merged 1 commit into from
Feb 6, 2025
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
11 changes: 3 additions & 8 deletions compiler/rustc_hir_typeck/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {

// prim -> prim
(Int(CEnum), Int(_)) => {
self.cenum_impl_drop_lint(fcx);
self.err_if_cenum_impl_drop(fcx);
Ok(CastKind::EnumCast)
}
(Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
Expand Down Expand Up @@ -1091,19 +1091,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
}
}

fn cenum_impl_drop_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
fn err_if_cenum_impl_drop(&self, fcx: &FnCtxt<'a, 'tcx>) {
if let ty::Adt(d, _) = self.expr_ty.kind()
&& d.has_dtor(fcx.tcx)
{
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);

fcx.tcx.emit_node_span_lint(
lint::builtin::CENUM_IMPL_DROP_CAST,
self.expr.hir_id,
self.span,
errors::CastEnumDrop { expr_ty, cast_ty },
);
fcx.dcx().emit_err(errors::CastEnumDrop { span: self.span, expr_ty, cast_ty });
}
}

Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_hir_typeck/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -677,9 +677,11 @@ pub(crate) struct CannotCastToBool<'tcx> {
pub help: CannotCastToBoolHelp,
}

#[derive(LintDiagnostic)]
#[derive(Diagnostic)]
#[diag(hir_typeck_cast_enum_drop)]
pub(crate) struct CastEnumDrop<'tcx> {
#[primary_span]
pub span: Span,
pub expr_ty: Ty<'tcx>,
pub cast_ty: Ty<'tcx>,
}
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,11 @@ fn register_builtins(store: &mut LintStore) {
<https://github.com/rust-lang/rust/pull/125380> for more information",
);
store.register_removed("unsupported_calling_conventions", "converted into hard error");
store.register_removed(
"cenum_impl_drop_cast",
"converted into hard error, \
see <https://github.com/rust-lang/rust/issues/73333> for more information",
);
}

fn register_internals(store: &mut LintStore) {
Expand Down
53 changes: 0 additions & 53 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ declare_lint_pass! {
BARE_TRAIT_OBJECTS,
BINDINGS_WITH_VARIANT_NAME,
BREAK_WITH_LABEL_AND_LOOP,
CENUM_IMPL_DROP_CAST,
COHERENCE_LEAK_CHECK,
CONFLICTING_REPR_HINTS,
CONST_EVALUATABLE_UNCHECKED,
Expand Down Expand Up @@ -2612,58 +2611,6 @@ declare_lint! {
@edition Edition2024 => Warn;
}

declare_lint! {
/// The `cenum_impl_drop_cast` lint detects an `as` cast of a field-less
/// `enum` that implements [`Drop`].
///
/// [`Drop`]: https://doc.rust-lang.org/std/ops/trait.Drop.html
///
/// ### Example
///
/// ```rust,compile_fail
/// # #![allow(unused)]
/// enum E {
/// A,
/// }
///
/// impl Drop for E {
/// fn drop(&mut self) {
/// println!("Drop");
/// }
/// }
///
/// fn main() {
/// let e = E::A;
/// let i = e as u32;
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Casting a field-less `enum` that does not implement [`Copy`] to an
/// integer moves the value without calling `drop`. This can result in
/// surprising behavior if it was expected that `drop` should be called.
/// Calling `drop` automatically would be inconsistent with other move
/// operations. Since neither behavior is clear or consistent, it was
/// decided that a cast of this nature will no longer be allowed.
///
/// This is a [future-incompatible] lint to transition this to a hard error
/// in the future. See [issue #73333] for more details.
///
/// [future-incompatible]: ../index.md#future-incompatible-lints
/// [issue #73333]: https://github.com/rust-lang/rust/issues/73333
/// [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html
pub CENUM_IMPL_DROP_CAST,
Deny,
"a C-like enum implementing Drop is cast",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
reference: "issue #73333 <https://github.com/rust-lang/rust/issues/73333>",
};
}

declare_lint! {
/// The `fuzzy_provenance_casts` lint detects an `as` cast between an integer
/// and a pointer.
Expand Down
71 changes: 0 additions & 71 deletions tests/mir-opt/building/enum_cast.droppy.built.after.mir

This file was deleted.

21 changes: 0 additions & 21 deletions tests/mir-opt/building/enum_cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,6 @@ fn far(far: Far) -> isize {
far as isize
}

// EMIT_MIR enum_cast.droppy.built.after.mir
enum Droppy {
A,
B,
C,
}

impl Drop for Droppy {
fn drop(&mut self) {}
}

fn droppy() {
{
let x = Droppy::C;
// remove this entire test once `cenum_impl_drop_cast` becomes a hard error
#[allow(cenum_impl_drop_cast)]
let y = x as usize;
}
let z = Droppy::B;
}

#[repr(i16)]
enum SignedAroundZero {
A = -2,
Expand Down
3 changes: 0 additions & 3 deletions tests/ui/cenum_impl_drop_cast.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![deny(cenum_impl_drop_cast)]

enum E {
A = 0,
}
Expand All @@ -14,5 +12,4 @@ fn main() {
let e = E::A;
let i = e as u32;
//~^ ERROR cannot cast enum `E` into integer `u32` because it implements `Drop`
//~| WARN this was previously accepted
}
25 changes: 1 addition & 24 deletions tests/ui/cenum_impl_drop_cast.stderr
Original file line number Diff line number Diff line change
@@ -1,31 +1,8 @@
error: cannot cast enum `E` into integer `u32` because it implements `Drop`
--> $DIR/cenum_impl_drop_cast.rs:15:13
--> $DIR/cenum_impl_drop_cast.rs:13:13
|
LL | let i = e as u32;
| ^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #73333 <https://github.com/rust-lang/rust/issues/73333>
note: the lint level is defined here
--> $DIR/cenum_impl_drop_cast.rs:1:9
|
LL | #![deny(cenum_impl_drop_cast)]
| ^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

Future incompatibility report: Future breakage diagnostic:
error: cannot cast enum `E` into integer `u32` because it implements `Drop`
--> $DIR/cenum_impl_drop_cast.rs:15:13
|
LL | let i = e as u32;
| ^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #73333 <https://github.com/rust-lang/rust/issues/73333>
note: the lint level is defined here
--> $DIR/cenum_impl_drop_cast.rs:1:9
|
LL | #![deny(cenum_impl_drop_cast)]
| ^^^^^^^^^^^^^^^^^^^^

Loading