Skip to content

Commit e24fc9a

Browse files
committed
Fix missing_const_for_fn not checking ~const Destruct
1 parent 4886937 commit e24fc9a

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

clippy_utils/src/qualify_min_const_fn.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,14 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
5252
}
5353

5454
for local in &body.local_decls {
55-
check_ty(tcx, local.ty, local.source_info.span)?;
55+
check_ty(tcx, local.ty, local.source_info.span, false)?;
5656
}
5757
// impl trait is gone in MIR, so check the return type manually
5858
check_ty(
5959
tcx,
6060
tcx.fn_sig(def_id).subst_identity().output().skip_binder(),
6161
body.local_decls.iter().next().unwrap().source_info.span,
62+
false,
6263
)?;
6364

6465
for bb in body.basic_blocks.iter() {
@@ -70,7 +71,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
7071
Ok(())
7172
}
7273

73-
fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
74+
fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, in_drop: bool) -> McfResult {
7475
for arg in ty.walk() {
7576
let ty = match arg.unpack() {
7677
GenericArgKind::Type(ty) => ty,
@@ -80,6 +81,27 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
8081
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => continue,
8182
};
8283

84+
// Only do this check if we're in `TerminatorKind::Drop`, otherwise rustc will sometimes overflow
85+
// its stack. This check is unnecessary outside of a `Drop` anyway so it's faster regardless
86+
if in_drop && let ty::Adt(def, subst) = ty.kind() {
87+
if def.has_non_const_dtor(tcx) && in_drop {
88+
return Err((
89+
span,
90+
"cannot drop locals with a non constant destructor in const fn".into(),
91+
));
92+
}
93+
94+
for fields in def.variants().iter().map(|v| &v.fields) {
95+
for field in fields {
96+
check_ty(tcx, field.ty(tcx, subst), span, in_drop)?;
97+
}
98+
}
99+
100+
for field in def.all_fields() {
101+
check_ty(tcx, field.ty(tcx, subst), span, in_drop)?;
102+
}
103+
}
104+
83105
match ty.kind() {
84106
ty::Ref(_, _, hir::Mutability::Mut) => {
85107
return Err((span, "mutable references in const fn are unstable".into()));
@@ -306,7 +328,12 @@ fn check_terminator<'tcx>(
306328
| TerminatorKind::Terminate
307329
| TerminatorKind::Unreachable => Ok(()),
308330

309-
TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body),
331+
TerminatorKind::Drop { place, .. } => {
332+
for local in &body.local_decls {
333+
check_ty(tcx, local.ty, span, true)?;
334+
}
335+
check_place(tcx, *place, span, body)
336+
},
310337

311338
TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body),
312339

tests/ui/missing_const_for_fn/cant_be_const.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,12 @@ with_span! {
126126
span
127127
fn dont_check_in_proc_macro() {}
128128
}
129+
130+
fn a(this: String) {}
131+
132+
enum A {
133+
F(String),
134+
N,
135+
}
136+
137+
fn b(this: A) {}

0 commit comments

Comments
 (0)