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