Skip to content

Commit 0e09bbb

Browse files
matthewcarrolljrose-apple
authored andcommitted
[DiagnosticsQoI] SR-3359: Add a fix-it to remove @discardableResult on functions that return Void or Never (#6681)
This commit adds a fix-it to remove @discardableResult on functions that return Void or Never. The fix-it is at the warning level. A test was added to verify that the fix-it removes the @discardableResult. This issue was reported in SR-3359: https://bugs.swift.org/browse/SR-3359 Changes: TypeCheckAttr.cpp: implemented AttributeChecker::visitDiscardableResultAttr to add a fix-it to remove @discardableResult on functions returning Void or Never. DiagnosticsSema.def: Added a warning with a diagnostic message. LoggingWrappers.swift.gyb, HashedCollections.swift.gyb: Removed @discardableResult on functions returning Void. fixits-apply-all.swift, fixits-apply-all.swift.result: Added tests to verify that @discardableResult is removed from functions returning Void or Never.
1 parent f462ce7 commit 0e09bbb

File tree

6 files changed

+32
-3
lines changed

6 files changed

+32
-3
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3295,6 +3295,14 @@ NOTE(availability_protocol_requirement_here, none,
32953295
NOTE(availability_conformance_introduced_here, none,
32963296
"conformance introduced here", ())
32973297

3298+
//------------------------------------------------------------------------------
3299+
// @discardableResult
3300+
//------------------------------------------------------------------------------
3301+
3302+
WARNING(discardable_result_on_void_never_function, none,
3303+
"@discardableResult declared on a function returning %select{Never|Void}0 is unnecessary",
3304+
(bool))
3305+
32983306
//------------------------------------------------------------------------------
32993307
// Resilience diagnostics
33003308
//------------------------------------------------------------------------------

lib/Sema/TypeCheckAttr.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,6 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
726726
IGNORED_ATTR(Testable)
727727
IGNORED_ATTR(WarnUnqualifiedAccess)
728728
IGNORED_ATTR(ShowInInterface)
729-
IGNORED_ATTR(DiscardableResult)
730729
#undef IGNORED_ATTR
731730

732731
void visitAvailableAttr(AvailableAttr *attr);
@@ -763,6 +762,8 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
763762
void visitSpecializeAttr(SpecializeAttr *attr);
764763

765764
void visitVersionedAttr(VersionedAttr *attr);
765+
766+
void visitDiscardableResultAttr(DiscardableResultAttr *attr);
766767
};
767768
} // end anonymous namespace
768769

@@ -1534,6 +1535,20 @@ void AttributeChecker::visitVersionedAttr(VersionedAttr *attr) {
15341535
}
15351536
}
15361537

1538+
void AttributeChecker::visitDiscardableResultAttr(DiscardableResultAttr *attr) {
1539+
if (auto *FD = dyn_cast<FuncDecl>(D)) {
1540+
if (auto result = FD->getResultInterfaceType()) {
1541+
auto resultIsVoid = result->isVoid();
1542+
if (resultIsVoid || result->isUninhabited()) {
1543+
auto warn = diag::discardable_result_on_void_never_function;
1544+
auto diagnostic = TC.diagnose(D->getStartLoc(), warn, resultIsVoid);
1545+
diagnostic.fixItRemove(attr->getRangeWithAt());
1546+
attr->setInvalid();
1547+
}
1548+
}
1549+
}
1550+
}
1551+
15371552
void TypeChecker::checkDeclAttributes(Decl *D) {
15381553
AttributeChecker Checker(*this, D);
15391554

stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift.gyb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,6 @@ public struct ${Self}<
541541
return base.removeFirst()
542542
}
543543

544-
@discardableResult
545544
public mutating func removeFirst(_ n: Int) {
546545
Log.removeFirstN[selfType] += 1
547546
base.removeFirst(n)

stdlib/public/core/HashedCollections.swift.gyb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,6 @@ internal protocol _HashBuffer {
243243
@discardableResult
244244
mutating func removeValue(forKey key: Key) -> Value?
245245

246-
@discardableResult
247246
mutating func removeAll(keepingCapacity keepCapacity: Bool)
248247

249248
var count: Int { get }

test/FixCode/fixits-apply-all.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,7 @@ func goo(_ e: Error) {
2020

2121
@warn_unused_result(message="test message")
2222
func warn_unused_result_removal() -> Int { return 5 }
23+
24+
@discardableResult func discardableResultOnVoidFunc() {}
25+
26+
@discardableResult func discardableResultOnNeverFunc() -> Never { fatalError() }

test/FixCode/fixits-apply-all.swift.result

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,7 @@ func goo(_ e: Error) {
2020

2121

2222
func warn_unused_result_removal() -> Int { return 5 }
23+
24+
func discardableResultOnVoidFunc() {}
25+
26+
func discardableResultOnNeverFunc() -> Never { fatalError() }

0 commit comments

Comments
 (0)