Skip to content
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
8 changes: 8 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -3295,6 +3295,14 @@ NOTE(availability_protocol_requirement_here, none,
NOTE(availability_conformance_introduced_here, none,
"conformance introduced here", ())

//------------------------------------------------------------------------------
// @discardableResult
//------------------------------------------------------------------------------

WARNING(discardable_result_on_void_never_function, none,
"@discardableResult declared on a function returning %select{Never|Void}0 is unnecessary",
(bool))

//------------------------------------------------------------------------------
// Resilience diagnostics
//------------------------------------------------------------------------------
Expand Down
17 changes: 16 additions & 1 deletion lib/Sema/TypeCheckAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,6 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
IGNORED_ATTR(Testable)
IGNORED_ATTR(WarnUnqualifiedAccess)
IGNORED_ATTR(ShowInInterface)
IGNORED_ATTR(DiscardableResult)
#undef IGNORED_ATTR

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

void visitVersionedAttr(VersionedAttr *attr);

void visitDiscardableResultAttr(DiscardableResultAttr *attr);
};
} // end anonymous namespace

Expand Down Expand Up @@ -1534,6 +1535,20 @@ void AttributeChecker::visitVersionedAttr(VersionedAttr *attr) {
}
}

void AttributeChecker::visitDiscardableResultAttr(DiscardableResultAttr *attr) {
if (auto *FD = dyn_cast<FuncDecl>(D)) {
if (auto result = FD->getResultInterfaceType()) {
auto resultIsVoid = result->isVoid();
if (resultIsVoid || result->isUninhabited()) {
auto warn = diag::discardable_result_on_void_never_function;
auto diagnostic = TC.diagnose(D->getStartLoc(), warn, resultIsVoid);
diagnostic.fixItRemove(attr->getRangeWithAt());
attr->setInvalid();
}
}
}
}

void TypeChecker::checkDeclAttributes(Decl *D) {
AttributeChecker Checker(*this, D);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,6 @@ public struct ${Self}<
return base.removeFirst()
}

@discardableResult
public mutating func removeFirst(_ n: Int) {
Log.removeFirstN[selfType] += 1
base.removeFirst(n)
Expand Down
1 change: 0 additions & 1 deletion stdlib/public/core/HashedCollections.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@ internal protocol _HashBuffer {
@discardableResult
mutating func removeValue(forKey key: Key) -> Value?

@discardableResult
mutating func removeAll(keepingCapacity keepCapacity: Bool)

var count: Int { get }
Expand Down
4 changes: 4 additions & 0 deletions test/FixCode/fixits-apply-all.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ func goo(_ e: Error) {

@warn_unused_result(message="test message")
func warn_unused_result_removal() -> Int { return 5 }

@discardableResult func discardableResultOnVoidFunc() {}

@discardableResult func discardableResultOnNeverFunc() -> Never { fatalError() }
4 changes: 4 additions & 0 deletions test/FixCode/fixits-apply-all.swift.result
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ func goo(_ e: Error) {


func warn_unused_result_removal() -> Int { return 5 }

func discardableResultOnVoidFunc() {}

func discardableResultOnNeverFunc() -> Never { fatalError() }