From d5ea0e9f8def9a3ec0eb2dd88f0465d4d1a81c21 Mon Sep 17 00:00:00 2001 From: oddg Date: Thu, 14 May 2020 19:58:43 -0700 Subject: [PATCH 1/4] Report error when casting an C-like enum implementing Drop --- src/librustc_session/lint/builtin.rs | 11 ++++++++++ src/librustc_typeck/check/cast.rs | 30 +++++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs index 58388bafbeddf..5a8f5c1b9fbca 100644 --- a/src/librustc_session/lint/builtin.rs +++ b/src/librustc_session/lint/builtin.rs @@ -534,6 +534,16 @@ declare_lint! { @feature_gate = sym::unsafe_block_in_unsafe_fn; } +declare_lint! { + pub CENUM_IMPL_DROP_CAST, + Warn, + "a C-like enum implementing Drop is cast", + @future_incompatible = FutureIncompatibleInfo { + reference: "issue #73333 ", + edition: None, + }; +} + declare_lint_pass! { /// Does nothing as a lint pass, but registers some `Lint`s /// that are used by other parts of the compiler. @@ -607,6 +617,7 @@ declare_lint_pass! { ASM_SUB_REGISTER, UNSAFE_OP_IN_UNSAFE_FN, INCOMPLETE_INCLUDE, + CENUM_IMPL_DROP_CAST, ] } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 46d6706cbf429..bea5e0e996658 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -609,7 +609,10 @@ impl<'a, 'tcx> CastCheck<'tcx> { (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt), // prim -> prim - (Int(CEnum), Int(_)) => Ok(CastKind::EnumCast), + (Int(CEnum), Int(_)) => { + self.cenum_impl_drop_lint(fcx); + Ok(CastKind::EnumCast) + } (Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast), (Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast), @@ -706,11 +709,13 @@ impl<'a, 'tcx> CastCheck<'tcx> { // Coerce to a raw pointer so that we generate AddressOf in MIR. let array_ptr_type = fcx.tcx.mk_ptr(m_expr); fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No) - .unwrap_or_else(|_| bug!( + .unwrap_or_else(|_| { + bug!( "could not cast from reference to array to pointer to array ({:?} to {:?})", self.expr_ty, array_ptr_type, - )); + ) + }); // this will report a type mismatch if needed fcx.demand_eqtype(self.span, ety, m_cast.ty); @@ -740,6 +745,25 @@ impl<'a, 'tcx> CastCheck<'tcx> { Err(err) => Err(err), } } + + fn cenum_impl_drop_lint(&self, fcx: &FnCtxt<'a, 'tcx>) { + if let ty::Adt(d, _) = self.expr_ty.kind { + if d.has_dtor(fcx.tcx) { + fcx.tcx.struct_span_lint_hir( + lint::builtin::CENUM_IMPL_DROP_CAST, + self.expr.hir_id, + self.span, + |err| { + err.build(&format!( + "Cast `enum` implementing `Drop` `{}` to integer `{}`", + self.expr_ty, self.cast_ty + )) + .emit(); + }, + ); + } + } + } } impl<'a, 'tcx> FnCtxt<'a, 'tcx> { From a40156e5b7053dcc36ba1ad65fb567b183c4e1fb Mon Sep 17 00:00:00 2001 From: oddg Date: Sun, 14 Jun 2020 15:49:20 -0700 Subject: [PATCH 2/4] UI test for deprecation warning of casting enum implementing Drop --- src/test/ui/cenum_impl_drop_cast.rs | 18 ++++++++++++++++++ src/test/ui/cenum_impl_drop_cast.stderr | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/test/ui/cenum_impl_drop_cast.rs create mode 100644 src/test/ui/cenum_impl_drop_cast.stderr diff --git a/src/test/ui/cenum_impl_drop_cast.rs b/src/test/ui/cenum_impl_drop_cast.rs new file mode 100644 index 0000000000000..623460673bfa2 --- /dev/null +++ b/src/test/ui/cenum_impl_drop_cast.rs @@ -0,0 +1,18 @@ +#![deny(cenum_impl_drop_cast)] + +enum E { + A = 0, +} + +impl Drop for E { + fn drop(&mut self) { + println!("Drop"); + } +} + +fn main() { + let e = E::A; + let i = e as u32; + //~^ ERROR Cast `enum` implementing `Drop` `E` to integer `u32` + //~| WARN this was previously accepted +} diff --git a/src/test/ui/cenum_impl_drop_cast.stderr b/src/test/ui/cenum_impl_drop_cast.stderr new file mode 100644 index 0000000000000..5c8f86ffd72ad --- /dev/null +++ b/src/test/ui/cenum_impl_drop_cast.stderr @@ -0,0 +1,16 @@ +error: Cast `enum` implementing `Drop` `E` to integer `u32` + --> $DIR/cenum_impl_drop_cast.rs:15:13 + | +LL | let i = e as u32; + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/cenum_impl_drop_cast.rs:1:9 + | +LL | #![deny(cenum_impl_drop_cast)] + | ^^^^^^^^^^^^^^^^^^^^ + = 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 + +error: aborting due to previous error + From b5809b027262cb9404519862ccbe06a13cae408b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 15 Jun 2020 12:12:22 -0400 Subject: [PATCH 3/4] Update src/librustc_typeck/check/cast.rs Co-authored-by: lzutao --- src/librustc_typeck/check/cast.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index bea5e0e996658..fa10851abd4f6 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -755,7 +755,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.span, |err| { err.build(&format!( - "Cast `enum` implementing `Drop` `{}` to integer `{}`", + "cannot cast enum `{}` into integer `{}` because it implements `Drop`", self.expr_ty, self.cast_ty )) .emit(); From f3dfe80ee1d13ec923082487e73c6d5d5833eef0 Mon Sep 17 00:00:00 2001 From: oddg Date: Mon, 15 Jun 2020 21:28:50 -0700 Subject: [PATCH 4/4] Adjust error message --- src/test/ui/cenum_impl_drop_cast.rs | 2 +- src/test/ui/cenum_impl_drop_cast.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/cenum_impl_drop_cast.rs b/src/test/ui/cenum_impl_drop_cast.rs index 623460673bfa2..96e3d967e2c61 100644 --- a/src/test/ui/cenum_impl_drop_cast.rs +++ b/src/test/ui/cenum_impl_drop_cast.rs @@ -13,6 +13,6 @@ impl Drop for E { fn main() { let e = E::A; let i = e as u32; - //~^ ERROR Cast `enum` implementing `Drop` `E` to integer `u32` + //~^ ERROR cannot cast enum `E` into integer `u32` because it implements `Drop` //~| WARN this was previously accepted } diff --git a/src/test/ui/cenum_impl_drop_cast.stderr b/src/test/ui/cenum_impl_drop_cast.stderr index 5c8f86ffd72ad..8d847a0c80b16 100644 --- a/src/test/ui/cenum_impl_drop_cast.stderr +++ b/src/test/ui/cenum_impl_drop_cast.stderr @@ -1,4 +1,4 @@ -error: Cast `enum` implementing `Drop` `E` to integer `u32` +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;