@@ -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
0 commit comments