mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Sema]: minor improvements to unused expression result diagnostics
Previously we would emit a diagnostic in cases in which a throwing function returning a structurally-unihabited type was called within an optional try expression. Such cases can never produce a return value, so suppress the existing diagnostic.
This commit is contained in:
@@ -1823,9 +1823,14 @@ static bool isDiscardableType(Type type) {
|
|||||||
if (auto *expansion = type->getAs<PackExpansionType>())
|
if (auto *expansion = type->getAs<PackExpansionType>())
|
||||||
return isDiscardableType(expansion->getPatternType());
|
return isDiscardableType(expansion->getPatternType());
|
||||||
|
|
||||||
return (type->hasError() ||
|
if (type->hasError())
|
||||||
type->isUninhabited() ||
|
return true;
|
||||||
type->lookThroughAllOptionalTypes()->isVoid());
|
|
||||||
|
// Look through optionality and check if the type is either `Void` or
|
||||||
|
// 'structurally uninhabited'. Treat either as discardable.
|
||||||
|
auto nonOptionalType = type->lookThroughAllOptionalTypes();
|
||||||
|
return (nonOptionalType->isStructurallyUninhabited() ||
|
||||||
|
nonOptionalType->isVoid());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void diagnoseIgnoredLiteral(ASTContext &Ctx, LiteralExpr *LE) {
|
static void diagnoseIgnoredLiteral(ASTContext &Ctx, LiteralExpr *LE) {
|
||||||
@@ -1972,9 +1977,8 @@ void TypeChecker::checkIgnoredExpr(Expr *E) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the result of this expression is of type "Never" or "()"
|
// If the result of this expression is either "structurally uninhabited" or
|
||||||
// (the latter potentially wrapped in optionals) then it is
|
// `Void`, (potentially wrapped in optionals) then it is safe to ignore.
|
||||||
// safe to ignore.
|
|
||||||
if (isDiscardableType(valueE->getType()))
|
if (isDiscardableType(valueE->getType()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
73
test/Sema/diag_implicit_discardable.swift
Normal file
73
test/Sema/diag_implicit_discardable.swift
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
// RUN: %target-typecheck-verify-swift
|
||||||
|
|
||||||
|
struct MyError: Error {}
|
||||||
|
enum MyNever {}
|
||||||
|
|
||||||
|
func never_throws() throws -> Never { throw MyError() }
|
||||||
|
func uninhabited_throws() throws -> (Int, MyNever) { throw MyError () }
|
||||||
|
func almost_uninhabited_throws() throws -> (Int, Never?) { throw MyError () }
|
||||||
|
func int_throws() throws -> Int { throw MyError() }
|
||||||
|
func void_throws() throws {}
|
||||||
|
|
||||||
|
func maybe_never() -> Never? { nil }
|
||||||
|
func maybe_uninhabited() -> (Int, MyNever)? { nil }
|
||||||
|
func maybe_maybe_uninhabited() -> (Int, Never)?? { nil }
|
||||||
|
func maybe_void() -> Void? { nil }
|
||||||
|
func maybe_maybe_void() -> Void?? { nil }
|
||||||
|
func looks_uninhabited_if_you_squint() -> (Int, Never?)? { nil }
|
||||||
|
|
||||||
|
// MARK: - Tests
|
||||||
|
|
||||||
|
func test_try() throws {
|
||||||
|
try never_throws()
|
||||||
|
try uninhabited_throws()
|
||||||
|
try almost_uninhabited_throws()
|
||||||
|
// expected-warning @-1 {{result of call to 'almost_uninhabited_throws()' is unused}}
|
||||||
|
try int_throws()
|
||||||
|
// expected-warning @-1 {{result of call to 'int_throws()' is unused}}
|
||||||
|
try void_throws()
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_force_try() throws {
|
||||||
|
try! never_throws()
|
||||||
|
try! uninhabited_throws()
|
||||||
|
try! almost_uninhabited_throws()
|
||||||
|
// expected-warning @-1 {{result of call to 'almost_uninhabited_throws()' is unused}}
|
||||||
|
try! int_throws()
|
||||||
|
// expected-warning @-1 {{result of call to 'int_throws()' is unused}}
|
||||||
|
try! void_throws()
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_optional_try() throws {
|
||||||
|
try? never_throws()
|
||||||
|
try? uninhabited_throws()
|
||||||
|
try? almost_uninhabited_throws()
|
||||||
|
// expected-warning @-1 {{result of 'try?' is unused}}
|
||||||
|
try? int_throws()
|
||||||
|
// expected-warning @-1 {{result of 'try?' is unused}}
|
||||||
|
try? void_throws()
|
||||||
|
}
|
||||||
|
|
||||||
|
func test_implicitly_discardable() {
|
||||||
|
maybe_never()
|
||||||
|
maybe_uninhabited()
|
||||||
|
maybe_maybe_uninhabited()
|
||||||
|
maybe_void()
|
||||||
|
maybe_maybe_void()
|
||||||
|
looks_uninhabited_if_you_squint()
|
||||||
|
// expected-warning @-1 {{result of call to 'looks_uninhabited_if_you_squint()' is unused}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/swiftlang/swift/issues/85092
|
||||||
|
|
||||||
|
func test_85092() {
|
||||||
|
struct MyError: Error {}
|
||||||
|
|
||||||
|
func f() throws -> Never {
|
||||||
|
throw MyError()
|
||||||
|
}
|
||||||
|
|
||||||
|
func g() {
|
||||||
|
try? f()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user