Skip to content

Commit bc9d233

Browse files
committed
[ConstraintSystem] Detect and diagnose extraneous returns from void functions
Diagnose an attempt return something from a function which doesn't have a return type specified e.g. ```swift func foo() { return 42 } ``` (cherry picked from commit 4f63c4a)
1 parent 35c0228 commit bc9d233

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
@@ -2676,3 +2676,9 @@ bool InvalidUseOfAddressOf::diagnoseAsError() {
26762676
emitDiagnostic(anchor->getSrc()->getLoc(), diag::extraneous_address_of);
26772677
return true;
26782678
}
2679+
2680+
bool ExtraneousReturnFailure::diagnoseAsError() {
2681+
auto *anchor = getAnchor();
2682+
emitDiagnostic(anchor->getLoc(), diag::cannot_return_value_from_void_func);
2683+
return true;
2684+
}

lib/Sema/CSDiagnostics.h

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

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

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
@@ -2087,6 +2087,14 @@ bool ConstraintSystem::repairFailures(
20872087
}
20882088

20892089
case ConstraintLocator::ContextualType: {
2090+
auto purpose = getContextualTypePurpose();
2091+
if (rhs->isVoid() &&
2092+
(purpose == CTP_ReturnStmt || purpose == CTP_ReturnSingleExpr)) {
2093+
conversionsOrFixes.push_back(
2094+
RemoveReturn::create(*this, getConstraintLocator(locator)));
2095+
return true;
2096+
}
2097+
20902098
// If both types are key path, the only differences
20912099
// between them are mutability and/or root, value type mismatch.
20922100
if (isKnownKeyPathType(lhs) && isKnownKeyPathType(rhs)) {
@@ -6482,6 +6490,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
64826490
}
64836491

64846492
case FixKind::InsertCall:
6493+
case FixKind::RemoveReturn:
64856494
case FixKind::RemoveAddressOf:
64866495
case FixKind::SkipSameTypeRequirement:
64876496
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)