@@ -674,7 +674,31 @@ static unsigned sourcePathLength(const RequirementSource *source) {
674
674
return count;
675
675
}
676
676
677
+ // / Check whether we have a NestedTypeNameMatch/ProtocolRequirement requirement
678
+ // / pair, in which case we prefer the RequirementSignature.
679
+ // /
680
+ // / This is part of staging out NestedTypeNameMatch requirement sources in
681
+ // / favor of something more principled.
682
+ static int isNestedTypeNameMatchAndRequirementSignaturePair (
683
+ const RequirementSource *lhs,
684
+ const RequirementSource *rhs) {
685
+ if (lhs->getRoot ()->kind == RequirementSource::NestedTypeNameMatch &&
686
+ rhs->isProtocolRequirement ())
687
+ return +1 ;
688
+
689
+ if (rhs->getRoot ()->kind == RequirementSource::NestedTypeNameMatch &&
690
+ lhs->isProtocolRequirement ())
691
+ return -1 ;
692
+
693
+ return 0 ;
694
+ }
695
+
677
696
int RequirementSource::compare (const RequirementSource *other) const {
697
+ // FIXME: Egregious hack while we phase out NestedTypeNameMatch
698
+ if (int compare =
699
+ isNestedTypeNameMatchAndRequirementSignaturePair (this , other))
700
+ return compare;
701
+
678
702
// Prefer the derived option, if there is one.
679
703
bool thisIsDerived = this ->isDerivedRequirement ();
680
704
bool otherIsDerived = other->isDerivedRequirement ();
@@ -2459,7 +2483,7 @@ ConstraintResult GenericSignatureBuilder::addConformanceRequirement(
2459
2483
2460
2484
// Collect all of the inherited associated types and typealiases in the
2461
2485
// inherited protocols (recursively).
2462
- DenseMap <DeclName, TinyPtrVector<TypeDecl *>> inheritedTypeDecls;
2486
+ llvm::MapVector <DeclName, TinyPtrVector<TypeDecl *>> inheritedTypeDecls;
2463
2487
{
2464
2488
Proto->walkInheritedProtocols (
2465
2489
[&](ProtocolDecl *inheritedProto) -> TypeWalker::Action {
@@ -2523,17 +2547,58 @@ ConstraintResult GenericSignatureBuilder::addConformanceRequirement(
2523
2547
return result;
2524
2548
};
2525
2549
2550
+ // Form an unsubstituted type referring to the given type declaration,
2551
+ // for use in an inferred same-type requirement.
2552
+ auto formUnsubstitutedType = [&](TypeDecl *typeDecl) -> Type {
2553
+ if (auto assocType = dyn_cast<AssociatedTypeDecl>(typeDecl)) {
2554
+ return DependentMemberType::get (
2555
+ assocType->getProtocol ()->getSelfInterfaceType (),
2556
+ assocType);
2557
+ }
2558
+
2559
+ if (auto typealias = dyn_cast<TypeAliasDecl>(typeDecl)) {
2560
+ // Resolve the underlying type, if we haven't done so yet.
2561
+ if (!typealias->hasInterfaceType ()) {
2562
+ getLazyResolver ()->resolveDeclSignature (typealias);
2563
+ }
2564
+
2565
+ return typealias->getUnderlyingTypeLoc ().getType ();
2566
+ }
2567
+
2568
+ return Type ();
2569
+ };
2570
+
2571
+ // An an inferred same-type requirement between the two type declarations
2572
+ // within this protocol or a protocol it inherits.
2573
+ auto addInferredSameTypeReq = [&](TypeDecl *first, TypeDecl *second) {
2574
+ Type firstType = formUnsubstitutedType (first);
2575
+ if (!firstType) return ;
2576
+
2577
+ Type secondType = formUnsubstitutedType (second);
2578
+ if (!secondType) return ;
2579
+
2580
+ auto inferredSameTypeSource =
2581
+ FloatingRequirementSource::viaProtocolRequirement (
2582
+ Source, Proto, WrittenRequirementLoc (), /* inferred=*/ true );
2583
+
2584
+ addRequirement (
2585
+ Requirement (RequirementKind::SameType, firstType, secondType),
2586
+ inferredSameTypeSource, Proto->getParentModule (),
2587
+ &protocolSubMap);
2588
+ };
2589
+
2526
2590
// Add requirements for each of the associated types.
2527
2591
for (auto Member : getProtocolMembers (Proto)) {
2528
- if (auto AssocType = dyn_cast<AssociatedTypeDecl>(Member)) {
2592
+ if (auto assocTypeDecl = dyn_cast<AssociatedTypeDecl>(Member)) {
2529
2593
// Add requirements placed directly on this associated type.
2530
- Type assocType = DependentMemberType::get (concreteSelf, AssocType );
2594
+ Type assocType = DependentMemberType::get (concreteSelf, assocTypeDecl );
2531
2595
auto assocResult =
2532
- addInheritedRequirements (AssocType , assocType, Source, protoModule);
2596
+ addInheritedRequirements (assocTypeDecl , assocType, Source, protoModule);
2533
2597
if (isErrorResult (assocResult))
2534
2598
return assocResult;
2535
2599
2536
- if (auto WhereClause = AssocType->getTrailingWhereClause ()) {
2600
+ // Add requirements from this associated type's where clause.
2601
+ if (auto WhereClause = assocTypeDecl->getTrailingWhereClause ()) {
2537
2602
for (auto &req : WhereClause->getRequirements ()) {
2538
2603
auto innerSource =
2539
2604
FloatingRequirementSource::viaProtocolRequirement (
@@ -2543,30 +2608,33 @@ ConstraintResult GenericSignatureBuilder::addConformanceRequirement(
2543
2608
}
2544
2609
2545
2610
// Check whether we inherited any types with the same name.
2546
- auto knownInherited = inheritedTypeDecls.find (AssocType->getFullName ());
2611
+ auto knownInherited =
2612
+ inheritedTypeDecls.find (assocTypeDecl->getFullName ());
2547
2613
if (knownInherited == inheritedTypeDecls.end ()) continue ;
2548
2614
2549
2615
bool shouldWarnAboutRedeclaration =
2550
2616
Source->kind == RequirementSource::RequirementSignatureSelf &&
2551
- AssocType ->getDefaultDefinitionLoc ().isNull ();
2552
- for (auto inheritedType : knownInherited->getSecond () ) {
2617
+ assocTypeDecl ->getDefaultDefinitionLoc ().isNull ();
2618
+ for (auto inheritedType : knownInherited->second ) {
2553
2619
// If we have inherited associated type...
2554
2620
if (auto inheritedAssocTypeDecl =
2555
2621
dyn_cast<AssociatedTypeDecl>(inheritedType)) {
2556
- // FIXME: Wire up same-type constraint.
2622
+ // Infer a same-type requirement among the same-named associated
2623
+ // types.
2624
+ addInferredSameTypeReq (assocTypeDecl, inheritedAssocTypeDecl);
2557
2625
2558
2626
// Complain about the first redeclaration.
2559
2627
if (shouldWarnAboutRedeclaration) {
2560
2628
auto inheritedFromProto = inheritedAssocTypeDecl->getProtocol ();
2561
2629
auto fixItWhere = getProtocolWhereLoc ();
2562
- Diags.diagnose (AssocType ,
2630
+ Diags.diagnose (assocTypeDecl ,
2563
2631
diag::inherited_associated_type_redecl,
2564
- AssocType ->getFullName (),
2632
+ assocTypeDecl ->getFullName (),
2565
2633
inheritedFromProto->getDeclaredInterfaceType ())
2566
2634
.fixItInsertAfter (
2567
- fixItWhere.first ,
2568
- getAssociatedTypeReqs (AssocType , fixItWhere.second ))
2569
- .fixItRemove (AssocType ->getSourceRange ());
2635
+ fixItWhere.first ,
2636
+ getAssociatedTypeReqs (assocTypeDecl , fixItWhere.second ))
2637
+ .fixItRemove (assocTypeDecl ->getSourceRange ());
2570
2638
2571
2639
Diags.diagnose (inheritedAssocTypeDecl, diag::decl_declared_here,
2572
2640
inheritedAssocTypeDecl->getFullName ());
@@ -2592,11 +2660,13 @@ ConstraintResult GenericSignatureBuilder::addConformanceRequirement(
2592
2660
bool shouldWarnAboutRedeclaration =
2593
2661
Source->kind == RequirementSource::RequirementSignatureSelf;
2594
2662
2595
- for (auto inheritedType : knownInherited->getSecond () ) {
2663
+ for (auto inheritedType : knownInherited->second ) {
2596
2664
// If we have inherited associated type...
2597
2665
if (auto inheritedAssocTypeDecl =
2598
2666
dyn_cast<AssociatedTypeDecl>(inheritedType)) {
2599
- // FIXME: Wire up same-type constraint.
2667
+ // Infer a same-type requirement between the typealias' underlying
2668
+ // type and the inherited associated type.
2669
+ addInferredSameTypeReq (inheritedAssocTypeDecl, typealias);
2600
2670
2601
2671
// Warn that one should use where clauses for this.
2602
2672
if (shouldWarnAboutRedeclaration) {
@@ -2626,6 +2696,16 @@ ConstraintResult GenericSignatureBuilder::addConformanceRequirement(
2626
2696
}
2627
2697
}
2628
2698
2699
+ // Infer same-type requirements among inherited type declarations.
2700
+ for (auto &entry : inheritedTypeDecls) {
2701
+ if (entry.second .size () < 2 ) continue ;
2702
+
2703
+ auto firstDecl = entry.second .front ();
2704
+ for (auto otherDecl : ArrayRef<TypeDecl *>(entry.second ).slice (1 )) {
2705
+ addInferredSameTypeReq (firstDecl, otherDecl);
2706
+ }
2707
+ }
2708
+
2629
2709
return ConstraintResult::Resolved;
2630
2710
}
2631
2711
0 commit comments