24
24
#include " swift/AST/Module.h"
25
25
#include " swift/AST/ParameterList.h"
26
26
#include " swift/AST/ProtocolConformance.h"
27
+ #include " swift/AST/TypeMatcher.h"
27
28
#include " swift/AST/TypeRepr.h"
28
29
#include " swift/AST/TypeWalker.h"
29
30
#include " swift/Basic/Defer.h"
@@ -1315,13 +1316,17 @@ bool ArchetypeBuilder::addSameTypeRequirementBetweenArchetypes(
1315
1316
Type concrete2 = T2->getConcreteType ();
1316
1317
1317
1318
if (concrete1 && concrete2) {
1318
- if (!concrete1->isEqual (concrete2)) {
1319
- Diags.diagnose (Source.getLoc (), diag::requires_same_type_conflict,
1320
- T1->getDependentType (/* FIXME: */ { }, true ), concrete1,
1321
- concrete2);
1322
- return true ;
1323
-
1324
- }
1319
+ bool mismatch =
1320
+ addSameTypeRequirement (concrete1, concrete2, Source, nullptr ,
1321
+ [&](Type type1, Type type2) {
1322
+ Diags.diagnose (Source.getLoc (),
1323
+ diag::requires_same_type_conflict,
1324
+ T1->getDependentType (/* FIXME: */ { }, true ), type1,
1325
+ type2);
1326
+
1327
+ });
1328
+
1329
+ if (mismatch) return true ;
1325
1330
} else if (concrete1) {
1326
1331
assert (!T2->ConcreteType
1327
1332
&& " already formed archetype for concrete-constrained parameter" );
@@ -1389,12 +1394,17 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
1389
1394
// If we've already been bound to a type, we're either done, or we have a
1390
1395
// problem.
1391
1396
if (auto oldConcrete = T->getConcreteType ()) {
1392
- if (!oldConcrete->isEqual (Concrete)) {
1393
- Diags.diagnose (Source.getLoc (), diag::requires_same_type_conflict,
1394
- T->getDependentType (/* FIXME: */ { }, true ), oldConcrete,
1395
- Concrete);
1396
- return true ;
1397
- }
1397
+ bool mismatch =
1398
+ addSameTypeRequirement (oldConcrete, Concrete, Source, nullptr ,
1399
+ [&](Type type1, Type type2) {
1400
+ Diags.diagnose (Source.getLoc (),
1401
+ diag::requires_same_type_conflict,
1402
+ T->getDependentType (/* FIXME: */ { }, true ), type1,
1403
+ type2);
1404
+
1405
+ });
1406
+
1407
+ if (mismatch) return true ;
1398
1408
return false ;
1399
1409
}
1400
1410
@@ -1458,27 +1468,51 @@ bool ArchetypeBuilder::addSameTypeRequirementToConcrete(
1458
1468
return false ;
1459
1469
}
1460
1470
1461
- bool ArchetypeBuilder::addSameTypeRequirement (Type Reqt1, Type Reqt2,
1462
- RequirementSource Source,
1463
- PotentialArchetype *basePA) {
1464
- // Find the potential archetypes.
1465
- PotentialArchetype *T1 = resolveArchetype (Reqt1, basePA);
1466
- PotentialArchetype *T2 = resolveArchetype (Reqt2, basePA);
1471
+ bool ArchetypeBuilder::addSameTypeRequirement (
1472
+ Type type1, Type type2,
1473
+ RequirementSource source,
1474
+ PotentialArchetype *basePA,
1475
+ llvm::function_ref<void (Type, Type)> diagnoseMismatch) {
1476
+ // Local class to handle matching the two sides of the same-type constraint.
1477
+ class ReqTypeMatcher : public TypeMatcher <ReqTypeMatcher> {
1478
+ ArchetypeBuilder &builder;
1479
+ RequirementSource source;
1480
+ PotentialArchetype *basePA;
1481
+ llvm::function_ref<void (Type, Type)> diagnoseMismatch;
1482
+
1483
+ public:
1484
+ ReqTypeMatcher (ArchetypeBuilder &builder,
1485
+ RequirementSource source,
1486
+ PotentialArchetype *basePA,
1487
+ llvm::function_ref<void (Type, Type)> diagnoseMismatch)
1488
+ : builder(builder), source(source), basePA(basePA),
1489
+ diagnoseMismatch (diagnoseMismatch) { }
1490
+
1491
+ bool mismatch (TypeBase *firstType, TypeBase *secondType,
1492
+ Type sugaredFirstType) {
1493
+ // Find the potential archetypes.
1494
+ PotentialArchetype *pa1 = builder.resolveArchetype (firstType, basePA);
1495
+ PotentialArchetype *pa2 = builder.resolveArchetype (secondType, basePA);
1496
+
1497
+ // If both sides of the requirement are type parameters, equate them.
1498
+ if (pa1 && pa2)
1499
+ return !builder.addSameTypeRequirementBetweenArchetypes (pa1, pa2,
1500
+ source);
1501
+
1502
+ // If just one side is a type parameter, map it to a concrete type.
1503
+ if (pa1)
1504
+ return !builder.addSameTypeRequirementToConcrete (pa1, secondType,
1505
+ source);
1506
+ if (pa2)
1507
+ return !builder.addSameTypeRequirementToConcrete (pa2, sugaredFirstType,
1508
+ source);
1509
+
1510
+ diagnoseMismatch (sugaredFirstType, secondType);
1511
+ return false ;
1512
+ }
1513
+ } matcher(*this , source, basePA, diagnoseMismatch);
1467
1514
1468
- // Require that at least one side of the requirement be a potential archetype.
1469
- if (!T1 && !T2) {
1470
- Diags.diagnose (Source.getLoc (), diag::requires_no_same_type_archetype);
1471
- return true ;
1472
- }
1473
-
1474
- // If both sides of the requirement are open archetypes, combine them.
1475
- if (T1 && T2)
1476
- return addSameTypeRequirementBetweenArchetypes (T1, T2, Source);
1477
-
1478
- // Otherwise, we're binding an open archetype.
1479
- if (T1)
1480
- return addSameTypeRequirementToConcrete (T1, Reqt2, Source);
1481
- return addSameTypeRequirementToConcrete (T2, Reqt1, Source);
1515
+ return !matcher.match(type1, type2);
1482
1516
}
1483
1517
1484
1518
// Local function to mark the given associated type as recursive,
@@ -1623,46 +1657,58 @@ bool ArchetypeBuilder::addRequirement(const RequirementRepr &Req) {
1623
1657
}
1624
1658
1625
1659
case RequirementReprKind::SameType:
1626
- return addSameTypeRequirement (Req.getFirstType (),
1627
- Req.getSecondType (),
1628
- RequirementSource (RequirementSource::Explicit,
1629
- Req.getEqualLoc ()));
1660
+ // Require that at least one side of the requirement contain a type
1661
+ // parameter.
1662
+ if (!Req.getFirstType ()->hasTypeParameter () &&
1663
+ !Req.getSecondType ()->hasTypeParameter ()) {
1664
+ Diags.diagnose (Req.getEqualLoc (), diag::requires_no_same_type_archetype)
1665
+ .highlight (Req.getFirstTypeLoc ().getSourceRange ())
1666
+ .highlight (Req.getSecondTypeLoc ().getSourceRange ());
1667
+ return true ;
1668
+ }
1669
+
1670
+ return addRequirement (Requirement (RequirementKind::SameType,
1671
+ Req.getFirstType (),
1672
+ Req.getSecondType ()),
1673
+ RequirementSource (RequirementSource::Explicit,
1674
+ Req.getEqualLoc ()));
1630
1675
}
1631
1676
1632
1677
llvm_unreachable (" Unhandled requirement?" );
1633
1678
}
1634
1679
1635
- void ArchetypeBuilder::addRequirement (const Requirement &req,
1680
+ bool ArchetypeBuilder::addRequirement (const Requirement &req,
1636
1681
RequirementSource source) {
1637
1682
llvm::SmallPtrSet<ProtocolDecl *, 8 > Visited;
1638
- addRequirement (req, source, nullptr , Visited);
1683
+ return addRequirement (req, source, nullptr , Visited);
1639
1684
}
1640
1685
1641
- void ArchetypeBuilder::addRequirement (
1686
+ bool ArchetypeBuilder::addRequirement (
1642
1687
const Requirement &req, RequirementSource source,
1643
1688
PotentialArchetype *basePA,
1644
1689
llvm::SmallPtrSetImpl<ProtocolDecl *> &Visited) {
1645
1690
switch (req.getKind ()) {
1646
1691
case RequirementKind::Superclass: {
1692
+ // FIXME: Diagnose this.
1647
1693
PotentialArchetype *pa = resolveArchetype (req.getFirstType (), basePA);
1648
- if (!pa) return ;
1694
+ if (!pa) return false ;
1649
1695
1650
1696
assert (req.getSecondType ()->getClassOrBoundGenericClass ());
1651
- addSuperclassRequirement (pa, req.getSecondType (), source);
1652
- return ;
1697
+ return addSuperclassRequirement (pa, req.getSecondType (), source);
1653
1698
}
1654
1699
1655
1700
case RequirementKind::Layout: {
1701
+ // FIXME: Diagnose this.
1656
1702
PotentialArchetype *pa = resolveArchetype (req.getFirstType (), basePA);
1657
- if (!pa) return ;
1703
+ if (!pa) return false ;
1658
1704
1659
- (void )addLayoutRequirement (pa, req.getLayoutConstraint (), source);
1660
- return ;
1705
+ return addLayoutRequirement (pa, req.getLayoutConstraint (), source);
1661
1706
}
1662
1707
1663
1708
case RequirementKind::Conformance: {
1709
+ // FIXME: Diagnose this.
1664
1710
PotentialArchetype *pa = resolveArchetype (req.getFirstType (), basePA);
1665
- if (!pa) return ;
1711
+ if (!pa) return false ;
1666
1712
1667
1713
SmallVector<ProtocolDecl *, 4 > conformsTo;
1668
1714
(void )req.getSecondType ()->isExistentialType (conformsTo);
@@ -1673,16 +1719,21 @@ void ArchetypeBuilder::addRequirement(
1673
1719
markPotentialArchetypeRecursive (pa, proto, source);
1674
1720
continue ;
1675
1721
}
1676
- ( void ) addConformanceRequirement (pa, proto, source, Visited);
1722
+ if ( addConformanceRequirement (pa, proto, source, Visited)) return true ;
1677
1723
}
1678
1724
1679
- return ;
1725
+ return false ;
1680
1726
}
1681
1727
1682
1728
case RequirementKind::SameType:
1683
- addSameTypeRequirement (req.getFirstType (), req.getSecondType (), source,
1684
- basePA);
1685
- return ;
1729
+ return addSameTypeRequirement (
1730
+ req.getFirstType (), req.getSecondType (), source, basePA,
1731
+ [&](Type type1, Type type2) {
1732
+ if (source.getLoc ().isValid ())
1733
+ Diags.diagnose (source.getLoc (),
1734
+ diag::requires_same_concrete_type, type1,
1735
+ type2);
1736
+ });
1686
1737
}
1687
1738
1688
1739
llvm_unreachable (" Unhandled requirement?" );
0 commit comments