@@ -518,6 +518,7 @@ namespace {
518
518
519
519
520
520
void handleStoreUse (unsigned UseID);
521
+ void handleLoadUse (unsigned UseID);
521
522
void handleInOutUse (const DIMemoryUse &Use);
522
523
void handleEscapeUse (const DIMemoryUse &Use);
523
524
@@ -807,15 +808,16 @@ void LifetimeChecker::doIt() {
807
808
handleStoreUse (i);
808
809
break ;
809
810
810
- case DIUseKind::IndirectIn:
811
- case DIUseKind::Load: {
811
+ case DIUseKind::IndirectIn: {
812
812
bool IsSuperInitComplete, FailedSelfUse;
813
813
// If the value is not definitively initialized, emit an error.
814
814
if (!isInitializedAtUse (Use, &IsSuperInitComplete, &FailedSelfUse))
815
815
handleLoadUseFailure (Use, IsSuperInitComplete, FailedSelfUse);
816
816
break ;
817
817
}
818
-
818
+ case DIUseKind::Load:
819
+ handleLoadUse (i);
820
+ break ;
819
821
case DIUseKind::InOutUse:
820
822
handleInOutUse (Use);
821
823
break ;
@@ -855,6 +857,55 @@ void LifetimeChecker::doIt() {
855
857
handleConditionalDestroys (ControlVariable);
856
858
}
857
859
860
+ void LifetimeChecker::handleLoadUse (unsigned UseID) {
861
+ DIMemoryUse &Use = Uses[UseID];
862
+ SILInstruction *LoadInst = Use.Inst ;
863
+
864
+ bool IsSuperInitComplete, FailedSelfUse;
865
+ // If the value is not definitively initialized, emit an error.
866
+ if (!isInitializedAtUse (Use, &IsSuperInitComplete, &FailedSelfUse))
867
+ return handleLoadUseFailure (Use, IsSuperInitComplete, FailedSelfUse);
868
+
869
+ // If this is an OpenExistentialAddrInst in preparation for applying
870
+ // a witness method, analyze its use to make sure, that no mutation of
871
+ // lvalue let constants occurs.
872
+ auto * OEAI = dyn_cast<OpenExistentialAddrInst>(LoadInst);
873
+ if (OEAI != nullptr && TheMemory.isElementLetProperty (Use.FirstElement )) {
874
+ for (auto OEAUse : OEAI->getUses ()) {
875
+ auto * AI = dyn_cast<ApplyInst>(OEAUse->getUser ());
876
+
877
+ if (AI == nullptr )
878
+ // User is not an ApplyInst
879
+ continue ;
880
+
881
+ unsigned OperandNumber = OEAUse->getOperandNumber ();
882
+ if (OperandNumber < 1 || OperandNumber > AI->getNumCallArguments ())
883
+ // Not used as a call argument
884
+ continue ;
885
+
886
+ unsigned ArgumentNumber = OperandNumber - 1 ;
887
+
888
+ CanSILFunctionType calleeType = AI->getSubstCalleeType ();
889
+ SILParameterInfo parameterInfo = calleeType->getParameters ()[ArgumentNumber];
890
+
891
+ if (!parameterInfo.isIndirectMutating () ||
892
+ parameterInfo.getType ().isAnyClassReferenceType ())
893
+ continue ;
894
+
895
+ if (!shouldEmitError (LoadInst))
896
+ continue ;
897
+
898
+ std::string PropertyName;
899
+ auto *VD = TheMemory.getPathStringToElement (Use.FirstElement , PropertyName);
900
+ diagnose (Module, LoadInst->getLoc (),
901
+ diag::mutating_protocol_witness_method_on_let_constant, PropertyName);
902
+
903
+ if (auto *Var = dyn_cast<VarDecl>(VD)) {
904
+ Var->emitLetToVarNoteIfSimple (nullptr );
905
+ }
906
+ }
907
+ }
908
+ }
858
909
859
910
void LifetimeChecker::handleStoreUse (unsigned UseID) {
860
911
DIMemoryUse &InstInfo = Uses[UseID];
0 commit comments