@@ -1559,6 +1559,49 @@ CanType TypeBase::getCanonicalType(GenericSignature sig) {
15591559 return sig.getCanonicalTypeInContext (this );
15601560}
15611561
1562+ CanType TypeBase::getMinimalCanonicalType () const {
1563+ const auto MinimalTy = getCanonicalType ().transform ([](Type Ty) -> Type {
1564+ const CanType CanTy = CanType (Ty);
1565+
1566+ if (const auto ET = dyn_cast<ExistentialType>(CanTy)) {
1567+ const auto PCT =
1568+ dyn_cast<ProtocolCompositionType>(ET.getConstraintType ());
1569+ if (!PCT) {
1570+ return CanTy;
1571+ }
1572+
1573+ const auto MinimalTy = PCT->getMinimalCanonicalType ();
1574+ if (MinimalTy->getClassOrBoundGenericClass ()) {
1575+ return MinimalTy;
1576+ }
1577+
1578+ return ExistentialType::get (MinimalTy);
1579+ }
1580+
1581+ if (const auto EM = dyn_cast<ExistentialMetatypeType>(CanTy)) {
1582+ const auto PCT = dyn_cast<ProtocolCompositionType>(EM.getInstanceType ());
1583+ if (!PCT) {
1584+ return CanTy;
1585+ }
1586+
1587+ const auto MinimalTy = PCT->getMinimalCanonicalType ();
1588+ if (MinimalTy->getClassOrBoundGenericClass ()) {
1589+ return MetatypeType::get (MinimalTy);
1590+ }
1591+
1592+ return ExistentialMetatypeType::get (MinimalTy);
1593+ }
1594+
1595+ if (const auto Composition = dyn_cast<ProtocolCompositionType>(CanTy)) {
1596+ return Composition->getMinimalCanonicalType ();
1597+ }
1598+
1599+ return CanTy;
1600+ });
1601+
1602+ return CanType (MinimalTy);
1603+ }
1604+
15621605TypeBase *TypeBase::reconstituteSugar (bool Recursive) {
15631606 auto Func = [Recursive](Type Ty) -> Type {
15641607 if (auto boundGeneric = dyn_cast<BoundGenericType>(Ty.getPointer ())) {
@@ -3712,6 +3755,16 @@ bool ProtocolCompositionType::requiresClass() {
37123755Type ProtocolCompositionType::get (const ASTContext &C,
37133756 ArrayRef<Type> Members,
37143757 bool HasExplicitAnyObject) {
3758+ // Fast path for 'AnyObject' and 'Any'.
3759+ if (Members.empty ()) {
3760+ return build (C, Members, HasExplicitAnyObject);
3761+ }
3762+
3763+ // If there's a single member and no layout constraint, return that type.
3764+ if (Members.size () == 1 && !HasExplicitAnyObject) {
3765+ return Members.front ();
3766+ }
3767+
37153768 for (Type t : Members) {
37163769 if (!t->isCanonical ())
37173770 return build (C, Members, HasExplicitAnyObject);
@@ -3730,11 +3783,6 @@ Type ProtocolCompositionType::get(const ASTContext &C,
37303783 if (Superclass)
37313784 HasExplicitAnyObject = false ;
37323785
3733- // If one protocol remains with no further constraints, its nominal
3734- // type is the canonical type.
3735- if (Protocols.size () == 1 && !Superclass && !HasExplicitAnyObject)
3736- return Protocols.front ()->getDeclaredInterfaceType ();
3737-
37383786 // Form the set of canonical protocol types from the protocol
37393787 // declarations, and use that to build the canonical composition type.
37403788 SmallVector<Type, 4 > CanTypes;
@@ -3744,11 +3792,65 @@ Type ProtocolCompositionType::get(const ASTContext &C,
37443792 Protocols, std::back_inserter (CanTypes),
37453793 [](ProtocolDecl *Proto) { return Proto->getDeclaredInterfaceType (); });
37463794
3747- // TODO: Canonicalize away HasExplicitAnyObject if it is implied
3748- // by one of our member protocols.
3795+ // If one member remains and no layout constraint, return that type.
3796+ if (CanTypes.size () == 1 && !HasExplicitAnyObject)
3797+ return CanTypes.front ();
3798+
37493799 return build (C, CanTypes, HasExplicitAnyObject);
37503800}
37513801
3802+ CanType ProtocolCompositionType::getMinimalCanonicalType () const {
3803+ const CanType CanTy = getCanonicalType ();
3804+
3805+ // If the canonical type is not a composition, it's minimal.
3806+ const auto Composition = dyn_cast<ProtocolCompositionType>(CanTy);
3807+ if (!Composition) {
3808+ return CanTy;
3809+ }
3810+
3811+ // Nothing to minimize.
3812+ if (Composition->getMembers ().empty ()) {
3813+ return CanTy;
3814+ }
3815+
3816+ // The only cases we're missing out on proper minimization is when a
3817+ // composition has an explicit superclass or AnyObject constraint.
3818+ if (!Composition->hasExplicitAnyObject () &&
3819+ !Composition->getMembers ().front ()->getClassOrBoundGenericClass ()) {
3820+ // Already minimal.
3821+ return CanTy;
3822+ }
3823+
3824+ auto &Ctx = CanTy->getASTContext ();
3825+
3826+ // Use generic signature minimization: the requirements of the signature will
3827+ // represent the minimal composition.
3828+ const auto Sig = Ctx.getOpenedArchetypeSignature (CanTy);
3829+ const auto &Reqs = Sig.getRequirements ();
3830+ if (Reqs.size () == 1 ) {
3831+ return Reqs.front ().getSecondType ()->getCanonicalType ();
3832+ }
3833+
3834+ llvm::SmallVector<Type, 2 > MinimalMembers;
3835+ bool MinimalHasExplicitAnyObject = false ;
3836+ for (const auto &Req : Reqs) {
3837+ switch (Req.getKind ()) {
3838+ case RequirementKind::Conformance:
3839+ case RequirementKind::Superclass:
3840+ MinimalMembers.push_back (Req.getSecondType ());
3841+ break ;
3842+ case RequirementKind::Layout:
3843+ MinimalHasExplicitAnyObject = true ;
3844+ break ;
3845+ case RequirementKind::SameType:
3846+ llvm_unreachable (" " );
3847+ }
3848+ }
3849+
3850+ // The resulting composition is necessarily canonical.
3851+ return CanType (build (Ctx, MinimalMembers, MinimalHasExplicitAnyObject));
3852+ }
3853+
37523854ClangTypeInfo AnyFunctionType::getClangTypeInfo () const {
37533855 switch (getKind ()) {
37543856 case TypeKind::Function:
0 commit comments