@@ -335,44 +335,65 @@ bool TypeBase::allowsOwnership(const GenericSignatureImpl *sig) {
335335 return getCanonicalType ().allowsOwnership (sig);
336336}
337337
338+ // / Adds the inferred default protocols for an ExistentialLayout with respect
339+ // / to that existential's inverses. For example, if an inverse ~P exists, then
340+ // / P will not be added to the protocols list.
341+ // /
342+ // / \param inverses the inverses '& ~P' that are in the existential's type.
343+ // / \param protocols the output vector of protocols for an ExistentialLayout
344+ // / to be modified.
345+ static void expandDefaultProtocols (
346+ ASTContext &ctx,
347+ InvertibleProtocolSet inverses,
348+ SmallVectorImpl<ProtocolDecl*> &protocols) {
349+
350+ // Skip unless noncopyable generics is enabled
351+ if (!ctx.LangOpts .hasFeature (swift::Feature::NoncopyableGenerics))
352+ return ;
353+
354+ // Try to add all invertible protocols, unless an inverse was provided.
355+ for (auto ip : InvertibleProtocolSet::full ()) {
356+ if (inverses.contains (ip))
357+ continue ;
358+
359+ auto proto = ctx.getProtocol (getKnownProtocolKind (ip));
360+ assert (proto);
361+
362+ protocols.push_back (proto);
363+ }
364+ }
365+
338366ExistentialLayout::ExistentialLayout (CanProtocolType type) {
339367 auto *protoDecl = type->getDecl ();
340368
341369 hasExplicitAnyObject = false ;
342- hasInverseCopyable = false ;
343370 containsNonObjCProtocol = !isObjCProtocol (protoDecl);
344371 containsParameterized = false ;
372+ representsAnyObject = false ;
345373
346374 protocols.push_back (protoDecl);
375+
376+ // NOTE: all the invertible protocols are usable from ObjC.
377+ expandDefaultProtocols (type->getASTContext (), {}, protocols);
347378}
348379
349380ExistentialLayout::ExistentialLayout (CanInverseType type) {
350381 hasExplicitAnyObject = false ;
351- hasInverseCopyable = false ;
352382 containsNonObjCProtocol = false ;
353383 containsParameterized = false ;
384+ representsAnyObject = false ;
354385
355- // Handle inverse.
356- switch (type->getInverseKind ()) {
357- case InvertibleProtocolKind::Copyable:
358- hasInverseCopyable = true ;
359- }
386+ // NOTE: all the invertible protocols are usable from ObjC.
387+ expandDefaultProtocols (type->getASTContext (),
388+ {type->getInverseKind ()},
389+ protocols);
360390}
361391
362392ExistentialLayout::ExistentialLayout (CanProtocolCompositionType type) {
363393 hasExplicitAnyObject = type->hasExplicitAnyObject ();
364- hasInverseCopyable = false ;
365394 containsNonObjCProtocol = false ;
366395 containsParameterized = false ;
367396
368- // Handle inverses.
369- for (auto ip : type->getInverses ()) {
370- switch (ip) {
371- case InvertibleProtocolKind::Copyable:
372- hasInverseCopyable = true ;
373- }
374- }
375-
376397 auto members = type.getMembers ();
377398 if (!members.empty () &&
378399 (members[0 ].getClassOrBoundGenericClass () ||
@@ -393,6 +414,12 @@ ExistentialLayout::ExistentialLayout(CanProtocolCompositionType type) {
393414 containsNonObjCProtocol |= !isObjCProtocol (protoDecl);
394415 protocols.push_back (protoDecl);
395416 }
417+
418+ representsAnyObject =
419+ hasExplicitAnyObject && !explicitSuperclass && getProtocols ().empty ();
420+
421+ // NOTE: all the invertible protocols are usable from ObjC.
422+ expandDefaultProtocols (type->getASTContext (), type->getInverses (), protocols);
396423}
397424
398425ExistentialLayout::ExistentialLayout (CanParameterizedProtocolType type)
@@ -466,10 +493,6 @@ Type ExistentialLayout::getSuperclass() const {
466493 return Type ();
467494}
468495
469- bool ExistentialLayout::isAnyObject () const {
470- return (hasExplicitAnyObject && !explicitSuperclass && getProtocols ().empty ());
471- }
472-
473496bool TypeBase::isObjCExistentialType () {
474497 return getCanonicalType ().isObjCExistentialType ();
475498}
0 commit comments