@@ -320,20 +320,40 @@ ManagedValue
320320SILGenFunction::emitOptionalSome (SILLocation loc, SILType optTy,
321321 ValueProducerRef produceValue,
322322 SGFContext C) {
323- // If the conversion is a bridging conversion from an optional type,
324- // do a bridging conversion from the non-optional type instead.
325- // TODO: should this be a general thing for all conversions?
323+ // If we're emitting into a conversion, try to peephole the
324+ // injection into it.
326325 if (auto optInit = C.getAsConversion ()) {
327326 const auto &optConversion = optInit->getConversion ();
328- if (optConversion.isBridging ()) {
329- auto sourceValueType =
330- optConversion.getBridgingSourceType ().getOptionalObjectType ();
331- assert (sourceValueType);
332- if (auto valueConversion =
333- optConversion.adjustForInitialOptionalConversions (sourceValueType)){
334- return optInit->emitWithAdjustedConversion (*this , loc, *valueConversion,
335- produceValue);
336- }
327+
328+ auto adjustment = optConversion.adjustForInitialOptionalInjection ();
329+
330+ // If the adjustment gives us a conversion that produces an optional
331+ // value, that completely takes over emission. This generally happens
332+ // only because of bridging.
333+ if (adjustment.isInjection ()) {
334+ return optInit->emitWithAdjustedConversion (*this , loc,
335+ adjustment.getInjectionConversion (),
336+ produceValue);
337+
338+ // If the adjustment gives us a conversion that produces a non-optional
339+ // value, we need to produce the value under that conversion and then
340+ // inject that into an optional. We can do that by recursing. This
341+ // will terminate because the recursive call to emitOptionalSome gets
342+ // passed a strictly "smaller" context: the parent context of the
343+ // converting context we were passed.
344+ } else if (adjustment.isValue ()) {
345+ auto produceConvertedValue = [&](SILGenFunction &SGF,
346+ SILLocation loc,
347+ SGFContext C) {
348+ return SGF.emitConvertedRValue (loc, adjustment.getValueConversion (),
349+ C, produceValue);
350+ };
351+ auto result = emitOptionalSome (loc, optConversion.getLoweredResultType (),
352+ produceConvertedValue,
353+ optInit->getFinalContext ());
354+ optInit->initWithConvertedValue (*this , loc, result);
355+ optInit->finishInitialization (*this );
356+ return ManagedValue::forInContext ();
337357 }
338358 }
339359
@@ -1133,20 +1153,6 @@ void ConvertingInitialization::
11331153 });
11341154}
11351155
1136- namespace {
1137- struct CombinedConversions {
1138- std::optional<Conversion> first;
1139- std::optional<Conversion> second;
1140-
1141- explicit CombinedConversions () {}
1142- explicit CombinedConversions (const Conversion &first)
1143- : first(first) {}
1144- explicit CombinedConversions (const Conversion &first,
1145- const Conversion &second)
1146- : first(first), second(second) {}
1147- };
1148- }
1149-
11501156static std::optional<CombinedConversions>
11511157combineConversions (SILGenFunction &SGF, const Conversion &outer,
11521158 const Conversion &inner);
@@ -1250,6 +1256,7 @@ ManagedValue Conversion::emit(SILGenFunction &SGF, SILLocation loc,
12501256 ManagedValue value, SGFContext C) const {
12511257 switch (getKind ()) {
12521258 case AnyErasure:
1259+ case BridgingSubtype:
12531260 case Subtype:
12541261 return SGF.emitTransformedValue (loc, value, getBridgingSourceType (),
12551262 getBridgingResultType (), C);
@@ -1304,6 +1311,48 @@ ManagedValue Conversion::emit(SILGenFunction &SGF, SILLocation loc,
13041311 llvm_unreachable (" bad kind" );
13051312}
13061313
1314+ OptionalInjectionConversion
1315+ Conversion::adjustForInitialOptionalInjection () const {
1316+ switch (getKind ()) {
1317+ case Reabstract:
1318+ return OptionalInjectionConversion::forValue (
1319+ getReabstract (
1320+ getReabstractionInputOrigType ().getOptionalObjectType (),
1321+ getReabstractionInputSubstType ().getOptionalObjectType (),
1322+ getReabstractionInputLoweredType ().getOptionalObjectType (),
1323+ getReabstractionOutputOrigType ().getOptionalObjectType (),
1324+ getReabstractionOutputSubstType ().getOptionalObjectType (),
1325+ getReabstractionOutputLoweredType ().getOptionalObjectType ())
1326+ );
1327+
1328+ case Subtype:
1329+ return OptionalInjectionConversion::forValue (
1330+ getSubtype (
1331+ getBridgingSourceType ().getOptionalObjectType (),
1332+ getBridgingResultType ().getOptionalObjectType (),
1333+ getBridgingLoweredResultType ().getOptionalObjectType ())
1334+ );
1335+
1336+ // TODO: can these actually happen?
1337+ case ForceOptional:
1338+ case ForceAndBridgeToObjC:
1339+ case BridgingSubtype:
1340+ return OptionalInjectionConversion ();
1341+
1342+ case AnyErasure:
1343+ case BridgeToObjC:
1344+ case BridgeFromObjC:
1345+ case BridgeResultFromObjC:
1346+ return OptionalInjectionConversion::forInjection (
1347+ getBridging (getKind (), getBridgingSourceType ().getOptionalObjectType (),
1348+ getBridgingResultType (),
1349+ getBridgingLoweredResultType (),
1350+ isBridgingExplicit ())
1351+ );
1352+ }
1353+ llvm_unreachable (" bad kind" );
1354+ }
1355+
13071356std::optional<Conversion>
13081357Conversion::adjustForInitialOptionalConversions (CanType newSourceType) const {
13091358 switch (getKind ()) {
@@ -1315,6 +1364,7 @@ Conversion::adjustForInitialOptionalConversions(CanType newSourceType) const {
13151364 case ForceAndBridgeToObjC:
13161365 return std::nullopt ;
13171366
1367+ case BridgingSubtype:
13181368 case Subtype:
13191369 case AnyErasure:
13201370 case BridgeToObjC:
@@ -1336,6 +1386,7 @@ std::optional<Conversion> Conversion::adjustForInitialForceValue() const {
13361386 case BridgeResultFromObjC:
13371387 case ForceOptional:
13381388 case ForceAndBridgeToObjC:
1389+ case BridgingSubtype:
13391390 case Subtype:
13401391 return std::nullopt ;
13411392
@@ -1389,6 +1440,8 @@ void Conversion::print(llvm::raw_ostream &out) const {
13891440 return printReabstraction (*this , out, " Reabstract" );
13901441 case AnyErasure:
13911442 return printBridging (*this , out, " AnyErasure" );
1443+ case BridgingSubtype:
1444+ return printBridging (*this , out, " BridgingSubtype" );
13921445 case Subtype:
13931446 return printBridging (*this , out, " Subtype" );
13941447 case ForceOptional:
@@ -1741,7 +1794,8 @@ combineBridging(SILGenFunction &SGF,
17411794 sourceType, resultType, loweredResultTy));
17421795 } else {
17431796 return applyPeephole (
1744- Conversion::getSubtype (sourceType, resultType, loweredResultTy));
1797+ Conversion::getBridging (Conversion::BridgingSubtype,
1798+ sourceType, resultType, loweredResultTy));
17451799 }
17461800 }
17471801
@@ -1769,7 +1823,8 @@ combineBridging(SILGenFunction &SGF,
17691823 // Look for a subtype relationship between the source and destination.
17701824 if (areRelatedTypesForBridgingPeephole (sourceType, resultType)) {
17711825 return applyPeephole (
1772- Conversion::getSubtype (sourceType, resultType, loweredResultTy));
1826+ Conversion::getBridging (Conversion::BridgingSubtype,
1827+ sourceType, resultType, loweredResultTy));
17731828 }
17741829
17751830 // If the inner conversion is a result conversion that removes
@@ -1784,7 +1839,8 @@ combineBridging(SILGenFunction &SGF,
17841839 sourceType = sourceValueType;
17851840 loweredSourceTy = loweredSourceTy.getOptionalObjectType ();
17861841 return applyPeephole (
1787- Conversion::getSubtype (sourceValueType, resultType, loweredResultTy));
1842+ Conversion::getBridging (Conversion::BridgingSubtype,
1843+ sourceValueType, resultType, loweredResultTy));
17881844 }
17891845 }
17901846 }
@@ -1816,6 +1872,7 @@ combineConversions(SILGenFunction &SGF, const Conversion &outer,
18161872 return std::nullopt ;
18171873
18181874 case Conversion::AnyErasure:
1875+ case Conversion::BridgingSubtype:
18191876 case Conversion::BridgeFromObjC:
18201877 case Conversion::BridgeResultFromObjC:
18211878 // TODO: maybe peephole bridging through a Swift type?
0 commit comments