An unused @ discardableResult should not throw an error (#6785)
A function marked with @discardableResult should not throw an error if
its returning closure is unused.
Fixes SR-2948.
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index 230d023..e21228f 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -1082,9 +1082,22 @@
// TODO: What about tuples which contain functions by-value that are
// dead?
if (E->getType()->is<AnyFunctionType>()) {
- diagnose(E->getLoc(), diag::expression_unused_function)
- .highlight(E->getSourceRange());
- return;
+ bool isDiscardable = false;
+ if (auto *Fn = dyn_cast<ApplyExpr>(E)) {
+ if (auto *declRef = dyn_cast<DeclRefExpr>(Fn->getFn())) {
+ if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(declRef->getDecl())) {
+ if (funcDecl->getAttrs().hasAttribute<DiscardableResultAttr>()) {
+ isDiscardable = true;
+ }
+ }
+ }
+ }
+
+ if (!isDiscardable) {
+ diagnose(E->getLoc(), diag::expression_unused_function)
+ .highlight(E->getSourceRange());
+ return;
+ }
}
// If the result of this expression is of type "Never" or "()"
diff --git a/test/attr/attr_discardableResult.swift b/test/attr/attr_discardableResult.swift
index 151e55f..95c50dc 100644
--- a/test/attr/attr_discardableResult.swift
+++ b/test/attr/attr_discardableResult.swift
@@ -176,3 +176,9 @@
s1?.f2Optional() // expected-warning {{result of call to 'f2Optional()' is unused}}
s1!.f2Optional() // expected-warning {{result of call to 'f2Optional()' is unused}}
}
+
+@discardableResult func SR2948 (_ closure: @escaping ()->()) -> (()->()) {
+ closure()
+ return closure
+}
+SR2948({}) // okay