@@ -972,20 +972,18 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
972972 // to hold the results. This will be initialized on every entry into the loop
973973 // header and consumed by the loop body. On loop exit, the terminating value
974974 // 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 ();
984980 auto &optTL = SGF.getTypeLowering (optTy);
981+
985982 SILValue addrOnlyBuf;
986- ManagedValue nextBufOrValue;
983+ bool nextResultTyIsAddressOnly =
984+ optTL.isAddressOnly () && SGF.silConv .useLoweredAddresses ();
987985
988- if (optTL. isAddressOnly () && SGF. silConv . useLoweredAddresses () )
986+ if (nextResultTyIsAddressOnly )
989987 addrOnlyBuf = SGF.emitTemporaryAllocation (S, optTL.getLoweredType ());
990988
991989 // Create a new basic block and jump into it.
@@ -1028,25 +1026,22 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
10281026 SGFContext ().withFollowingSideEffects ()));
10291027 };
10301028
1029+ bool hasElementConversion = S->getElementExpr ();
10311030 auto buildElementRValue = [&](SILLocation loc, SGFContext ctx) {
10321031 RValue result;
10331032 result = SGF.emitApplyMethod (
10341033 loc, iteratorNextRef, buildArgumentSource (),
10351034 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);
10431036 return result;
10441037 };
1038+
1039+ ManagedValue nextBufOrElement;
10451040 // Then emit the loop destination block.
10461041 //
10471042 // Advance the generator. Use a scope to ensure that any temporary stack
10481043 // allocations in the subexpression are immediately released.
1049- if (optTL. isAddressOnly () && SGF. silConv . useLoweredAddresses () ) {
1044+ if (nextResultTyIsAddressOnly ) {
10501045 // Create the initialization outside of the innerForScope so that the
10511046 // innerForScope doesn't clean it up.
10521047 auto nextInit = SGF.useBufferAsTemporary (addrOnlyBuf, optTL);
@@ -1061,16 +1056,23 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
10611056 }
10621057 innerForScope.pop ();
10631058 }
1064- nextBufOrValue = nextInit->getManagedAddress ();
1059+ nextBufOrElement = nextInit->getManagedAddress ();
10651060 } else {
10661061 ArgumentScope innerForScope (SGF, SILLocation (S));
1067- nextBufOrValue = innerForScope.popPreservingValue (
1062+ nextBufOrElement = innerForScope.popPreservingValue (
10681063 buildElementRValue (SILLocation (S), SGFContext ())
10691064 .getAsSingleValue (SGF, SILLocation (S)));
10701065 }
10711066
10721067 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+ };
10741076
10751077 switchEnumBuilder.addOptionalSomeCase (
10761078 createBasicBlock (), loopDest.getBlock (),
@@ -1096,13 +1098,22 @@ void StmtEmitter::visitForEachStmt(ForEachStmt *S) {
10961098 //
10971099 // *NOTE* If we do not have an address only value, then inputValue is
10981100 // *already properly unwrapped.
1099- if (optTL.isAddressOnly () && SGF.silConv .useLoweredAddresses ()) {
1101+ SGFContext loopVarCtx{initLoopVars.get ()};
1102+ if (nextResultTyIsAddressOnly) {
11001103 inputValue = SGF.emitUncheckedGetOptionalValueFrom (
1101- S, inputValue, optTL, SGFContext (initLoopVars.get ()));
1104+ S, inputValue, optTL,
1105+ hasElementConversion ? SGFContext () : loopVarCtx);
11021106 }
11031107
1108+ CanType optConvertedTy = optTy;
1109+ if (hasElementConversion) {
1110+ inputValue = convertElementRValue (inputValue, loopVarCtx);
1111+ optConvertedTy =
1112+ OptionalType::get (S->getConvertElementExpr ()->getType ())
1113+ ->getCanonicalType ();
1114+ }
11041115 if (!inputValue.isInContext ())
1105- RValue (SGF, S, optTy .getOptionalObjectType (), inputValue)
1116+ RValue (SGF, S, optConvertedTy .getOptionalObjectType (), inputValue)
11061117 .forwardInto (SGF, S, initLoopVars.get ());
11071118
11081119 // Now that the pattern has been initialized, check any where
0 commit comments