Rollup merge of #72331 - oddg:forbid-cast-of-cenum-implementing-drop, r=matthewjasper,nikomatsakis
Report error when casting an C-like enum implementing Drop Following approach described in https://github.com/rust-lang/rust/issues/35941
This commit is contained in:
commit
9c54c65c9d
@ -534,6 +534,16 @@
|
||||
@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 @@
|
||||
ASM_SUB_REGISTER,
|
||||
UNSAFE_OP_IN_UNSAFE_FN,
|
||||
INCOMPLETE_INCLUDE,
|
||||
CENUM_IMPL_DROP_CAST,
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -678,7 +678,10 @@ fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<CastKind, CastError> {
|
||||
(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),
|
||||
@ -775,11 +778,13 @@ fn check_ref_cast(
|
||||
// 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);
|
||||
@ -809,6 +814,25 @@ fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<(), ty::error::Typ
|
||||
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> {
|
||||
|
18
src/test/ui/cenum_impl_drop_cast.rs
Normal file
18
src/test/ui/cenum_impl_drop_cast.rs
Normal file
@ -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
src/test/ui/cenum_impl_drop_cast.stderr
Normal file
16
src/test/ui/cenum_impl_drop_cast.stderr
Normal file
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user