about summary refs log tree commit diff
diff options
context:
space:
mode:
authoroddg <odegevigney@gmail.com>2020-05-14 19:58:43 -0700
committeroddg <odegevigney@gmail.com>2020-06-13 17:35:31 -0700
commitd5ea0e9f8def9a3ec0eb2dd88f0465d4d1a81c21 (patch)
tree5a45f946c1a71c435de04f6a7dcc0119271cc46b
parent1fb612bd15bb3ef098fd24c20d0727de573b4410 (diff)
downloadrust-d5ea0e9f8def9a3ec0eb2dd88f0465d4d1a81c21.tar.gz
rust-d5ea0e9f8def9a3ec0eb2dd88f0465d4d1a81c21.zip
Report error when casting an C-like enum implementing Drop
-rw-r--r--src/librustc_session/lint/builtin.rs11
-rw-r--r--src/librustc_typeck/check/cast.rs30
2 files changed, 38 insertions, 3 deletions
diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs
index 58388bafbed..5a8f5c1b9fb 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 <https://github.com/rust-lang/rust/issues/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 46d6706cbf4..bea5e0e9966 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> {