@@ -3556,6 +3556,13 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
35563556 " destructure with none ownership kind operand and non-none "
35573557 " ownership kind result?!" );
35583558 }
3559+ if (operandTy.getNominalOrBoundGenericNominal ()
3560+ ->getValueTypeDestructor ()) {
3561+ require (
3562+ isa<DropDeinitInst>(lookThroughOwnershipInsts (DSI->getOperand ())),
3563+ " a destructure of a move-only-type-with-deinit requires a "
3564+ " drop_deinit" );
3565+ }
35593566 }
35603567 }
35613568
@@ -5978,12 +5985,40 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
59785985 " Result and operand must have the same type, today." );
59795986 }
59805987
5988+ // check that a drop_deinit can only ever be destroyed or destructured
5989+ void checkDropDeinitUses (DropDeinitInst *ddi) {
5990+ // Address-type drop_deinit has no special structural requirements. It just
5991+ // sits there and blocks optimization on the allocation and downstream uses
5992+ // of the address. If we want to optimize around address-type drop_deinit,
5993+ // then we need a seperate verifier for its requirements.
5994+ if (ddi->getType ().isAddress ())
5995+ return ;
5996+
5997+ visitNonOwnershipUses (ddi, [&](Operand *use) {
5998+ auto *user = use->getUser ();
5999+ require (isa<DestroyValueInst>(user)
6000+ || isa<EndLifetimeInst>(user)
6001+ || isa<DestructureStructInst>(user)
6002+ || isa<SwitchEnumInst>(user),
6003+ " A drop_deinit can only be destroyed or destructured" );
6004+ return true ;
6005+ });
6006+ }
6007+
59816008 void checkDropDeinitInst (DropDeinitInst *ddi) {
5982- require (ddi->getType () == ddi->getOperand ()->getType (),
6009+ require (F.hasOwnership (), " drop_deinit only allowed in OSSA" );
6010+
6011+ auto type = ddi->getType ();
6012+ require (type == ddi->getOperand ()->getType (),
59836013 " Result and operand must have the same type." );
5984- require (ddi-> getType () .isMoveOnlyNominalType (),
6014+ require (type .isMoveOnlyNominalType (),
59856015 " drop_deinit only allowed for move-only types" );
5986- require (F.hasOwnership (), " drop_deinit only allowed in OSSA" );
6016+ require (type.getNominalOrBoundGenericNominal ()
6017+ ->getValueTypeDestructor (), " drop_deinit only allowed for "
6018+ " struct/enum types that define a deinit" );
6019+ assert (!type.isTrivial (F) && " a type with a deinit is nontrivial" );
6020+
6021+ checkDropDeinitUses (ddi);
59876022 }
59886023
59896024 void checkMarkMustCheckInst (MarkMustCheckInst *i) {
0 commit comments