@@ -969,20 +969,18 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
969
969
// to hold the results. This will be initialized on every entry into the loop
970
970
// header and consumed by the loop body. On loop exit, the terminating value
971
971
// will be in the buffer.
972
- CanType optTy;
973
- if (S->getConvertElementExpr ()) {
974
- optTy = S->getConvertElementExpr ()->getType ()->getCanonicalType ();
975
- } else {
976
- optTy = OptionalType::get (S->getSequenceConformance ().getTypeWitnessByName (
977
- S->getSequence ()->getType (),
978
- SGF.getASTContext ().Id_Element ))
979
- ->getCanonicalType ();
980
- }
972
+ CanType optTy =
973
+ OptionalType::get (
974
+ S->getSequenceConformance ().getTypeWitnessByName (
975
+ S->getSequence ()->getType (), SGF.getASTContext ().Id_Element ))
976
+ ->getCanonicalType ();
981
977
auto &optTL = SGF.getTypeLowering (optTy);
978
+
982
979
SILValue addrOnlyBuf;
983
- ManagedValue nextBufOrValue;
980
+ bool nextResultTyIsAddressOnly =
981
+ optTL.isAddressOnly () && SGF.silConv .useLoweredAddresses ();
984
982
985
- if (optTL. isAddressOnly () && SGF. silConv . useLoweredAddresses () )
983
+ if (nextResultTyIsAddressOnly )
986
984
addrOnlyBuf = SGF.emitTemporaryAllocation (S, optTL.getLoweredType ());
987
985
988
986
// Create a new basic block and jump into it.
@@ -1025,25 +1023,22 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
1025
1023
SGFContext ().withFollowingSideEffects ()));
1026
1024
};
1027
1025
1026
+ bool hasElementConversion = S->getElementExpr ();
1028
1027
auto buildElementRValue = [&](SILLocation loc, SGFContext ctx) {
1029
1028
RValue result;
1030
1029
result = SGF.emitApplyMethod (
1031
1030
loc, iteratorNextRef, buildArgumentSource (),
1032
1031
PreparedArguments (ArrayRef<AnyFunctionType::Param>({})),
1033
- S->getElementExpr () ? SGFContext () : ctx);
1034
- if (S->getElementExpr ()) {
1035
- SILGenFunction::OpaqueValueRAII pushOpaqueValue (
1036
- SGF, S->getElementExpr (),
1037
- std::move (result).getAsSingleValue (SGF, loc));
1038
- result = SGF.emitRValue (S->getConvertElementExpr (), ctx);
1039
- }
1032
+ hasElementConversion ? SGFContext () : ctx);
1040
1033
return result;
1041
1034
};
1035
+
1036
+ ManagedValue nextBufOrElement;
1042
1037
// Then emit the loop destination block.
1043
1038
//
1044
1039
// Advance the generator. Use a scope to ensure that any temporary stack
1045
1040
// allocations in the subexpression are immediately released.
1046
- if (optTL. isAddressOnly () && SGF. silConv . useLoweredAddresses () ) {
1041
+ if (nextResultTyIsAddressOnly ) {
1047
1042
// Create the initialization outside of the innerForScope so that the
1048
1043
// innerForScope doesn't clean it up.
1049
1044
auto nextInit = SGF.useBufferAsTemporary (addrOnlyBuf, optTL);
@@ -1058,16 +1053,23 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
1058
1053
}
1059
1054
innerForScope.pop ();
1060
1055
}
1061
- nextBufOrValue = nextInit->getManagedAddress ();
1056
+ nextBufOrElement = nextInit->getManagedAddress ();
1062
1057
} else {
1063
1058
ArgumentScope innerForScope (SGF, SILLocation (S));
1064
- nextBufOrValue = innerForScope.popPreservingValue (
1059
+ nextBufOrElement = innerForScope.popPreservingValue (
1065
1060
buildElementRValue (SILLocation (S), SGFContext ())
1066
1061
.getAsSingleValue (SGF, SILLocation (S)));
1067
1062
}
1068
1063
1069
1064
SILBasicBlock *failExitingBlock = createBasicBlock ();
1070
- SwitchEnumBuilder switchEnumBuilder (SGF.B , S, nextBufOrValue);
1065
+ SwitchEnumBuilder switchEnumBuilder (SGF.B , S, nextBufOrElement);
1066
+
1067
+ auto convertElementRValue = [&](ManagedValue inputValue, SGFContext ctx) -> ManagedValue {
1068
+ SILGenFunction::OpaqueValueRAII pushOpaqueValue (SGF, S->getElementExpr (),
1069
+ inputValue);
1070
+ return SGF.emitRValue (S->getConvertElementExpr (), ctx)
1071
+ .getAsSingleValue (SGF, SILLocation (S));
1072
+ };
1071
1073
1072
1074
switchEnumBuilder.addOptionalSomeCase (
1073
1075
createBasicBlock (), loopDest.getBlock (),
@@ -1093,13 +1095,22 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
1093
1095
//
1094
1096
// *NOTE* If we do not have an address only value, then inputValue is
1095
1097
// *already properly unwrapped.
1096
- if (optTL.isAddressOnly () && SGF.silConv .useLoweredAddresses ()) {
1098
+ SGFContext loopVarCtx{initLoopVars.get ()};
1099
+ if (nextResultTyIsAddressOnly) {
1097
1100
inputValue = SGF.emitUncheckedGetOptionalValueFrom (
1098
- S, inputValue, optTL, SGFContext (initLoopVars.get ()));
1101
+ S, inputValue, optTL,
1102
+ hasElementConversion ? SGFContext () : loopVarCtx);
1099
1103
}
1100
1104
1105
+ CanType optConvertedTy = optTy;
1106
+ if (hasElementConversion) {
1107
+ inputValue = convertElementRValue (inputValue, loopVarCtx);
1108
+ optConvertedTy =
1109
+ OptionalType::get (S->getConvertElementExpr ()->getType ())
1110
+ ->getCanonicalType ();
1111
+ }
1101
1112
if (!inputValue.isInContext ())
1102
- RValue (SGF, S, optTy .getOptionalObjectType (), inputValue)
1113
+ RValue (SGF, S, optConvertedTy .getOptionalObjectType (), inputValue)
1103
1114
.forwardInto (SGF, S, initLoopVars.get ());
1104
1115
1105
1116
// Now that the pattern has been initialized, check any where
0 commit comments