@@ -404,7 +404,7 @@ void PropertyMap::computeConcreteTypeInDomainMap() {
404
404
}
405
405
406
406
void PropertyMap::concretizeNestedTypesFromConcreteParents (
407
- SmallVectorImpl<InducedRule> &inducedRules) const {
407
+ SmallVectorImpl<InducedRule> &inducedRules) {
408
408
for (const auto &props : Entries) {
409
409
if (props->getConformsTo ().empty ())
410
410
continue ;
@@ -426,8 +426,10 @@ void PropertyMap::concretizeNestedTypesFromConcreteParents(
426
426
concretizeNestedTypesFromConcreteParent (
427
427
props->getKey (),
428
428
RequirementKind::SameType,
429
+ *props->ConcreteTypeRule ,
429
430
props->ConcreteType ->getConcreteType (),
430
431
props->ConcreteType ->getSubstitutions (),
432
+ props->ConformsToRules ,
431
433
props->ConformsTo ,
432
434
props->ConcreteConformances ,
433
435
inducedRules);
@@ -441,9 +443,11 @@ void PropertyMap::concretizeNestedTypesFromConcreteParents(
441
443
concretizeNestedTypesFromConcreteParent (
442
444
props->getKey (),
443
445
RequirementKind::Superclass,
446
+ *props->SuperclassRule ,
444
447
props->Superclass ->getSuperclass (),
445
448
props->Superclass ->getSubstitutions (),
446
- props->getConformsTo (),
449
+ props->ConformsToRules ,
450
+ props->ConformsTo ,
447
451
props->SuperclassConformances ,
448
452
inducedRules);
449
453
}
@@ -484,22 +488,45 @@ void PropertyMap::concretizeNestedTypesFromConcreteParents(
484
488
// /
485
489
void PropertyMap::concretizeNestedTypesFromConcreteParent (
486
490
Term key, RequirementKind requirementKind,
487
- CanType concreteType, ArrayRef<Term> substitutions,
491
+ unsigned concreteRuleID,
492
+ CanType concreteType,
493
+ ArrayRef<Term> substitutions,
494
+ ArrayRef<unsigned > conformsToRules,
488
495
ArrayRef<const ProtocolDecl *> conformsTo,
489
496
llvm::TinyPtrVector<ProtocolConformance *> &conformances,
490
- SmallVectorImpl<InducedRule> &inducedRules) const {
497
+ SmallVectorImpl<InducedRule> &inducedRules) {
491
498
assert (requirementKind == RequirementKind::SameType ||
492
499
requirementKind == RequirementKind::Superclass);
500
+ assert (conformsTo.size () == conformsToRules.size ());
501
+
502
+ for (unsigned i : indices (conformsTo)) {
503
+ auto *proto = conformsTo[i];
504
+ unsigned conformanceRuleID = conformsToRules[i];
493
505
494
- for (auto *proto : conformsTo) {
495
506
// FIXME: Either remove the ModuleDecl entirely from conformance lookup,
496
507
// or pass the correct one down in here.
497
508
auto *module = proto->getParentModule ();
498
509
499
510
auto conformance = module ->lookupConformance (concreteType,
500
511
const_cast <ProtocolDecl *>(proto));
501
512
if (conformance.isInvalid ()) {
502
- // FIXME: Diagnose conflict
513
+ // For superclass rules, it is totally fine to have a signature like:
514
+ //
515
+ // protocol P {}
516
+ // class C {}
517
+ // <T where T : P, T : C>
518
+ //
519
+ // There is no relation between P and C here.
520
+ //
521
+ // With concrete types, a missing conformance is a conflict.
522
+ if (requirementKind == RequirementKind::SameType) {
523
+ // FIXME: Diagnose conflict
524
+ //
525
+ // FIXME: We should mark the more specific rule of the two
526
+ // as conflicting.
527
+ System.getRule (conformanceRuleID).markConflicting ();
528
+ }
529
+
503
530
if (Debug.contains (DebugFlags::ConcretizeNestedTypes)) {
504
531
llvm::dbgs () << " ^^ " << concreteType << " does not conform to "
505
532
<< proto->getName () << " \n " ;
@@ -514,6 +541,9 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
514
541
515
542
auto *concrete = conformance.getConcrete ();
516
543
544
+ recordConcreteConformanceRule (concreteRuleID, conformanceRuleID, proto,
545
+ inducedRules);
546
+
517
547
// Record the conformance for use by
518
548
// PropertyBag::getConformsToExcludingSuperclassConformances().
519
549
conformances.push_back (concrete);
@@ -672,92 +702,6 @@ MutableTerm PropertyMap::computeConstraintTermForTypeWitness(
672
702
return constraintType;
673
703
}
674
704
675
- void PropertyMap::recordConcreteConformanceRules (
676
- SmallVectorImpl<InducedRule> &inducedRules) {
677
- for (const auto &props : Entries) {
678
- if (props->getConformsTo ().empty ())
679
- continue ;
680
-
681
- if (props->ConcreteType ) {
682
- unsigned concreteRuleID = *props->ConcreteTypeRule ;
683
-
684
- // The GSB drops all conformance requirements on a type parameter equated
685
- // to a concrete type, even if the concrete type doesn't conform. That is,
686
- //
687
- // protocol P {}
688
- // <T where T : P, T == Int>
689
- //
690
- // minimizes as
691
- //
692
- // <T where T == Int>.
693
- //
694
- // We model this by marking unsatisfied conformance rules as conflicts.
695
-
696
- // The conformances in ConcreteConformances should appear in the same
697
- // order as the protocols in ConformsTo.
698
- auto conformanceIter = props->ConcreteConformances .begin ();
699
-
700
- for (unsigned i : indices (props->ConformsTo )) {
701
- auto conformanceRuleID = props->ConformsToRules [i];
702
- if (conformanceIter == props->ConcreteConformances .end ()) {
703
- // FIXME: We should mark the more specific rule of the conformance and
704
- // concrete type rules as conflicting.
705
- System.getRule (conformanceRuleID).markConflicting ();
706
- continue ;
707
- }
708
-
709
- auto *proto = props->ConformsTo [i];
710
- if (proto != (*conformanceIter)->getProtocol ()) {
711
- // FIXME: We should mark the more specific rule of the conformance and
712
- // concrete type rules as conflicting.
713
- System.getRule (conformanceRuleID).markConflicting ();
714
- continue ;
715
- }
716
-
717
- recordConcreteConformanceRule (concreteRuleID, conformanceRuleID, proto,
718
- inducedRules);
719
- ++conformanceIter;
720
- }
721
-
722
- assert (conformanceIter == props->ConcreteConformances .end ());
723
- }
724
-
725
- if (props->Superclass ) {
726
- unsigned superclassRuleID = *props->SuperclassRule ;
727
-
728
- // For superclass rules, we only introduce a concrete conformance if the
729
- // superclass actually conforms. Otherwise, it is totally fine to have a
730
- // signature like
731
- //
732
- // protocol P {}
733
- // class C {}
734
- // <T where T : P, T : C>
735
- //
736
- // There is no relation between P and C here.
737
-
738
- // The conformances in SuperclassConformances should appear in the same
739
- // order as the protocols in ConformsTo.
740
- auto conformanceIter = props->SuperclassConformances .begin ();
741
-
742
- for (unsigned i : indices (props->ConformsTo )) {
743
- if (conformanceIter == props->SuperclassConformances .end ())
744
- break ;
745
-
746
- auto *proto = props->ConformsTo [i];
747
- if (proto != (*conformanceIter)->getProtocol ())
748
- continue ;
749
-
750
- unsigned conformanceRuleID = props->ConformsToRules [i];
751
- recordConcreteConformanceRule (superclassRuleID, conformanceRuleID, proto,
752
- inducedRules);
753
- ++conformanceIter;
754
- }
755
-
756
- assert (conformanceIter == props->SuperclassConformances .end ());
757
- }
758
- }
759
- }
760
-
761
705
void PropertyMap::recordConcreteConformanceRule (
762
706
unsigned concreteRuleID,
763
707
unsigned conformanceRuleID,
0 commit comments