@@ -567,8 +567,11 @@ SILCombiner::optimizeConcatenationOfStringLiterals(ApplyInst *AI) {
567
567
// / initialized. This is either a init_existential_addr or the source of a
568
568
// / copy_addr. Returns a null value if the address does not dominate the
569
569
// / alloc_stack user \p ASIUser.
570
+ // / If the value is copied from another stack location, \p isCopied is set to
571
+ // / true.
570
572
static SILValue getAddressOfStackInit (AllocStackInst *ASI,
571
- SILInstruction *ASIUser) {
573
+ SILInstruction *ASIUser,
574
+ bool &isCopied) {
572
575
SILInstruction *SingleWrite = nullptr ;
573
576
// Check that this alloc_stack is initialized only once.
574
577
for (auto Use : ASI->getUses ()) {
@@ -588,6 +591,7 @@ static SILValue getAddressOfStackInit(AllocStackInst *ASI,
588
591
if (SingleWrite)
589
592
return SILValue ();
590
593
SingleWrite = CAI;
594
+ isCopied = true ;
591
595
}
592
596
continue ;
593
597
}
@@ -621,23 +625,29 @@ static SILValue getAddressOfStackInit(AllocStackInst *ASI,
621
625
if (auto *CAI = dyn_cast<CopyAddrInst>(SingleWrite)) {
622
626
// Try to derive the type from the copy_addr that was used to
623
627
// initialize the alloc_stack.
628
+ assert (isCopied && " isCopied not set for a copy_addr" );
624
629
SILValue CAISrc = CAI->getSrc ();
625
630
if (auto *ASI = dyn_cast<AllocStackInst>(CAISrc))
626
- return getAddressOfStackInit (ASI, CAI);
631
+ return getAddressOfStackInit (ASI, CAI, isCopied );
627
632
return CAISrc;
628
633
}
629
634
return SingleWrite;
630
635
}
631
636
632
637
// / Find the init_existential, which could be used to determine a concrete
633
638
// / type of the \p Self.
639
+ // / If the value is copied from another stack location, \p isCopied is set to
640
+ // / true.
634
641
static SILInstruction *findInitExistential (FullApplySite AI, SILValue Self,
635
642
ArchetypeType *&OpenedArchetype,
636
- SILValue &OpenedArchetypeDef) {
643
+ SILValue &OpenedArchetypeDef,
644
+ bool &isCopied) {
645
+ isCopied = false ;
637
646
if (auto *Instance = dyn_cast<AllocStackInst>(Self)) {
638
647
// In case the Self operand is an alloc_stack where a copy_addr copies the
639
648
// result of an open_existential_addr to this stack location.
640
- if (SILValue Src = getAddressOfStackInit (Instance, AI.getInstruction ()))
649
+ if (SILValue Src = getAddressOfStackInit (Instance, AI.getInstruction (),
650
+ isCopied))
641
651
Self = Src;
642
652
}
643
653
@@ -647,7 +657,7 @@ static SILInstruction *findInitExistential(FullApplySite AI, SILValue Self,
647
657
if (!ASI)
648
658
return nullptr ;
649
659
650
- SILValue StackWrite = getAddressOfStackInit (ASI, Open);
660
+ SILValue StackWrite = getAddressOfStackInit (ASI, Open, isCopied );
651
661
if (!StackWrite)
652
662
return nullptr ;
653
663
@@ -853,8 +863,10 @@ SILCombiner::propagateConcreteTypeOfInitExistential(FullApplySite AI,
853
863
// determine a concrete type of the self.
854
864
ArchetypeType *OpenedArchetype = nullptr ;
855
865
SILValue OpenedArchetypeDef;
866
+ bool isCopied = false ;
856
867
SILInstruction *InitExistential =
857
- findInitExistential (AI, Self, OpenedArchetype, OpenedArchetypeDef);
868
+ findInitExistential (AI, Self, OpenedArchetype, OpenedArchetypeDef,
869
+ isCopied);
858
870
if (!InitExistential)
859
871
return nullptr ;
860
872
@@ -888,6 +900,18 @@ SILCombiner::propagateConcreteTypeOfInitExistential(FullApplySite AI,
888
900
// Propagate the concrete type into the callee-operand if required.
889
901
Propagate (ConcreteType, Conformance);
890
902
903
+ if (isCopied) {
904
+ // If the witness method is mutating self, we cannot replace self with
905
+ // the source of a copy. Otherwise the call would modify another value than
906
+ // the original self.
907
+ switch (AI.getArgumentConvention (AI.getNumArguments () - 1 )) {
908
+ case SILArgumentConvention::ConventionType::Indirect_Inout:
909
+ case SILArgumentConvention::ConventionType::Indirect_InoutAliasable:
910
+ return nullptr ;
911
+ default :
912
+ break ;
913
+ }
914
+ }
891
915
// Create a new apply instruction that uses the concrete type instead
892
916
// of the existential type.
893
917
auto *NewAI = createApplyWithConcreteType (AI, NewSelf, Self, ConcreteType,
0 commit comments