Skip to content

Commit d912e12

Browse files
committed
[ResultBuilders] Use new fix to detect and diagnose use of return statements in a result builder body
1 parent 03ede74 commit d912e12

File tree

4 files changed

+32
-5
lines changed

4 files changed

+32
-5
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,7 +1671,7 @@ ConstraintSystem::matchResultBuilder(
16711671
if (InvalidResultBuilderBodies.count(fn)) {
16721672
(void)recordFix(
16731673
IgnoreInvalidResultBuilderBody::duringConstraintGeneration(
1674-
*this, getConstraintLocator(fn.getBody())));
1674+
*this, getConstraintLocator(fn.getAbstractClosureExpr())));
16751675
return getTypeMatchSuccess();
16761676
}
16771677

@@ -1690,13 +1690,25 @@ ConstraintSystem::matchResultBuilder(
16901690
return getTypeMatchFailure(locator);
16911691

16921692
if (recordFix(IgnoreInvalidResultBuilderBody::duringPreCheck(
1693-
*this, getConstraintLocator(fn.getBody()))))
1693+
*this, getConstraintLocator(fn.getAbstractClosureExpr()))))
16941694
return getTypeMatchFailure(locator);
16951695

16961696
return getTypeMatchSuccess();
16971697
}
16981698

16991699
case ResultBuilderBodyPreCheck::HasReturnStmt:
1700+
// Diagnostic mode means that solver couldn't reach any viable
1701+
// solution, so let's diagnose presence of a `return` statement
1702+
// in the closure body.
1703+
if (shouldAttemptFixes()) {
1704+
if (recordFix(IgnoreResultBuilderWithReturnStmts::create(
1705+
*this, builderType,
1706+
getConstraintLocator(fn.getAbstractClosureExpr()))))
1707+
return getTypeMatchFailure(locator);
1708+
1709+
return getTypeMatchSuccess();
1710+
}
1711+
17001712
// If the body has a return statement, suppress the transform but
17011713
// continue solving the constraint system.
17021714
return None;
@@ -1744,7 +1756,7 @@ ConstraintSystem::matchResultBuilder(
17441756

17451757
if (recordFix(
17461758
IgnoreInvalidResultBuilderBody::duringConstraintGeneration(
1747-
*this, getConstraintLocator(fn.getBody()))))
1759+
*this, getConstraintLocator(fn.getAbstractClosureExpr()))))
17481760
return getTypeMatchFailure(locator);
17491761

17501762
return getTypeMatchSuccess();

lib/Sema/CSBindings.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1424,7 +1424,7 @@ TypeVariableBinding::fixForHole(ConstraintSystem &cs) const {
14241424
// If the whole body is being ignored due to a pre-check failure,
14251425
// let's not record a fix about result type since there is
14261426
// just not enough context to infer it without a body.
1427-
if (cs.hasFixFor(cs.getConstraintLocator(closure->getBody()),
1427+
if (cs.hasFixFor(cs.getConstraintLocator(closure),
14281428
FixKind::IgnoreInvalidResultBuilderBody))
14291429
return None;
14301430

lib/Sema/CSFix.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1579,7 +1579,7 @@ bool IgnoreInvalidResultBuilderBody::diagnose(const Solution &solution,
15791579
return true; // Already diagnosed by `matchResultBuilder`.
15801580
}
15811581

1582-
auto *S = getAnchor().get<Stmt *>();
1582+
auto *S = castToExpr<ClosureExpr>(getAnchor())->getBody();
15831583

15841584
class PreCheckWalker : public ASTWalker {
15851585
DeclContext *DC;

test/Constraints/result_builder_diags.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,21 @@ struct MyTuplifiedStruct {
286286
}
287287
}
288288

289+
func test_invalid_return_type_in_body() {
290+
tuplify(true) { _ -> (Void, Int) in
291+
tuplify(false) { condition in
292+
if condition {
293+
return 42 // expected-error {{application of result builder 'TupleBuilder' disabled by explicit 'return' statement}}
294+
// expected-note@-1 {{remove 'return' statements to apply the result builder}} {{9-16=}}
295+
} else {
296+
1
297+
}
298+
}
299+
300+
42
301+
}
302+
}
303+
289304
// Check that we're performing syntactic use diagnostics.
290305
func acceptMetatype<T>(_: T.Type) -> Bool { true }
291306

0 commit comments

Comments
 (0)