Rollup merge of #135964 - ehuss:cenum_impl_drop_cast, r=Nadrieril
Make cenum_impl_drop_cast a hard error This changes the `cenum_impl_drop_cast` lint to be a hard error. This lint has been deny-by-default and warning in dependencies since https://github.com/rust-lang/rust/pull/97652 about 2.5 years ago. Closes https://github.com/rust-lang/rust/issues/73333
This commit is contained in:
commit
def44600d1
8 changed files with 12 additions and 181 deletions
|
@ -831,7 +831,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
|
|
||||||
// prim -> prim
|
// prim -> prim
|
||||||
(Int(CEnum), Int(_)) => {
|
(Int(CEnum), Int(_)) => {
|
||||||
self.cenum_impl_drop_lint(fcx);
|
self.err_if_cenum_impl_drop(fcx);
|
||||||
Ok(CastKind::EnumCast)
|
Ok(CastKind::EnumCast)
|
||||||
}
|
}
|
||||||
(Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
|
(Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
|
||||||
|
@ -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()
|
if let ty::Adt(d, _) = self.expr_ty.kind()
|
||||||
&& d.has_dtor(fcx.tcx)
|
&& d.has_dtor(fcx.tcx)
|
||||||
{
|
{
|
||||||
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
|
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
|
||||||
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
||||||
|
|
||||||
fcx.tcx.emit_node_span_lint(
|
fcx.dcx().emit_err(errors::CastEnumDrop { span: self.span, expr_ty, cast_ty });
|
||||||
lint::builtin::CENUM_IMPL_DROP_CAST,
|
|
||||||
self.expr.hir_id,
|
|
||||||
self.span,
|
|
||||||
errors::CastEnumDrop { expr_ty, cast_ty },
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -677,9 +677,11 @@ pub(crate) struct CannotCastToBool<'tcx> {
|
||||||
pub help: CannotCastToBoolHelp,
|
pub help: CannotCastToBoolHelp,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(LintDiagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(hir_typeck_cast_enum_drop)]
|
#[diag(hir_typeck_cast_enum_drop)]
|
||||||
pub(crate) struct CastEnumDrop<'tcx> {
|
pub(crate) struct CastEnumDrop<'tcx> {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
pub expr_ty: Ty<'tcx>,
|
pub expr_ty: Ty<'tcx>,
|
||||||
pub cast_ty: Ty<'tcx>,
|
pub cast_ty: Ty<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -595,6 +595,11 @@ fn register_builtins(store: &mut LintStore) {
|
||||||
<https://github.com/rust-lang/rust/pull/125380> for more information",
|
<https://github.com/rust-lang/rust/pull/125380> for more information",
|
||||||
);
|
);
|
||||||
store.register_removed("unsupported_calling_conventions", "converted into hard error");
|
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) {
|
fn register_internals(store: &mut LintStore) {
|
||||||
|
|
|
@ -27,7 +27,6 @@ declare_lint_pass! {
|
||||||
BARE_TRAIT_OBJECTS,
|
BARE_TRAIT_OBJECTS,
|
||||||
BINDINGS_WITH_VARIANT_NAME,
|
BINDINGS_WITH_VARIANT_NAME,
|
||||||
BREAK_WITH_LABEL_AND_LOOP,
|
BREAK_WITH_LABEL_AND_LOOP,
|
||||||
CENUM_IMPL_DROP_CAST,
|
|
||||||
COHERENCE_LEAK_CHECK,
|
COHERENCE_LEAK_CHECK,
|
||||||
CONFLICTING_REPR_HINTS,
|
CONFLICTING_REPR_HINTS,
|
||||||
CONST_EVALUATABLE_UNCHECKED,
|
CONST_EVALUATABLE_UNCHECKED,
|
||||||
|
@ -2612,58 +2611,6 @@ declare_lint! {
|
||||||
@edition Edition2024 => Warn;
|
@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! {
|
declare_lint! {
|
||||||
/// The `fuzzy_provenance_casts` lint detects an `as` cast between an integer
|
/// The `fuzzy_provenance_casts` lint detects an `as` cast between an integer
|
||||||
/// and a pointer.
|
/// and a pointer.
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
// MIR for `droppy` after built
|
|
||||||
|
|
||||||
fn droppy() -> () {
|
|
||||||
let mut _0: ();
|
|
||||||
let _1: ();
|
|
||||||
let _2: Droppy;
|
|
||||||
let _4: Droppy;
|
|
||||||
let mut _5: isize;
|
|
||||||
let mut _6: u8;
|
|
||||||
let mut _7: bool;
|
|
||||||
let _8: Droppy;
|
|
||||||
scope 1 {
|
|
||||||
debug x => _2;
|
|
||||||
scope 2 {
|
|
||||||
debug y => _3;
|
|
||||||
}
|
|
||||||
scope 3 {
|
|
||||||
let _3: usize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scope 4 {
|
|
||||||
debug z => _8;
|
|
||||||
}
|
|
||||||
|
|
||||||
bb0: {
|
|
||||||
StorageLive(_1);
|
|
||||||
StorageLive(_2);
|
|
||||||
_2 = Droppy::C;
|
|
||||||
FakeRead(ForLet(None), _2);
|
|
||||||
StorageLive(_3);
|
|
||||||
StorageLive(_4);
|
|
||||||
_4 = move _2;
|
|
||||||
_5 = discriminant(_4);
|
|
||||||
_6 = copy _5 as u8 (IntToInt);
|
|
||||||
_7 = Le(copy _6, const 2_u8);
|
|
||||||
assume(move _7);
|
|
||||||
_3 = move _5 as usize (IntToInt);
|
|
||||||
drop(_4) -> [return: bb1, unwind: bb4];
|
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageDead(_4);
|
|
||||||
FakeRead(ForLet(None), _3);
|
|
||||||
_1 = const ();
|
|
||||||
StorageDead(_3);
|
|
||||||
drop(_2) -> [return: bb2, unwind: bb5];
|
|
||||||
}
|
|
||||||
|
|
||||||
bb2: {
|
|
||||||
StorageDead(_2);
|
|
||||||
StorageDead(_1);
|
|
||||||
StorageLive(_8);
|
|
||||||
_8 = Droppy::B;
|
|
||||||
FakeRead(ForLet(None), _8);
|
|
||||||
_0 = const ();
|
|
||||||
drop(_8) -> [return: bb3, unwind: bb5];
|
|
||||||
}
|
|
||||||
|
|
||||||
bb3: {
|
|
||||||
StorageDead(_8);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bb4 (cleanup): {
|
|
||||||
drop(_2) -> [return: bb5, unwind terminate(cleanup)];
|
|
||||||
}
|
|
||||||
|
|
||||||
bb5 (cleanup): {
|
|
||||||
resume;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -41,27 +41,6 @@ fn far(far: Far) -> isize {
|
||||||
far as 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)]
|
#[repr(i16)]
|
||||||
enum SignedAroundZero {
|
enum SignedAroundZero {
|
||||||
A = -2,
|
A = -2,
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#![deny(cenum_impl_drop_cast)]
|
|
||||||
|
|
||||||
enum E {
|
enum E {
|
||||||
A = 0,
|
A = 0,
|
||||||
}
|
}
|
||||||
|
@ -14,5 +12,4 @@ fn main() {
|
||||||
let e = E::A;
|
let e = E::A;
|
||||||
let i = e as u32;
|
let i = e as u32;
|
||||||
//~^ ERROR cannot cast enum `E` into integer `u32` because it implements `Drop`
|
//~^ ERROR cannot cast enum `E` into integer `u32` because it implements `Drop`
|
||||||
//~| WARN this was previously accepted
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,8 @@
|
||||||
error: cannot cast enum `E` into integer `u32` because it implements `Drop`
|
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;
|
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
|
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…
Add table
Add a link
Reference in a new issue