Skip to content

Commit f39823f

Browse files
authored
Merge pull request #3486 from swiftwasm/main
[pull] swiftwasm from main
2 parents 1424f82 + 9a75847 commit f39823f

File tree

13 files changed

+308
-25
lines changed

13 files changed

+308
-25
lines changed

include/swift/AST/GenericSignature.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,9 @@ class GenericSignature {
200200
/// (archetypes) that correspond to the interface types in this generic
201201
/// signature.
202202
GenericEnvironment *getGenericEnvironment() const;
203+
204+
/// Check invariants.
205+
void verify() const;
203206
};
204207

205208
/// A reference to a canonical generic signature.

include/swift/Sema/ConstraintSystem.h

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,11 @@ class Solution {
11981198
/// A map from argument expressions to their applied property wrapper expressions.
11991199
llvm::MapVector<ASTNode, SmallVector<AppliedPropertyWrapper, 2>> appliedPropertyWrappers;
12001200

1201+
/// A mapping from the constraint locators for references to various
1202+
/// names (e.g., member references, normal name references, possible
1203+
/// constructions) to the argument lists for the call to that locator.
1204+
llvm::MapVector<ConstraintLocator *, ArgumentList *> argumentLists;
1205+
12011206
/// Record a new argument matching choice for given locator that maps a
12021207
/// single argument to a single parameter.
12031208
void recordSingleArgMatchingChoice(ConstraintLocator *locator);
@@ -1332,6 +1337,10 @@ class Solution {
13321337
/// expression type map.
13331338
bool isStaticallyDerivedMetatype(Expr *E) const;
13341339

1340+
/// Retrieve the argument list that is associated with a call at the given
1341+
/// locator.
1342+
ArgumentList *getArgumentList(ConstraintLocator *locator) const;
1343+
13351344
SWIFT_DEBUG_DUMP;
13361345

13371346
/// Dump this solution.
@@ -2406,6 +2415,11 @@ class ConstraintSystem {
24062415
/// Cache of the effects any closures visited.
24072416
llvm::SmallDenseMap<ClosureExpr *, FunctionType::ExtInfo, 4> closureEffectsCache;
24082417

2418+
/// A mapping from the constraint locators for references to various
2419+
/// names (e.g., member references, normal name references, possible
2420+
/// constructions) to the argument lists for the call to that locator.
2421+
llvm::MapVector<ConstraintLocator *, ArgumentList *> ArgumentLists;
2422+
24092423
public:
24102424
/// A map from argument expressions to their applied property wrapper expressions.
24112425
llvm::SmallMapVector<ASTNode, SmallVector<AppliedPropertyWrapper, 2>, 4> appliedPropertyWrappers;
@@ -2784,20 +2798,18 @@ class ConstraintSystem {
27842798
/// we're exploring.
27852799
SolverState *solverState = nullptr;
27862800

2787-
/// A mapping from the constraint locators for references to various
2788-
/// names (e.g., member references, normal name references, possible
2789-
/// constructions) to the argument lists for the call to that locator.
2790-
llvm::DenseMap<ConstraintLocator *, ArgumentList *> ArgumentLists;
2791-
27922801
/// Form a locator that can be used to retrieve argument information cached in
27932802
/// the constraint system for the callee described by the anchor of the
27942803
/// passed locator.
27952804
ConstraintLocator *getArgumentInfoLocator(ConstraintLocator *locator);
27962805

2797-
/// Retrieve the argument list that is associated with a member
2798-
/// reference at the given locator.
2806+
/// Retrieve the argument list that is associated with a call at the given
2807+
/// locator.
27992808
ArgumentList *getArgumentList(ConstraintLocator *locator);
28002809

2810+
/// Associate an argument list with a call at a given locator.
2811+
void associateArgumentList(ConstraintLocator *locator, ArgumentList *args);
2812+
28012813
Optional<SelectedOverload>
28022814
findSelectedOverloadFor(ConstraintLocator *locator) const {
28032815
auto result = ResolvedOverloads.find(locator);
@@ -2896,6 +2908,9 @@ class ConstraintSystem {
28962908
/// The length of \c ImplicitValueConversions.
28972909
unsigned numImplicitValueConversions;
28982910

2911+
/// The length of \c ArgumentLists.
2912+
unsigned numArgumentLists;
2913+
28992914
/// The previous score.
29002915
Score PreviousScore;
29012916

lib/AST/ArgumentList.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ ArgumentList *ArgumentList::createImplicit(ASTContext &ctx, SourceLoc lParenLoc,
116116
ArgumentList *ArgumentList::createImplicit(ASTContext &ctx,
117117
ArrayRef<Argument> args,
118118
AllocationArena arena) {
119-
return createImplicit(ctx, SourceLoc(), args, SourceLoc());
119+
return createImplicit(ctx, SourceLoc(), args, SourceLoc(), arena);
120120
}
121121

122122
ArgumentList *ArgumentList::forImplicitSingle(ASTContext &ctx, Identifier label,

lib/AST/GenericSignature.cpp

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,4 +1539,181 @@ int swift::compareDependentTypes(Type type1, Type type2) {
15391539
return result;
15401540

15411541
return 0;
1542+
}
1543+
1544+
void GenericSignature::verify() const {
1545+
auto canSig = getCanonicalSignature();
1546+
1547+
PrettyStackTraceGenericSignature debugStack("checking", canSig);
1548+
1549+
auto canonicalRequirements = canSig.getRequirements();
1550+
1551+
// We collect conformance requirements to check that they're minimal.
1552+
llvm::SmallDenseMap<CanType, SmallVector<ProtocolDecl *, 2>, 2> conformances;
1553+
1554+
// Check that the requirements satisfy certain invariants.
1555+
for (unsigned idx : indices(canonicalRequirements)) {
1556+
debugStack.setRequirement(idx);
1557+
1558+
const auto &reqt = canonicalRequirements[idx];
1559+
1560+
// Left-hand side must be a canonical type parameter.
1561+
if (reqt.getKind() != RequirementKind::SameType) {
1562+
if (!reqt.getFirstType()->isTypeParameter()) {
1563+
llvm::errs() << "Left-hand side must be a type parameter: ";
1564+
reqt.dump(llvm::errs());
1565+
llvm::errs() << "\n";
1566+
abort();
1567+
}
1568+
1569+
if (!canSig->isCanonicalTypeInContext(reqt.getFirstType())) {
1570+
llvm::errs() << "Left-hand side is not canonical: ";
1571+
reqt.dump(llvm::errs());
1572+
llvm::errs() << "\n";
1573+
abort();
1574+
}
1575+
}
1576+
1577+
// Check canonicalization of requirement itself.
1578+
switch (reqt.getKind()) {
1579+
case RequirementKind::Superclass:
1580+
if (!canSig->isCanonicalTypeInContext(reqt.getSecondType())) {
1581+
llvm::errs() << "Right-hand side is not canonical: ";
1582+
reqt.dump(llvm::errs());
1583+
llvm::errs() << "\n";
1584+
abort();
1585+
}
1586+
break;
1587+
1588+
case RequirementKind::Layout:
1589+
break;
1590+
1591+
case RequirementKind::SameType: {
1592+
auto isCanonicalAnchor = [&](Type type) {
1593+
if (auto *dmt = type->getAs<DependentMemberType>())
1594+
return canSig->isCanonicalTypeInContext(dmt->getBase());
1595+
return type->is<GenericTypeParamType>();
1596+
};
1597+
1598+
auto firstType = reqt.getFirstType();
1599+
auto secondType = reqt.getSecondType();
1600+
if (!isCanonicalAnchor(firstType)) {
1601+
llvm::errs() << "Left hand side does not have a canonical parent: ";
1602+
reqt.dump(llvm::errs());
1603+
llvm::errs() << "\n";
1604+
abort();
1605+
}
1606+
1607+
if (reqt.getSecondType()->isTypeParameter()) {
1608+
if (!isCanonicalAnchor(secondType)) {
1609+
llvm::errs() << "Right hand side does not have a canonical parent: ";
1610+
reqt.dump(llvm::errs());
1611+
llvm::errs() << "\n";
1612+
abort();
1613+
}
1614+
if (compareDependentTypes(firstType, secondType) >= 0) {
1615+
llvm::errs() << "Out-of-order type parameters: ";
1616+
reqt.dump(llvm::errs());
1617+
llvm::errs() << "\n";
1618+
abort();
1619+
}
1620+
} else {
1621+
if (!canSig->isCanonicalTypeInContext(secondType)) {
1622+
llvm::errs() << "Right hand side is not canonical: ";
1623+
reqt.dump(llvm::errs());
1624+
llvm::errs() << "\n";
1625+
abort();
1626+
}
1627+
}
1628+
break;
1629+
}
1630+
1631+
case RequirementKind::Conformance:
1632+
// Collect all conformance requirements on each type parameter.
1633+
conformances[CanType(reqt.getFirstType())].push_back(
1634+
reqt.getProtocolDecl());
1635+
break;
1636+
}
1637+
1638+
// From here on, we're only interested in requirements beyond the first.
1639+
if (idx == 0) continue;
1640+
1641+
// Make sure that the left-hand sides are in nondecreasing order.
1642+
const auto &prevReqt = canonicalRequirements[idx-1];
1643+
int compareLHS =
1644+
compareDependentTypes(prevReqt.getFirstType(), reqt.getFirstType());
1645+
if (compareLHS > 0) {
1646+
llvm::errs() << "Out-of-order left-hand side: ";
1647+
reqt.dump(llvm::errs());
1648+
llvm::errs() << "\n";
1649+
abort();
1650+
}
1651+
1652+
// If we have two same-type requirements where the left-hand sides differ
1653+
// but fall into the same equivalence class, we can check the form.
1654+
if (compareLHS < 0 && reqt.getKind() == RequirementKind::SameType &&
1655+
prevReqt.getKind() == RequirementKind::SameType &&
1656+
canSig->areSameTypeParameterInContext(prevReqt.getFirstType(),
1657+
reqt.getFirstType())) {
1658+
// If it's a it's a type parameter, make sure the equivalence class is
1659+
// wired together sanely.
1660+
if (prevReqt.getSecondType()->isTypeParameter()) {
1661+
if (!prevReqt.getSecondType()->isEqual(reqt.getFirstType())) {
1662+
llvm::errs() << "Same-type requirement within an equiv. class "
1663+
<< "is out-of-order: ";
1664+
reqt.dump(llvm::errs());
1665+
llvm::errs() << "\n";
1666+
abort();
1667+
}
1668+
} else {
1669+
// Otherwise, the concrete types must match up.
1670+
if (!prevReqt.getSecondType()->isEqual(reqt.getSecondType())) {
1671+
llvm::errs() << "Inconsistent concrete requirement in equiv. class: ";
1672+
reqt.dump(llvm::errs());
1673+
llvm::errs() << "\n";
1674+
abort();
1675+
}
1676+
}
1677+
}
1678+
1679+
// If we have a concrete same-type requirement, we shouldn't have any
1680+
// other requirements on the same type.
1681+
if (reqt.getKind() == RequirementKind::SameType &&
1682+
!reqt.getSecondType()->isTypeParameter()) {
1683+
if (compareLHS >= 0) {
1684+
llvm::errs() << "Concrete subject type should not have "
1685+
<< "any other requirements: ";
1686+
reqt.dump(llvm::errs());
1687+
llvm::errs() << "\n";
1688+
abort();
1689+
}
1690+
}
1691+
1692+
if (prevReqt.compare(reqt) >= 0) {
1693+
llvm::errs() << "Out-of-order requirement: ";
1694+
reqt.dump(llvm::errs());
1695+
llvm::errs() << "\n";
1696+
abort();
1697+
}
1698+
}
1699+
1700+
// Make sure we don't have redundant protocol conformance requirements.
1701+
for (auto pair : conformances) {
1702+
const auto &protos = pair.second;
1703+
auto canonicalProtos = protos;
1704+
1705+
// canonicalizeProtocols() will sort them and filter out any protocols that
1706+
// are refined by other protocols in the list. It should be a no-op at this
1707+
// point.
1708+
ProtocolType::canonicalizeProtocols(canonicalProtos);
1709+
1710+
if (protos.size() != canonicalProtos.size()) {
1711+
llvm::errs() << "Redundant conformance requirements in signature\n";
1712+
abort();
1713+
}
1714+
if (!std::equal(protos.begin(), protos.end(), canonicalProtos.begin())) {
1715+
llvm::errs() << "Out-of-order conformance requirements\n";
1716+
abort();
1717+
}
1718+
}
15421719
}

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7997,6 +7997,9 @@ static void checkGenericSignature(CanGenericSignature canSig,
79977997

79987998
auto canonicalRequirements = canSig.getRequirements();
79997999

8000+
// We collect conformance requirements to check that they're minimal.
8001+
llvm::SmallDenseMap<CanType, SmallVector<ProtocolDecl *, 2>, 2> conformances;
8002+
80008003
// Check that the signature is canonical.
80018004
for (unsigned idx : indices(canonicalRequirements)) {
80028005
debugStack.setRequirement(idx);
@@ -8047,6 +8050,10 @@ static void checkGenericSignature(CanGenericSignature canSig,
80478050
"Left-hand side must be a type parameter");
80488051
assert(isa<ProtocolType>(reqt.getSecondType().getPointer()) &&
80498052
"Right-hand side of conformance isn't a protocol type");
8053+
8054+
// Collect all conformance requirements on each type parameter.
8055+
conformances[CanType(reqt.getFirstType())].push_back(
8056+
reqt.getProtocolDecl());
80508057
break;
80518058
}
80528059

@@ -8089,6 +8096,22 @@ static void checkGenericSignature(CanGenericSignature canSig,
80898096
assert(prevReqt.compare(reqt) < 0 &&
80908097
"Out-of-order requirements");
80918098
}
8099+
8100+
// Make sure we don't have redundant protocol conformance requirements.
8101+
for (auto pair : conformances) {
8102+
const auto &protos = pair.second;
8103+
auto canonicalProtos = protos;
8104+
8105+
// canonicalizeProtocols() will sort them and filter out any protocols that
8106+
// are refined by other protocols in the list. It should be a no-op at this
8107+
// point.
8108+
ProtocolType::canonicalizeProtocols(canonicalProtos);
8109+
8110+
assert(protos.size() == canonicalProtos.size() &&
8111+
"redundant conformance requirements");
8112+
assert(std::equal(protos.begin(), protos.end(), canonicalProtos.begin()) &&
8113+
"out-of-order conformance requirements");
8114+
}
80928115
}
80938116
#endif
80948117

@@ -8382,7 +8405,10 @@ GenericSignature GenericSignatureBuilder::computeGenericSignature(
83828405
auto sig = GenericSignature::get(getGenericParams(), requirements);
83838406

83848407
#ifndef NDEBUG
8385-
if (!Impl->HadAnyError) {
8408+
bool hadAnyError = Impl->HadAnyError;
8409+
8410+
if (requirementSignatureSelfProto &&
8411+
!hadAnyError) {
83868412
checkGenericSignature(sig.getCanonicalSignature(), *this);
83878413
}
83888414
#endif
@@ -8405,6 +8431,13 @@ GenericSignature GenericSignatureBuilder::computeGenericSignature(
84058431
// anything more.
84068432
Impl.reset();
84078433

8434+
#ifndef NDEBUG
8435+
if (!requirementSignatureSelfProto &&
8436+
!hadAnyError) {
8437+
sig.verify();
8438+
}
8439+
#endif
8440+
84088441
return sig;
84098442
}
84108443

lib/Sema/CSDiagnostics.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ Expr *FailureDiagnostic::findParentExpr(const Expr *subExpr) const {
112112

113113
ArgumentList *
114114
FailureDiagnostic::getArgumentListFor(ConstraintLocator *locator) const {
115-
return getConstraintSystem().getArgumentList(locator);
115+
return S.getArgumentList(locator);
116116
}
117117

118118
Expr *FailureDiagnostic::getBaseExprFor(const Expr *anchor) const {

lib/Sema/CSGen.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ namespace {
917917
CS.getConstraintLocator(locator,
918918
ConstraintLocator::FunctionResult);
919919

920-
associateArgumentList(memberLocator, argList);
920+
CS.associateArgumentList(memberLocator, argList);
921921

922922
Type outputTy;
923923

@@ -1174,7 +1174,7 @@ namespace {
11741174

11751175
Type visitObjectLiteralExpr(ObjectLiteralExpr *expr) {
11761176
auto *exprLoc = CS.getConstraintLocator(expr);
1177-
associateArgumentList(exprLoc, expr->getArgs());
1177+
CS.associateArgumentList(exprLoc, expr->getArgs());
11781178

11791179
// If the expression has already been assigned a type; just use that type.
11801180
if (expr->getType())
@@ -2687,7 +2687,7 @@ namespace {
26872687
Type visitApplyExpr(ApplyExpr *expr) {
26882688
auto fnExpr = expr->getFn();
26892689

2690-
associateArgumentList(CS.getConstraintLocator(expr), expr->getArgs());
2690+
CS.associateArgumentList(CS.getConstraintLocator(expr), expr->getArgs());
26912691

26922692
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(fnExpr)) {
26932693
auto typeOperation = getTypeOperation(UDE, CS.getASTContext());
@@ -3442,11 +3442,6 @@ namespace {
34423442
}
34433443
llvm_unreachable("unhandled operation");
34443444
}
3445-
3446-
void associateArgumentList(ConstraintLocator *locator, ArgumentList *args) {
3447-
assert(locator && locator->getAnchor());
3448-
CS.ArgumentLists[CS.getArgumentInfoLocator(locator)] = args;
3449-
}
34503445
};
34513446

34523447
class ConstraintWalker : public ASTWalker {

0 commit comments

Comments
 (0)