Skip to content

Commit 7712903

Browse files
committed
Fix nondeterminism in explicitly-specified generic macro arguments
A hash table got flattened into an array without any ordering guarantees, and then we assumed it was in order. Fixes rdar://121397992.
1 parent fcec8b5 commit 7712903

File tree

2 files changed

+53
-18
lines changed

2 files changed

+53
-18
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13701,6 +13701,25 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint(
1370113701
if (simplifiedBoundType->isTypeVariableOrMember())
1370213702
return formUnsolved();
1370313703

13704+
std::function<GenericParamList *(ValueDecl *)> getGenericParams =
13705+
[&](ValueDecl *decl) -> GenericParamList * {
13706+
auto genericContext = decl->getAsGenericContext();
13707+
if (!genericContext)
13708+
return nullptr;
13709+
13710+
auto genericParams = genericContext->getGenericParams();
13711+
if (!genericParams) {
13712+
// If declaration is a non-generic typealias, let's point
13713+
// to the underlying generic declaration.
13714+
if (auto *TA = dyn_cast<TypeAliasDecl>(decl)) {
13715+
if (auto *UGT = TA->getUnderlyingType()->getAs<AnyGenericType>())
13716+
return getGenericParams(UGT->getDecl());
13717+
}
13718+
}
13719+
13720+
return genericParams;
13721+
};
13722+
1370413723
ValueDecl *decl;
1370513724
SmallVector<OpenedType, 2> openedTypes;
1370613725
if (auto *bound = dyn_cast<TypeAliasType>(type1.getPointer())) {
@@ -13757,27 +13776,19 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint(
1375713776
decl = overloadChoice.getDecl();
1375813777

1375913778
auto openedOverloadTypes = getOpenedTypes(overloadLocator);
13760-
openedTypes.append(openedOverloadTypes.begin(), openedOverloadTypes.end());
13761-
}
13762-
13763-
std::function<GenericParamList *(ValueDecl *)> getGenericParams =
13764-
[&](ValueDecl *decl) -> GenericParamList * {
13765-
auto genericContext = decl->getAsGenericContext();
13766-
if (!genericContext)
13767-
return nullptr;
1376813779

13769-
auto genericParams = genericContext->getGenericParams();
13770-
if (!genericParams) {
13771-
// If declaration is a non-generic typealias, let's point
13772-
// to the underlying generic declaration.
13773-
if (auto *TA = dyn_cast<TypeAliasDecl>(decl)) {
13774-
if (auto *UGT = TA->getUnderlyingType()->getAs<AnyGenericType>())
13775-
return getGenericParams(UGT->getDecl());
13780+
auto genericParams = getGenericParams(decl);
13781+
if (genericParams) {
13782+
for (auto gp : *genericParams) {
13783+
auto found = find_if(openedOverloadTypes, [&](auto entry) {
13784+
return entry.first->getDepth() == gp->getDepth() &&
13785+
entry.first->getIndex() == gp->getIndex();
13786+
});
13787+
assert(found != openedOverloadTypes.end());
13788+
openedTypes.push_back(*found);
1377613789
}
1377713790
}
13778-
13779-
return genericParams;
13780-
};
13791+
}
1378113792

1378213793
if (!decl->getAsGenericContext())
1378313794
return SolutionKind::Error;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %target-typecheck-verify-swift -swift-version 5
4+
5+
protocol P {
6+
associatedtype A
7+
}
8+
9+
@freestanding(expression)
10+
macro resolve<T, U: P>(_ first: U.A, _ second: U) -> T = #externalMacro(module: "A", type: "B")
11+
// expected-warning@-1{{external macro implementation type 'A.B' could not be found}}
12+
// expected-note@-2{{'resolve' declared here}}
13+
14+
protocol Q { }
15+
16+
struct X: P {
17+
typealias A = Int
18+
}
19+
20+
func test(i: Int) {
21+
_ = #resolve<any Q, X>(i, X())
22+
// expected-error@-1{{external macro implementation type 'A.B' could not be found for macro 'resolve'; plugin for module 'A' not found}}
23+
}
24+

0 commit comments

Comments
 (0)