@@ -325,20 +325,40 @@ ManagedValue
325325SILGenFunction::emitOptionalSome (SILLocation loc, SILType optTy,
326326 ValueProducerRef produceValue,
327327 SGFContext C) {
328- // If the conversion is a bridging conversion from an optional type,
329- // do a bridging conversion from the non-optional type instead.
330- // TODO: should this be a general thing for all conversions?
328+ // If we're emitting into a conversion, try to peephole the
329+ // injection into it.
331330 if (auto optInit = C.getAsConversion ()) {
332331 const auto &optConversion = optInit->getConversion ();
333- if (optConversion.isBridging ()) {
334- auto sourceValueType =
335- optConversion.getBridgingSourceType ().getOptionalObjectType ();
336- assert (sourceValueType);
337- if (auto valueConversion =
338- optConversion.adjustForInitialOptionalConversions (sourceValueType)){
339- return optInit->emitWithAdjustedConversion (*this , loc, *valueConversion,
340- produceValue);
341- }
332+
333+ auto adjustment = optConversion.adjustForInitialOptionalInjection ();
334+
335+ // If the adjustment gives us a conversion that produces an optional
336+ // value, that completely takes over emission. This generally happens
337+ // only because of bridging.
338+ if (adjustment.isInjection ()) {
339+ return optInit->emitWithAdjustedConversion (*this , loc,
340+ adjustment.getInjectionConversion (),
341+ produceValue);
342+
343+ // If the adjustment gives us a conversion that produces a non-optional
344+ // value, we need to produce the value under that conversion and then
345+ // inject that into an optional. We can do that by recursing. This
346+ // will terminate because the recursive call to emitOptionalSome gets
347+ // passed a strictly "smaller" context: the parent context of the
348+ // converting context we were passed.
349+ } else if (adjustment.isValue ()) {
350+ auto produceConvertedValue = [&](SILGenFunction &SGF,
351+ SILLocation loc,
352+ SGFContext C) {
353+ return SGF.emitConvertedRValue (loc, adjustment.getValueConversion (),
354+ C, produceValue);
355+ };
356+ auto result = emitOptionalSome (loc, optConversion.getLoweredResultType (),
357+ produceConvertedValue,
358+ optInit->getFinalContext ());
359+ optInit->initWithConvertedValue (*this , loc, result);
360+ optInit->finishInitialization (*this );
361+ return ManagedValue::forInContext ();
342362 }
343363 }
344364
@@ -1141,20 +1161,6 @@ void ConvertingInitialization::
11411161 });
11421162}
11431163
1144- namespace {
1145- struct CombinedConversions {
1146- std::optional<Conversion> first;
1147- std::optional<Conversion> second;
1148-
1149- explicit CombinedConversions () {}
1150- explicit CombinedConversions (const Conversion &first)
1151- : first(first) {}
1152- explicit CombinedConversions (const Conversion &first,
1153- const Conversion &second)
1154- : first(first), second(second) {}
1155- };
1156- }
1157-
11581164static std::optional<CombinedConversions>
11591165combineConversions (SILGenFunction &SGF, const Conversion &outer,
11601166 const Conversion &inner);
@@ -1258,6 +1264,7 @@ ManagedValue Conversion::emit(SILGenFunction &SGF, SILLocation loc,
12581264 ManagedValue value, SGFContext C) const {
12591265 switch (getKind ()) {
12601266 case AnyErasure:
1267+ case BridgingSubtype:
12611268 case Subtype:
12621269 return SGF.emitTransformedValue (loc, value, getBridgingSourceType (),
12631270 getBridgingResultType (), C);
@@ -1312,6 +1319,48 @@ ManagedValue Conversion::emit(SILGenFunction &SGF, SILLocation loc,
13121319 llvm_unreachable (" bad kind" );
13131320}
13141321
1322+ OptionalInjectionConversion
1323+ Conversion::adjustForInitialOptionalInjection () const {
1324+ switch (getKind ()) {
1325+ case Reabstract:
1326+ return OptionalInjectionConversion::forValue (
1327+ getReabstract (
1328+ getReabstractionInputOrigType ().getOptionalObjectType (),
1329+ getReabstractionInputSubstType ().getOptionalObjectType (),
1330+ getReabstractionInputLoweredType ().getOptionalObjectType (),
1331+ getReabstractionOutputOrigType ().getOptionalObjectType (),
1332+ getReabstractionOutputSubstType ().getOptionalObjectType (),
1333+ getReabstractionOutputLoweredType ().getOptionalObjectType ())
1334+ );
1335+
1336+ case Subtype:
1337+ return OptionalInjectionConversion::forValue (
1338+ getSubtype (
1339+ getBridgingSourceType ().getOptionalObjectType (),
1340+ getBridgingResultType ().getOptionalObjectType (),
1341+ getBridgingLoweredResultType ().getOptionalObjectType ())
1342+ );
1343+
1344+ // TODO: can these actually happen?
1345+ case ForceOptional:
1346+ case ForceAndBridgeToObjC:
1347+ case BridgingSubtype:
1348+ return OptionalInjectionConversion ();
1349+
1350+ case AnyErasure:
1351+ case BridgeToObjC:
1352+ case BridgeFromObjC:
1353+ case BridgeResultFromObjC:
1354+ return OptionalInjectionConversion::forInjection (
1355+ getBridging (getKind (), getBridgingSourceType ().getOptionalObjectType (),
1356+ getBridgingResultType (),
1357+ getBridgingLoweredResultType (),
1358+ isBridgingExplicit ())
1359+ );
1360+ }
1361+ llvm_unreachable (" bad kind" );
1362+ }
1363+
13151364std::optional<Conversion>
13161365Conversion::adjustForInitialOptionalConversions (CanType newSourceType) const {
13171366 switch (getKind ()) {
@@ -1323,6 +1372,7 @@ Conversion::adjustForInitialOptionalConversions(CanType newSourceType) const {
13231372 case ForceAndBridgeToObjC:
13241373 return std::nullopt ;
13251374
1375+ case BridgingSubtype:
13261376 case Subtype:
13271377 case AnyErasure:
13281378 case BridgeToObjC:
@@ -1344,6 +1394,7 @@ std::optional<Conversion> Conversion::adjustForInitialForceValue() const {
13441394 case BridgeResultFromObjC:
13451395 case ForceOptional:
13461396 case ForceAndBridgeToObjC:
1397+ case BridgingSubtype:
13471398 case Subtype:
13481399 return std::nullopt ;
13491400
@@ -1397,6 +1448,8 @@ void Conversion::print(llvm::raw_ostream &out) const {
13971448 return printReabstraction (*this , out, " Reabstract" );
13981449 case AnyErasure:
13991450 return printBridging (*this , out, " AnyErasure" );
1451+ case BridgingSubtype:
1452+ return printBridging (*this , out, " BridgingSubtype" );
14001453 case Subtype:
14011454 return printBridging (*this , out, " Subtype" );
14021455 case ForceOptional:
@@ -1749,7 +1802,8 @@ combineBridging(SILGenFunction &SGF,
17491802 sourceType, resultType, loweredResultTy));
17501803 } else {
17511804 return applyPeephole (
1752- Conversion::getSubtype (sourceType, resultType, loweredResultTy));
1805+ Conversion::getBridging (Conversion::BridgingSubtype,
1806+ sourceType, resultType, loweredResultTy));
17531807 }
17541808 }
17551809
@@ -1777,7 +1831,8 @@ combineBridging(SILGenFunction &SGF,
17771831 // Look for a subtype relationship between the source and destination.
17781832 if (areRelatedTypesForBridgingPeephole (sourceType, resultType)) {
17791833 return applyPeephole (
1780- Conversion::getSubtype (sourceType, resultType, loweredResultTy));
1834+ Conversion::getBridging (Conversion::BridgingSubtype,
1835+ sourceType, resultType, loweredResultTy));
17811836 }
17821837
17831838 // If the inner conversion is a result conversion that removes
@@ -1792,7 +1847,8 @@ combineBridging(SILGenFunction &SGF,
17921847 sourceType = sourceValueType;
17931848 loweredSourceTy = loweredSourceTy.getOptionalObjectType ();
17941849 return applyPeephole (
1795- Conversion::getSubtype (sourceValueType, resultType, loweredResultTy));
1850+ Conversion::getBridging (Conversion::BridgingSubtype,
1851+ sourceValueType, resultType, loweredResultTy));
17961852 }
17971853 }
17981854 }
@@ -1824,6 +1880,7 @@ combineConversions(SILGenFunction &SGF, const Conversion &outer,
18241880 return std::nullopt ;
18251881
18261882 case Conversion::AnyErasure:
1883+ case Conversion::BridgingSubtype:
18271884 case Conversion::BridgeFromObjC:
18281885 case Conversion::BridgeResultFromObjC:
18291886 // TODO: maybe peephole bridging through a Swift type?
0 commit comments