Skip to content

Commit 942866d

Browse files
committed
[CS] Introduce performSyntacticDiagnosticsForTarget
Add a function that deals with invoking syntactic diagnostics for all the expressions involved in a SolutionApplicationTarget. Resolves SR-13260 Resolves rdar://65903005
1 parent b61cfea commit 942866d

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed

lib/Sema/ConstraintSystem.h

Lines changed: 7 additions & 0 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.
@@ -5288,6 +5290,11 @@ bool isKnownKeyPathDecl(ASTContext &ctx, ValueDecl *decl);
52885290
/// statements that could produce non-void result.
52895291
bool hasExplicitResult(ClosureExpr *closure);
52905292

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

52935300
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)