@@ -1392,68 +1392,68 @@ static bool optimizeStaticallyKnownProtocolConformance(
1392
1392
auto *SM = Mod.getSwiftModule ();
1393
1393
1394
1394
auto Proto = dyn_cast<ProtocolDecl>(TargetType->getAnyNominal ());
1395
- if (Proto) {
1396
- auto Conformance = SM->lookupConformance (SourceType, Proto);
1397
- if (Conformance.hasValue () &&
1398
- Conformance->getConditionalRequirements ().empty ()) {
1399
- // SourceType is a non-existential type with a non-conditional
1400
- // conformance to a protocol represented by the TargetType.
1401
- //
1402
- // Conditional conformances are complicated: they may depend on
1403
- // information not known until runtime. For instance, if `X: P` where `T
1404
- // == Int` in `func foo<T>(_: T) { ... X<T>() as? P ... }`, the cast
1405
- // will succeed for `foo(0)` but not for `foo("string")`. There are many
1406
- // cases where everything is completely static (`X<Int>() as? P`), but
1407
- // we don't try to handle that at the moment.
1408
- SILBuilder B (Inst);
1409
- SmallVector<ProtocolConformanceRef, 1 > NewConformances;
1410
- NewConformances.push_back (Conformance.getValue ());
1411
- ArrayRef<ProtocolConformanceRef> Conformances =
1412
- Ctx.AllocateCopy (NewConformances);
1413
-
1414
- auto ExistentialRepr =
1415
- Dest->getType ().getPreferredExistentialRepresentation (Mod,
1416
- SourceType);
1417
-
1418
- switch (ExistentialRepr) {
1419
- default :
1420
- return false ;
1421
- case ExistentialRepresentation::Opaque: {
1422
- auto ExistentialAddr = B.createInitExistentialAddr (
1423
- Loc, Dest, SourceType, Src->getType ().getObjectType (),
1424
- Conformances);
1425
- B.createCopyAddr (Loc, Src, ExistentialAddr, IsTake_t::IsTake,
1426
- IsInitialization_t::IsInitialization);
1427
- break ;
1428
- }
1429
- case ExistentialRepresentation::Class: {
1430
- auto Value = B.createLoad (Loc, Src,
1431
- swift::LoadOwnershipQualifier::Unqualified);
1432
- auto Existential =
1433
- B.createInitExistentialRef (Loc, Dest->getType ().getObjectType (),
1434
- SourceType, Value, Conformances);
1435
- B.createStore (Loc, Existential, Dest,
1436
- swift::StoreOwnershipQualifier::Unqualified);
1437
- break ;
1438
- }
1439
- case ExistentialRepresentation::Boxed: {
1440
- auto AllocBox = B.createAllocExistentialBox (Loc, Dest->getType (),
1441
- SourceType, Conformances);
1442
- auto Projection =
1443
- B.createProjectExistentialBox (Loc, Src->getType (), AllocBox);
1444
- // This needs to be a copy_addr (for now) because we must handle
1445
- // address-only types.
1446
- B.createCopyAddr (Loc, Src, Projection, IsTake, IsInitialization);
1447
- B.createStore (Loc, AllocBox, Dest,
1448
- swift::StoreOwnershipQualifier::Unqualified);
1449
- break ;
1450
- }
1451
- };
1395
+ if (!Proto)
1396
+ return false ;
1452
1397
1453
- return true ;
1454
- }
1398
+ // SourceType is a non-existential type with a non-conditional
1399
+ // conformance to a protocol represented by the TargetType.
1400
+ //
1401
+ // TypeChecker::conformsToProtocol checks any conditional conformances. If
1402
+ // they depend on information not known until runtime, the conformance
1403
+ // will not be returned. For instance, if `X: P` where `T == Int` in `func
1404
+ // foo<T>(_: T) { ... X<T>() as? P ... }`, the cast will succeed for
1405
+ // `foo(0)` but not for `foo("string")`. There are many cases where
1406
+ // everything is completely static (`X<Int>() as? P`), in which case a
1407
+ // valid conformance will be returned.
1408
+ auto Conformance = SM->conformsToProtocol (SourceType, Proto);
1409
+ if (!Conformance)
1410
+ return false ;
1411
+
1412
+ SILBuilder B (Inst);
1413
+ SmallVector<ProtocolConformanceRef, 1 > NewConformances;
1414
+ NewConformances.push_back (Conformance.getValue ());
1415
+ ArrayRef<ProtocolConformanceRef> Conformances =
1416
+ Ctx.AllocateCopy (NewConformances);
1417
+
1418
+ auto ExistentialRepr =
1419
+ Dest->getType ().getPreferredExistentialRepresentation (Mod, SourceType);
1420
+
1421
+ switch (ExistentialRepr) {
1422
+ default :
1423
+ return false ;
1424
+ case ExistentialRepresentation::Opaque: {
1425
+ auto ExistentialAddr = B.createInitExistentialAddr (
1426
+ Loc, Dest, SourceType, Src->getType ().getObjectType (), Conformances);
1427
+ B.createCopyAddr (Loc, Src, ExistentialAddr, IsTake_t::IsTake,
1428
+ IsInitialization_t::IsInitialization);
1429
+ break ;
1455
1430
}
1431
+ case ExistentialRepresentation::Class: {
1432
+ auto Value =
1433
+ B.createLoad (Loc, Src, swift::LoadOwnershipQualifier::Unqualified);
1434
+ auto Existential =
1435
+ B.createInitExistentialRef (Loc, Dest->getType ().getObjectType (),
1436
+ SourceType, Value, Conformances);
1437
+ B.createStore (Loc, Existential, Dest,
1438
+ swift::StoreOwnershipQualifier::Unqualified);
1439
+ break ;
1440
+ }
1441
+ case ExistentialRepresentation::Boxed: {
1442
+ auto AllocBox = B.createAllocExistentialBox (Loc, Dest->getType (),
1443
+ SourceType, Conformances);
1444
+ auto Projection =
1445
+ B.createProjectExistentialBox (Loc, Src->getType (), AllocBox);
1446
+ // This needs to be a copy_addr (for now) because we must handle
1447
+ // address-only types.
1448
+ B.createCopyAddr (Loc, Src, Projection, IsTake, IsInitialization);
1449
+ B.createStore (Loc, AllocBox, Dest,
1450
+ swift::StoreOwnershipQualifier::Unqualified);
1451
+ break ;
1452
+ }
1453
+ };
1454
+ return true ;
1456
1455
}
1456
+ // Not a concrete -> existential cast.
1457
1457
return false ;
1458
1458
}
1459
1459
0 commit comments