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
4 changed files with 72 additions and 3 deletions
|
@ -534,6 +534,16 @@ declare_lint! {
|
||||||
@feature_gate = sym::unsafe_block_in_unsafe_fn;
|
@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! {
|
declare_lint_pass! {
|
||||||
/// Does nothing as a lint pass, but registers some `Lint`s
|
/// Does nothing as a lint pass, but registers some `Lint`s
|
||||||
/// that are used by other parts of the compiler.
|
/// that are used by other parts of the compiler.
|
||||||
|
@ -607,6 +617,7 @@ declare_lint_pass! {
|
||||||
ASM_SUB_REGISTER,
|
ASM_SUB_REGISTER,
|
||||||
UNSAFE_OP_IN_UNSAFE_FN,
|
UNSAFE_OP_IN_UNSAFE_FN,
|
||||||
INCOMPLETE_INCLUDE,
|
INCOMPLETE_INCLUDE,
|
||||||
|
CENUM_IMPL_DROP_CAST,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -678,7 +678,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
(FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
|
(FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt),
|
||||||
|
|
||||||
// prim -> prim
|
// 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(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
|
||||||
|
|
||||||
(Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
|
(Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
|
||||||
|
@ -775,11 +778,13 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
// Coerce to a raw pointer so that we generate AddressOf in MIR.
|
// Coerce to a raw pointer so that we generate AddressOf in MIR.
|
||||||
let array_ptr_type = fcx.tcx.mk_ptr(m_expr);
|
let array_ptr_type = fcx.tcx.mk_ptr(m_expr);
|
||||||
fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No)
|
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 {:?})",
|
"could not cast from reference to array to pointer to array ({:?} to {:?})",
|
||||||
self.expr_ty,
|
self.expr_ty,
|
||||||
array_ptr_type,
|
array_ptr_type,
|
||||||
));
|
)
|
||||||
|
});
|
||||||
|
|
||||||
// this will report a type mismatch if needed
|
// this will report a type mismatch if needed
|
||||||
fcx.demand_eqtype(self.span, ety, m_cast.ty);
|
fcx.demand_eqtype(self.span, ety, m_cast.ty);
|
||||||
|
@ -809,6 +814,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
Err(err) => Err(err),
|
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> {
|
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…
Add table
Add a link
Reference in a new issue