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