Skip to content

🍒 [5.7] Sema, DiagQoI: Fix and tailor diagnosis of explicit closure result type conflicts #59596

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,12 @@ FIXIT(insert_closure_return_type_placeholder,
NOTE(use_of_anon_closure_param,none,
"anonymous closure parameter %0 is used here", (Identifier))

ERROR(incorrect_explicit_closure_result,none,
ERROR(incorrect_explicit_closure_result_vs_contextual_type,none,
"declared closure result %0 is incompatible with contextual type %1",
(Type, Type))
ERROR(incorrect_explicit_closure_result_vs_return_type,none,
"declared closure result %0 is incompatible with return type %1",
(Type, Type))

ERROR(unsupported_closure_attr,none,
"%select{attribute |}0 '%1' is not supported on a closure",
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Sema/ConstraintLocatorPathElts.def
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ SIMPLE_LOCATOR_PATH_ELT(AutoclosureResult)
/// The result of a closure.
SIMPLE_LOCATOR_PATH_ELT(ClosureResult)

/// FIXME: Misleading name: this locator is used only for single-expression
/// closure returns.
///
/// The type of a closure body.
CUSTOM_LOCATOR_PATH_ELT(ClosureBody)

Expand Down
25 changes: 20 additions & 5 deletions lib/Sema/CSDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2318,17 +2318,32 @@ bool ContextualFailure::diagnoseAsError() {
auto toType = getToType();

Diag<Type, Type> diagnostic;
switch (path.back().getKind()) {

const auto lastPathEltKind = path.back().getKind();
switch (lastPathEltKind) {
case ConstraintLocator::ClosureBody:
case ConstraintLocator::ClosureResult: {
auto *closure = castToExpr<ClosureExpr>(getRawAnchor());
if (closure->hasExplicitResultType() &&
closure->getExplicitResultTypeRepr()) {
auto resultRepr = closure->getExplicitResultTypeRepr();
emitDiagnosticAt(resultRepr->getStartLoc(),
diag::incorrect_explicit_closure_result, fromType,
toType)
.fixItReplace(resultRepr->getSourceRange(), toType.getString());

if (lastPathEltKind == ConstraintLocator::ClosureBody) {
// The conflict is between the return type and the declared result type.
emitDiagnosticAt(resultRepr->getStartLoc(),
diag::incorrect_explicit_closure_result_vs_return_type,
toType, fromType)
.fixItReplace(resultRepr->getSourceRange(), fromType.getString());
} else {
// The conflict is between the declared result type and the
// contextual type.
emitDiagnosticAt(
resultRepr->getStartLoc(),
diag::incorrect_explicit_closure_result_vs_contextual_type,
fromType, toType)
.fixItReplace(resultRepr->getSourceRange(), toType.getString());
}

return true;
}

Expand Down
2 changes: 1 addition & 1 deletion test/Constraints/closures.swift
Original file line number Diff line number Diff line change
Expand Up @@ -996,7 +996,7 @@ func rdar52204414() {
let _: () -> Void = { return 42 }
// expected-error@-1 {{cannot convert value of type 'Int' to closure result type 'Void'}}
let _ = { () -> Void in return 42 }
// expected-error@-1 {{declared closure result 'Int' is incompatible with contextual type 'Void'}}
// expected-error@-1 {{declared closure result 'Void' is incompatible with return type 'Int'}} {{19-23=Int}}
}

// SR-12291 - trailing closure is used as an argument to the last (positionally) parameter.
Expand Down
2 changes: 1 addition & 1 deletion test/Sema/substring_to_string_conversion_swift4.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ do {

// CTP_ClosureResult
do {
[ss].map { (x: Substring) -> String in x } // expected-error {{declared closure result 'Substring' is incompatible with contextual type 'String'}}
[ss].map { (x: Substring) -> String in x } // expected-error {{declared closure result 'String' is incompatible with return type 'Substring'}} {{32-38=Substring}}
}

// CTP_ArrayElement
Expand Down