Skip to content

Commit

Permalink
Rollup merge of #72331 - oddg:forbid-cast-of-cenum-implementing-drop,…
Browse files Browse the repository at this point in the history
… r=matthewjasper,nikomatsakis

Report error when casting an C-like enum implementing Drop

Following approach described in #35941
  • Loading branch information
RalfJung authored Jun 19, 2020
2 parents 27d4737 + f3dfe80 commit 9c54c65
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 3 deletions.
11 changes: 11 additions & 0 deletions src/librustc_session/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -607,6 +617,7 @@ declare_lint_pass! {
ASM_SUB_REGISTER,
UNSAFE_OP_IN_UNSAFE_FN,
INCOMPLETE_INCLUDE,
CENUM_IMPL_DROP_CAST,
]
}

Expand Down
30 changes: 27 additions & 3 deletions src/librustc_typeck/check/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,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),
Expand Down Expand Up @@ -775,11 +778,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);
Expand Down Expand Up @@ -809,6 +814,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!(
"cannot cast enum `{}` into integer `{}` because it implements `Drop`",
self.expr_ty, self.cast_ty
))
.emit();
},
);
}
}
}
}

impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Expand Down
18 changes: 18 additions & 0 deletions src/test/ui/cenum_impl_drop_cast.rs
Original file line number Diff line number Diff line change
@@ -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 cannot cast enum `E` into integer `u32` because it implements `Drop`
//~| WARN this was previously accepted
}
16 changes: 16 additions & 0 deletions src/test/ui/cenum_impl_drop_cast.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
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;
| ^^^^^^^^
|
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 <https://github.com/rust-lang/rust/issues/73333>

error: aborting due to previous error

0 comments on commit 9c54c65

Please sign in to comment.