Skip to content

Commit 7e71641

Browse files
authored
Merge pull request #76397 from xedin/rdar-135610320
[CSSimplify] Specialization: Fix a crash when specialized declaration…
2 parents 5ac817e + efd43b0 commit 7e71641

File tree

2 files changed

+101
-16
lines changed

2 files changed

+101
-16
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13858,6 +13858,23 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint(
1385813858
return genericParams;
1385913859
};
1386013860

13861+
auto fixInvalidSpecialization = [&](ValueDecl *decl) -> SolutionKind {
13862+
if (isa<AbstractFunctionDecl>(decl)) {
13863+
return recordFix(AllowFunctionSpecialization::create(
13864+
*this, decl, getConstraintLocator(locator)))
13865+
? SolutionKind::Error
13866+
: SolutionKind::Solved;
13867+
}
13868+
13869+
// Allow concrete macros to have specializations with just a warning.
13870+
return recordFix(AllowConcreteTypeSpecialization::create(
13871+
*this, type1, decl, getConstraintLocator(locator),
13872+
isa<MacroDecl>(decl) ? FixBehavior::DowngradeToWarning
13873+
: FixBehavior::Error))
13874+
? SolutionKind::Error
13875+
: SolutionKind::Solved;
13876+
};
13877+
1386113878
ValueDecl *decl;
1386213879
SmallVector<OpenedType, 2> openedTypes;
1386313880
if (auto *bound = dyn_cast<TypeAliasType>(type1.getPointer())) {
@@ -13916,6 +13933,12 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint(
1391613933
decl = overloadChoice.getDecl();
1391713934

1391813935
auto openedOverloadTypes = getOpenedTypes(overloadLocator);
13936+
// Attempting to specialize a non-generic declaration.
13937+
if (openedOverloadTypes.empty()) {
13938+
// Note that this is unconditional because the fix is
13939+
// downgraded to a warning in swift language modes < 6.
13940+
return fixInvalidSpecialization(decl);
13941+
}
1391913942

1392013943
auto genericParams = getGenericParams(decl);
1392113944
if (genericParams) {
@@ -13931,22 +13954,8 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint(
1393113954
}
1393213955

1393313956
auto genericParams = getGenericParams(decl);
13934-
if (!decl->getAsGenericContext() || !genericParams) {
13935-
if (isa<AbstractFunctionDecl>(decl)) {
13936-
return recordFix(AllowFunctionSpecialization::create(
13937-
*this, decl, getConstraintLocator(locator)))
13938-
? SolutionKind::Error
13939-
: SolutionKind::Solved;
13940-
}
13941-
13942-
// Allow concrete macros to have specializations with just a warning.
13943-
return recordFix(AllowConcreteTypeSpecialization::create(
13944-
*this, type1, decl, getConstraintLocator(locator),
13945-
isa<MacroDecl>(decl) ? FixBehavior::DowngradeToWarning
13946-
: FixBehavior::Error))
13947-
? SolutionKind::Error
13948-
: SolutionKind::Solved;
13949-
}
13957+
if (!decl->getAsGenericContext() || !genericParams)
13958+
return fixInvalidSpecialization(decl);
1395013959

1395113960
// Map the generic parameters we have over to their opened types.
1395213961
bool hasParameterPack = false;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// RUN: %empty-directory(%t/src)
2+
// RUN: split-file %s %t/src
3+
4+
/// Build the library A
5+
// RUN: %target-swift-frontend -emit-module %t/src/A.swift \
6+
// RUN: -module-name A -swift-version 5 -enable-library-evolution \
7+
// RUN: -emit-module-path %t/A.swiftmodule \
8+
// RUN: -emit-module-interface-path %t/A.swiftinterface
9+
10+
/// Build the library B
11+
// RUN: %target-swift-frontend -emit-module %t/src/B.swift \
12+
// RUN: -module-name B -swift-version 5 -enable-library-evolution \
13+
// RUN: -emit-module-path %t/B.swiftmodule \
14+
// RUN: -emit-module-interface-path %t/B.swiftinterface
15+
16+
// Build the client AB (language mode 5)
17+
// RUN: %target-swift-frontend -emit-module %t/src/ClientAB.swift \
18+
// RUN: -module-name Client -I %t -swift-version 5 \
19+
// RUN: -verify
20+
21+
// Build the client AB (language mode 6)
22+
// RUN: %target-swift-frontend -emit-module %t/src/ClientAB.swift \
23+
// RUN: -module-name Client -I %t -swift-version 6 \
24+
// RUN: -verify
25+
26+
// Build the client BA (language mode 5)
27+
// RUN: %target-swift-frontend -emit-module %t/src/ClientBA.swift \
28+
// RUN: -module-name Client -I %t -swift-version 5 \
29+
// RUN: -verify
30+
31+
// Build the client BA (language mode 6)
32+
// RUN: %target-swift-frontend -emit-module %t/src/ClientBA.swift \
33+
// RUN: -module-name Client -I %t -swift-version 6 \
34+
// RUN: -verify
35+
36+
//--- A.swift
37+
public protocol EventSource {
38+
}
39+
40+
//--- B.swift
41+
public struct Event<T> {
42+
}
43+
44+
public class EventSource<Parameter> {
45+
public var event: Event<Parameter> {
46+
fatalError()
47+
}
48+
49+
public init() {}
50+
}
51+
52+
//--- ClientAB.swift
53+
import B
54+
// Note: import order is important in this case because successful match might
55+
// mean that the other overload is not going to be attempted and we want
56+
// to attempt protocol EventSource always.
57+
import A
58+
59+
func test() {
60+
let test: B.Event<Void>
61+
test = EventSource<Void>().event
62+
print(test)
63+
}
64+
65+
//--- ClientBA.swift
66+
import B
67+
// Note: import order is important in this case because successful match might
68+
// mean that the other overload is not going to be attempted and we want
69+
// to attempt protocol EventSource always.
70+
import A
71+
72+
func test() {
73+
let test: B.Event<Void>
74+
test = EventSource<Void>().event
75+
print(test)
76+
}

0 commit comments

Comments
 (0)