@@ -52,13 +52,14 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv)
52
52
}
53
53
54
54
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 ) ?;
56
56
}
57
57
// impl trait is gone in MIR, so check the return type manually
58
58
check_ty (
59
59
tcx,
60
60
tcx. fn_sig ( def_id) . subst_identity ( ) . output ( ) . skip_binder ( ) ,
61
61
body. local_decls . iter ( ) . next ( ) . unwrap ( ) . source_info . span ,
62
+ false ,
62
63
) ?;
63
64
64
65
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)
70
71
Ok ( ( ) )
71
72
}
72
73
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 {
74
75
for arg in ty. walk ( ) {
75
76
let ty = match arg. unpack ( ) {
76
77
GenericArgKind :: Type ( ty) => ty,
@@ -80,6 +81,27 @@ fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
80
81
GenericArgKind :: Lifetime ( _) | GenericArgKind :: Const ( _) => continue ,
81
82
} ;
82
83
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
+
83
105
match ty. kind ( ) {
84
106
ty:: Ref ( _, _, hir:: Mutability :: Mut ) => {
85
107
return Err ( ( span, "mutable references in const fn are unstable" . into ( ) ) ) ;
@@ -306,7 +328,12 @@ fn check_terminator<'tcx>(
306
328
| TerminatorKind :: Terminate
307
329
| TerminatorKind :: Unreachable => Ok ( ( ) ) ,
308
330
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
+ } ,
310
337
311
338
TerminatorKind :: SwitchInt { discr, targets : _ } => check_operand ( tcx, discr, span, body) ,
312
339
0 commit comments