@@ -658,6 +658,17 @@ void PropertyMap::addProperty(
658
658
// /
659
659
// / - concrete vs superclass
660
660
// / - concrete vs layout
661
+ // /
662
+ // / Note that we allow a subclass existential 'any C & P' to satisfy a
663
+ // / superclass requirement 'C' as long as 'P' is an @objc protocol.
664
+ // /
665
+ // / This is not fully sound because 'any C & P' is not substitutable for
666
+ // / 'C' if the code calls static method or required initializers on 'C',
667
+ // / but existing code out there relies on this working.
668
+ // /
669
+ // / A more refined check would ensure that 'C' had no required initializers
670
+ // / and that 'P' was self-conforming; or we could ban this entirely in a
671
+ // / future -swift-version mode.
661
672
void PropertyMap::checkConcreteTypeRequirements () {
662
673
bool debug = Debug.contains (DebugFlags::ConcreteUnification);
663
674
@@ -669,6 +680,8 @@ void PropertyMap::checkConcreteTypeRequirements() {
669
680
// If the concrete type is not a class and we have a superclass
670
681
// requirement, we have a conflict.
671
682
if (!concreteType.getConcreteType ()->getClassOrBoundGenericClass () &&
683
+ !(concreteType.getConcreteType ()->isObjCExistentialType () &&
684
+ concreteType.getConcreteType ()->getSuperclass ()) &&
672
685
props->hasSuperclassBound ()) {
673
686
const auto &req = props->getSuperclassRequirement ();
674
687
for (auto pair : req.SuperclassRules ) {
@@ -677,26 +690,35 @@ void PropertyMap::checkConcreteTypeRequirements() {
677
690
}
678
691
}
679
692
680
- if (checkRuleOnce (concreteTypeRule)) {
681
- if (concreteType.getConcreteType ()->getClassOrBoundGenericClass ()) {
682
- // A rule (T.[concrete: C] => T) where C is a class type induces a rule
683
- // (T.[superclass: C] => T).
684
- auto superclassSymbol = Symbol::forSuperclass (
685
- concreteType.getConcreteType (),
686
- concreteType.getSubstitutions (),
687
- Context);
688
-
689
- recordRelation (props->getKey (), concreteTypeRule,
690
- superclassSymbol, System, debug);
691
- }
693
+ // If the concrete type does not satisfy a class layout constraint and
694
+ // we have such a layout requirement, we have a conflict.
695
+ if (!concreteType.getConcreteType ()->satisfiesClassConstraint () &&
696
+ props->LayoutRule &&
697
+ props->Layout ->isClass ()) {
698
+ if (checkRulePairOnce (concreteTypeRule, *props->LayoutRule ))
699
+ System.recordConflict (concreteTypeRule, *props->LayoutRule );
700
+ }
692
701
693
- // A rule (T.[concrete: C] => T) where C is a class type induces a rule
694
- // (T.[layout: L] => T), where L is either AnyObject or _NativeObject.
702
+ if (checkRuleOnce (concreteTypeRule)) {
695
703
if (concreteType.getConcreteType ()->satisfiesClassConstraint ()) {
696
704
Type superclassType = concreteType.getConcreteType ();
697
705
if (!superclassType->getClassOrBoundGenericClass ())
698
706
superclassType = superclassType->getSuperclass ();
699
707
708
+ if (superclassType) {
709
+ // A rule (T.[concrete: C] => T) where C is a class type induces a rule
710
+ // (T.[superclass: C] => T).
711
+ auto superclassSymbol = Symbol::forSuperclass (
712
+ superclassType->getCanonicalType (),
713
+ concreteType.getSubstitutions (),
714
+ Context);
715
+
716
+ recordRelation (props->getKey (), concreteTypeRule,
717
+ superclassSymbol, System, debug);
718
+ }
719
+
720
+ // A rule (T.[concrete: C] => T) where C is a class type induces a rule
721
+ // (T.[layout: L] => T), where L is either AnyObject or _NativeObject.
700
722
auto layoutConstraint = LayoutConstraintKind::Class;
701
723
if (superclassType)
702
724
if (auto *classDecl = superclassType->getClassOrBoundGenericClass ())
@@ -711,15 +733,6 @@ void PropertyMap::checkConcreteTypeRequirements() {
711
733
layoutSymbol, System, debug);
712
734
}
713
735
}
714
-
715
- // If the concrete type does not satisfy a class layout constraint and
716
- // we have such a layout requirement, we have a conflict.
717
- if (!concreteType.getConcreteType ()->satisfiesClassConstraint () &&
718
- props->LayoutRule &&
719
- props->Layout ->isClass ()) {
720
- if (checkRulePairOnce (concreteTypeRule, *props->LayoutRule ))
721
- System.recordConflict (concreteTypeRule, *props->LayoutRule );
722
- }
723
736
}
724
737
}
725
738
}
0 commit comments