@@ -1417,65 +1417,59 @@ void AttributeChecker::visitSpecializeAttr(SpecializeAttr *attr) {
1417
1417
}
1418
1418
// Initialize each TypeLoc in this attribute with a concrete type,
1419
1419
// and populate a substitution map from GenericTypeParamType to concrete Type.
1420
- TypeSubstitutionMap subMap;
1420
+ SubstitutionMap subMap;
1421
1421
for (unsigned paramIdx = 0 ; paramIdx < numTypes; ++paramIdx) {
1422
1422
1423
1423
auto *genericTypeParamTy = genericSig->getGenericParams ()[paramIdx];
1424
1424
auto &tl = attr->getTypeLocs ()[paramIdx];
1425
1425
1426
1426
auto ty = TC.resolveType (tl.getTypeRepr (), DC, None);
1427
- if (ty && !ty->hasError ()) {
1428
- if (ty->getCanonicalType ()->hasArchetype ()) {
1429
- TC.diagnose (attr->getLocation (),
1430
- diag::cannot_partially_specialize_generic_function);
1431
- return ;
1432
- }
1433
- tl.setType (ty, /* validated=*/ true );
1434
- subMap[genericTypeParamTy->getCanonicalType ().getPointer ()] = ty;
1427
+ if (!ty || ty->hasError ()) {
1428
+ attr->setInvalid ();
1429
+ return ;
1430
+ }
1431
+
1432
+ if (ty->getCanonicalType ()->hasArchetype ()) {
1433
+ TC.diagnose (attr->getLocation (),
1434
+ diag::cannot_partially_specialize_generic_function);
1435
+ attr->setInvalid ();
1436
+ return ;
1435
1437
}
1438
+
1439
+ tl.setType (ty, /* validated=*/ true );
1440
+ subMap.addSubstitution (genericTypeParamTy->getCanonicalType (), ty);
1436
1441
}
1437
- // Build a list of Substitutions.
1438
- //
1439
- // This walks the generic signature's requirements, similar to
1440
- // Solution::computeSubstitutions but with several differences:
1441
- // - It does not operate within the type constraint system.
1442
- // - This is the first point at which diagnostics must be emitted for
1443
- // bad conformances. Self and super requirements must also be
1444
- // checked and diagnosed.
1445
- // - This does not make use of Archetypes since it is directly substituting
1446
- // in place of GenericTypeParams.
1447
- //
1448
- // FIXME: Refactor to use GenericSignature->getSubstitutions()?
1449
- SmallVector<Substitution, 4 > substitutions;
1450
- auto currentModule = FD->getParentModule ();
1451
- Type currentFromTy;
1452
- Type currentReplacement;
1442
+
1443
+ // Capture the conformances needed for the substitution map.
1444
+ CanType currentType;
1453
1445
SmallVector<ProtocolConformanceRef, 4 > currentConformances;
1446
+ auto flushConformances = [&] {
1447
+ subMap.addConformances (currentType,
1448
+ TC.Context .AllocateCopy (currentConformances));
1449
+ currentConformances.clear ();
1450
+ };
1451
+
1454
1452
for (const auto &req : genericSig->getRequirements ()) {
1453
+ // If we're on to a new dependent type, flush the conformances gathered
1454
+ // thus far.
1455
+ CanType canFirstType = req.getFirstType ()->getCanonicalType ();
1456
+ if (req.getKind () != RequirementKind::WitnessMarker &&
1457
+ canFirstType != currentType) {
1458
+ if (currentType) flushConformances ();
1459
+ currentType = canFirstType;
1460
+ }
1455
1461
1456
1462
switch (req.getKind ()) {
1457
1463
case RequirementKind::WitnessMarker:
1458
- // Flush the current conformances.
1459
- if (currentFromTy) {
1460
- substitutions.push_back ({
1461
- currentReplacement,
1462
- DC->getASTContext ().AllocateCopy (currentConformances)
1463
- });
1464
- currentConformances.clear ();
1465
- }
1466
- // Each witness marker starts a new substitution.
1467
- currentFromTy = req.getFirstType ();
1468
- currentReplacement = currentFromTy.subst (currentModule, subMap, None);
1469
1464
break ;
1470
1465
1471
1466
case RequirementKind::Conformance: {
1472
- assert (currentFromTy->getCanonicalType ()
1473
- == req.getFirstType ()->getCanonicalType () && " bad WitnessMarker" );
1474
1467
// Get the conformance and record it.
1468
+ auto firstType = req.getFirstType ().subst (subMap);
1475
1469
auto protoType = req.getSecondType ()->castTo <ProtocolType>();
1476
1470
ProtocolConformance *conformance = nullptr ;
1477
1471
bool conforms =
1478
- TC.conformsToProtocol (currentReplacement ,
1472
+ TC.conformsToProtocol (firstType ,
1479
1473
protoType->getDecl (),
1480
1474
DC,
1481
1475
(ConformanceCheckFlags::InExpression|
@@ -1484,47 +1478,47 @@ void AttributeChecker::visitSpecializeAttr(SpecializeAttr *attr) {
1484
1478
if (!conforms || !conformance) {
1485
1479
TC.diagnose (attr->getLocation (),
1486
1480
diag::cannot_convert_argument_value_protocol,
1487
- currentReplacement , protoType);
1488
- // leaks prior conformances
1481
+ firstType , protoType);
1482
+ attr-> setInvalid ();
1489
1483
return ;
1490
1484
}
1491
- currentConformances. push_back (
1492
- ProtocolConformanceRef (protoType-> getDecl (), conformance));
1485
+
1486
+ currentConformances. push_back ( ProtocolConformanceRef (conformance));
1493
1487
break ;
1494
1488
}
1495
1489
case RequirementKind::Superclass: {
1496
1490
// Superclass requirements aren't recorded in substitutions.
1497
- auto firstTy = req.getFirstType ().subst (currentModule, subMap, None );
1498
- auto superTy = req.getSecondType ().subst (currentModule, subMap, None );
1491
+ auto firstTy = req.getFirstType ().subst (subMap);
1492
+ auto superTy = req.getSecondType ().subst (subMap);
1499
1493
if (!TC.isSubtypeOf (firstTy, superTy, DC)) {
1500
1494
TC.diagnose (attr->getLocation (), diag::type_does_not_inherit,
1501
1495
FD->getInterfaceType (), firstTy, superTy);
1496
+ attr->setInvalid ();
1497
+ return ;
1502
1498
}
1503
1499
break ;
1504
1500
}
1505
1501
case RequirementKind::SameType: {
1506
1502
// Same-type requirements are type checked but not recorded in
1507
1503
// substitutions.
1508
- auto firstTy = req.getFirstType ().subst (currentModule, subMap, None );
1509
- auto sameTy = req.getSecondType ().subst (currentModule, subMap, None );
1504
+ auto firstTy = req.getFirstType ().subst (subMap);
1505
+ auto sameTy = req.getSecondType ().subst (subMap);
1510
1506
if (!firstTy->isEqual (sameTy)) {
1511
1507
TC.diagnose (attr->getLocation (), diag::types_not_equal,
1512
1508
FD->getInterfaceType (), firstTy, sameTy);
1513
-
1509
+ attr-> setInvalid ();
1514
1510
return ;
1515
1511
}
1516
1512
break ;
1517
1513
}
1518
1514
}
1519
1515
}
1520
- // Flush the final conformances.
1521
- if (currentFromTy) {
1522
- substitutions.push_back ({
1523
- currentReplacement,
1524
- DC->getASTContext ().AllocateCopy (currentConformances),
1525
- });
1526
- currentConformances.clear ();
1527
- }
1516
+ if (currentType) flushConformances ();
1517
+
1518
+ // Compute the substitutions.
1519
+ SmallVector<Substitution, 4 > substitutions;
1520
+ genericSig->getSubstitutions (*FD->getParentModule (), subMap, substitutions);
1521
+
1528
1522
// Package the Substitution list in the SpecializeAttr's ConcreteDeclRef.
1529
1523
attr->setConcreteDecl (
1530
1524
ConcreteDeclRef (DC->getASTContext (), FD, substitutions));
0 commit comments