Skip to content

Commit 49710ab

Browse files
authored
Merge pull request #24587 from xedin/diag-extraneous-return-via-fixes
[ConstraintSystem] Detect and diagnose extraneous returns from void f…
2 parents df53d4c + 4f63c4a commit 49710ab

File tree

6 files changed

+57
-1
lines changed

6 files changed

+57
-1
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2733,3 +2733,9 @@ bool InvalidUseOfAddressOf::diagnoseAsError() {
27332733
emitDiagnostic(anchor->getSrc()->getLoc(), diag::extraneous_address_of);
27342734
return true;
27352735
}
2736+
2737+
bool ExtraneousReturnFailure::diagnoseAsError() {
2738+
auto *anchor = getAnchor();
2739+
emitDiagnostic(anchor->getLoc(), diag::cannot_return_value_from_void_func);
2740+
return true;
2741+
}

lib/Sema/CSDiagnostics.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,21 @@ class InvalidUseOfAddressOf final : public FailureDiagnostic {
11601160
bool diagnoseAsError() override;
11611161
};
11621162

1163+
/// Diagnose an attempt return something from a function which
1164+
/// doesn't have a return type specified e.g.
1165+
///
1166+
/// ```swift
1167+
/// func foo() { return 42 }
1168+
/// ```
1169+
class ExtraneousReturnFailure final : public FailureDiagnostic {
1170+
public:
1171+
ExtraneousReturnFailure(Expr *root, ConstraintSystem &cs,
1172+
ConstraintLocator *locator)
1173+
: FailureDiagnostic(root, cs, locator) {}
1174+
1175+
bool diagnoseAsError() override;
1176+
};
1177+
11631178
} // end namespace constraints
11641179
} // end namespace swift
11651180

lib/Sema/CSFix.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,3 +494,13 @@ RemoveAddressOf *RemoveAddressOf::create(ConstraintSystem &cs,
494494
ConstraintLocator *locator) {
495495
return new (cs.getAllocator()) RemoveAddressOf(cs, locator);
496496
}
497+
498+
bool RemoveReturn::diagnose(Expr *root, bool asNote) const {
499+
ExtraneousReturnFailure failure(root, getConstraintSystem(), getLocator());
500+
return failure.diagnose(asNote);
501+
}
502+
503+
RemoveReturn *RemoveReturn::create(ConstraintSystem &cs,
504+
ConstraintLocator *locator) {
505+
return new (cs.getAllocator()) RemoveReturn(cs, locator);
506+
}

lib/Sema/CSFix.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ enum class FixKind : uint8_t {
149149
/// Allow an invalid reference to a member declaration as part
150150
/// of a key path component.
151151
AllowInvalidRefInKeyPath,
152+
153+
/// Remove `return` or default last expression of single expression
154+
/// function to `Void` to conform to expected result type.
155+
RemoveReturn,
152156
};
153157

154158
class ConstraintFix {
@@ -870,6 +874,18 @@ class RemoveAddressOf final : public ConstraintFix {
870874
ConstraintLocator *locator);
871875
};
872876

877+
class RemoveReturn final : public ConstraintFix {
878+
RemoveReturn(ConstraintSystem &cs, ConstraintLocator *locator)
879+
: ConstraintFix(cs, FixKind::RemoveReturn, locator) {}
880+
881+
public:
882+
std::string getName() const override { return "remove or omit return type"; }
883+
884+
bool diagnose(Expr *root, bool asNote = false) const override;
885+
886+
static RemoveReturn *create(ConstraintSystem &cs, ConstraintLocator *locator);
887+
};
888+
873889
} // end namespace constraints
874890
} // end namespace swift
875891

lib/Sema/CSSimplify.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2129,6 +2129,14 @@ bool ConstraintSystem::repairFailures(
21292129
}
21302130

21312131
case ConstraintLocator::ContextualType: {
2132+
auto purpose = getContextualTypePurpose();
2133+
if (rhs->isVoid() &&
2134+
(purpose == CTP_ReturnStmt || purpose == CTP_ReturnSingleExpr)) {
2135+
conversionsOrFixes.push_back(
2136+
RemoveReturn::create(*this, getConstraintLocator(locator)));
2137+
return true;
2138+
}
2139+
21322140
// If both types are key path, the only differences
21332141
// between them are mutability and/or root, value type mismatch.
21342142
if (isKnownKeyPathType(lhs) && isKnownKeyPathType(rhs)) {
@@ -6514,6 +6522,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
65146522
}
65156523

65166524
case FixKind::InsertCall:
6525+
case FixKind::RemoveReturn:
65176526
case FixKind::RemoveAddressOf:
65186527
case FixKind::SkipSameTypeRequirement:
65196528
case FixKind::SkipSuperclassRequirement:

test/Parse/omit_return.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,7 @@ var fvs_explicit: String {
936936
var fvs_explicitClosure: () -> Void {
937937
get { return { print("howdy") } }
938938
set {
939-
return { print("howdy") } // expected-error {{function produces expected type '()'; did you mean to call it with '()'?}}
939+
return { print("howdy") } // expected-error {{unexpected non-void return value in void function}}
940940
}
941941
}
942942

0 commit comments

Comments
 (0)