Skip to content

Commit a176d64

Browse files
authored
Merge pull request #33041 from hamishknight/to-no-avail-5.3
2 parents db53a37 + 942866d commit a176d64

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

lib/Sema/ConstraintSystem.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,13 +1206,15 @@ struct DynamicCallableMethods {
12061206
/// Describes the target to which a constraint system's solution can be
12071207
/// applied.
12081208
class SolutionApplicationTarget {
1209+
public:
12091210
enum class Kind {
12101211
expression,
12111212
function,
12121213
stmtCondition,
12131214
caseLabelItem,
12141215
} kind;
12151216

1217+
private:
12161218
union {
12171219
struct {
12181220
/// The expression being type-checked.
@@ -1418,6 +1420,12 @@ class SolutionApplicationTarget {
14181420
/// For a pattern initialization target, retrieve the contextual pattern.
14191421
ContextualPattern getContextualPattern() const;
14201422

1423+
/// Whether this target is for a for-in statement.
1424+
bool isForEachStmt() const {
1425+
return kind == Kind::expression &&
1426+
getExprContextualTypePurpose() == CTP_ForEachStmt;
1427+
}
1428+
14211429
/// Whether this is an initialization for an Optional.Some pattern.
14221430
bool isOptionalSomePatternInit() const {
14231431
return kind == Kind::expression &&
@@ -1466,14 +1474,12 @@ class SolutionApplicationTarget {
14661474
}
14671475

14681476
const ForEachStmtInfo &getForEachStmtInfo() const {
1469-
assert(kind == Kind::expression);
1470-
assert(expression.contextualPurpose == CTP_ForEachStmt);
1477+
assert(isForEachStmt());
14711478
return expression.forEachStmt;
14721479
}
14731480

14741481
ForEachStmtInfo &getForEachStmtInfo() {
1475-
assert(kind == Kind::expression);
1476-
assert(expression.contextualPurpose == CTP_ForEachStmt);
1482+
assert(isForEachStmt());
14771483
return expression.forEachStmt;
14781484
}
14791485

@@ -5284,6 +5290,11 @@ bool isKnownKeyPathDecl(ASTContext &ctx, ValueDecl *decl);
52845290
/// statements that could produce non-void result.
52855291
bool hasExplicitResult(ClosureExpr *closure);
52865292

5293+
/// Emit diagnostics for syntactic restrictions within a given solution
5294+
/// application target.
5295+
void performSyntacticDiagnosticsForTarget(
5296+
const SolutionApplicationTarget &target, bool isExprStmt);
5297+
52875298
} // end namespace constraints
52885299

52895300
template<typename ...Args>

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2008,6 +2008,31 @@ bool GenericRequirementsCheckListener::diagnoseUnsatisfiedRequirement(
20082008
return false;
20092009
}
20102010

2011+
void constraints::performSyntacticDiagnosticsForTarget(
2012+
const SolutionApplicationTarget &target, bool isExprStmt) {
2013+
auto *dc = target.getDeclContext();
2014+
switch (target.kind) {
2015+
case SolutionApplicationTarget::Kind::expression: {
2016+
// First emit diagnostics for the main expression.
2017+
performSyntacticExprDiagnostics(target.getAsExpr(), dc, isExprStmt);
2018+
2019+
// If this is a for-in statement, we also need to check the where clause if
2020+
// present.
2021+
if (target.isForEachStmt()) {
2022+
if (auto *whereExpr = target.getForEachStmtInfo().whereExpr)
2023+
performSyntacticExprDiagnostics(whereExpr, dc, /*isExprStmt*/ false);
2024+
}
2025+
return;
2026+
}
2027+
case SolutionApplicationTarget::Kind::function:
2028+
case SolutionApplicationTarget::Kind::stmtCondition:
2029+
case SolutionApplicationTarget::Kind::caseLabelItem:
2030+
// Nothing to do for these.
2031+
return;
2032+
}
2033+
llvm_unreachable("Unhandled case in switch!");
2034+
}
2035+
20112036
#pragma mark High-level entry points
20122037
Type TypeChecker::typeCheckExpression(Expr *&expr, DeclContext *dc,
20132038
TypeLoc convertType,
@@ -2122,7 +2147,7 @@ TypeChecker::typeCheckExpression(
21222147
// expression now.
21232148
if (!cs.shouldSuppressDiagnostics()) {
21242149
bool isExprStmt = options.contains(TypeCheckExprFlags::IsExprStmt);
2125-
performSyntacticExprDiagnostics(result, dc, isExprStmt);
2150+
performSyntacticDiagnosticsForTarget(*resultTarget, isExprStmt);
21262151
}
21272152

21282153
resultTarget->setExpr(result);

test/Constraints/availability.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,12 @@ func test_contextual_member_with_availability() {
3434

3535
_ = Test(.foo) // Ok
3636
}
37+
38+
@available(*, unavailable)
39+
func unavailableFunction(_ x: Int) -> Bool { true } // expected-note {{'unavailableFunction' has been explicitly marked unavailable here}}
40+
41+
// SR-13260: Availability checking not working in the where clause of a for
42+
// loop.
43+
func sr13260(_ arr: [Int]) {
44+
for x in arr where unavailableFunction(x) {} // expected-error {{'unavailableFunction' is unavailable}}
45+
}

0 commit comments

Comments
 (0)