Skip to content

Commit 23615ba

Browse files
committed
[Function builders] Add support for "if #available".
Availability checks in if statements don't need any actual semantic checking, so enable them within function builders.
1 parent 7217cfa commit 23615ba

File tree

3 files changed

+82
-3
lines changed

3 files changed

+82
-3
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,9 @@ class BuilderClosureRewriter
831831
auto condition = ifStmt->getCond();
832832
for (auto &condElement : condition) {
833833
switch (condElement.getKind()) {
834+
case StmtConditionElement::CK_Availability:
835+
continue;
836+
834837
case StmtConditionElement::CK_Boolean: {
835838
auto condExpr = condElement.getBoolean();
836839
auto finalCondExpr = rewriteExpr(condExpr);
@@ -846,7 +849,6 @@ class BuilderClosureRewriter
846849
}
847850

848851
case StmtConditionElement::CK_PatternBinding:
849-
case StmtConditionElement::CK_Availability:
850852
llvm_unreachable("unhandled statement condition");
851853
}
852854
}

lib/Sema/CSGen.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3801,11 +3801,11 @@ Type ConstraintSystem::generateConstraints(Pattern *pattern,
38013801
bool ConstraintSystem::canGenerateConstraints(StmtCondition condition) {
38023802
for (const auto &element : condition) {
38033803
switch (element.getKind()) {
3804+
case StmtConditionElement::CK_Availability:
38043805
case StmtConditionElement::CK_Boolean:
38053806
continue;
38063807

38073808
case StmtConditionElement::CK_PatternBinding:
3808-
case StmtConditionElement::CK_Availability:
38093809
return false;
38103810
}
38113811
}
@@ -3823,6 +3823,10 @@ bool ConstraintSystem::generateConstraints(StmtCondition condition,
38233823

38243824
for (const auto &condElement : condition) {
38253825
switch (condElement.getKind()) {
3826+
case StmtConditionElement::CK_Availability:
3827+
// Nothing to do here.
3828+
continue;
3829+
38263830
case StmtConditionElement::CK_Boolean: {
38273831
Expr *condExpr = condElement.getBoolean();
38283832
condExpr = generateConstraints(condExpr, dc);
@@ -3838,7 +3842,6 @@ bool ConstraintSystem::generateConstraints(StmtCondition condition,
38383842
}
38393843

38403844
case StmtConditionElement::CK_PatternBinding:
3841-
case StmtConditionElement::CK_Availability:
38423845
llvm_unreachable("unhandled statement condition");
38433846
}
38443847
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// RUN: %target-typecheck-verify-swift -target x86_64-apple-macosx10.50
2+
3+
// REQUIRES: OS=macosx
4+
5+
enum Either<T,U> {
6+
case first(T)
7+
case second(U)
8+
}
9+
10+
@_functionBuilder
11+
struct TupleBuilder {
12+
static func buildBlock<T1>(_ t1: T1) -> (T1) {
13+
return (t1)
14+
}
15+
16+
static func buildBlock<T1, T2>(_ t1: T1, _ t2: T2) -> (T1, T2) {
17+
return (t1, t2)
18+
}
19+
20+
static func buildBlock<T1, T2, T3>(_ t1: T1, _ t2: T2, _ t3: T3)
21+
-> (T1, T2, T3) {
22+
return (t1, t2, t3)
23+
}
24+
25+
static func buildBlock<T1, T2, T3, T4>(_ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4)
26+
-> (T1, T2, T3, T4) {
27+
return (t1, t2, t3, t4)
28+
}
29+
30+
static func buildBlock<T1, T2, T3, T4, T5>(
31+
_ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4, _ t5: T5
32+
) -> (T1, T2, T3, T4, T5) {
33+
return (t1, t2, t3, t4, t5)
34+
}
35+
36+
static func buildDo<T>(_ value: T) -> T { return value }
37+
static func buildIf<T>(_ value: T?) -> T? { return value }
38+
39+
static func buildEither<T,U>(first value: T) -> Either<T,U> {
40+
return .first(value)
41+
}
42+
static func buildEither<T,U>(second value: U) -> Either<T,U> {
43+
return .second(value)
44+
}
45+
}
46+
47+
func tuplify<T>(_ cond: Bool, @TupleBuilder body: (Bool) -> T) {
48+
print(body(cond))
49+
}
50+
51+
@available(OSX, introduced: 10.9)
52+
func globalFuncAvailableOn10_9() -> Int { return 9 }
53+
54+
@available(OSX, introduced: 10.51)
55+
func globalFuncAvailableOn10_51() -> Int { return 10 }
56+
57+
@available(OSX, introduced: 10.52)
58+
func globalFuncAvailableOn10_52() -> Int { return 11 }
59+
60+
tuplify(true) { cond in
61+
globalFuncAvailableOn10_9()
62+
if #available(OSX 10.51, *) {
63+
globalFuncAvailableOn10_51()
64+
tuplify(false) { cond2 in
65+
if cond, #available(OSX 10.52, *) {
66+
cond2
67+
globalFuncAvailableOn10_52()
68+
} else {
69+
globalFuncAvailableOn10_52() // expected-error{{'globalFuncAvailableOn10_52()' is only available in macOS 10.52 or newer}}
70+
// expected-note@-1{{add 'if #available' version check}}
71+
}
72+
}
73+
}
74+
}

0 commit comments

Comments
 (0)