-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[AST][SILOptimizer]: unify missing return diagnostics in some cases #75574
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// RUN: %target-swift-frontend %s -emit-sil -verify | ||
|
||
// MARK: Relocated Test Cases | ||
// Missing return diagnostics used to also be implemented during parsing/AST | ||
// construction in addition to the SIL passes. Some existing test cases have | ||
// been moved here after removing the earlier phases' diagnostics in favor of | ||
// those implemented via the SIL passes. | ||
|
||
// MARK: `decl/subscript/subscripting` | ||
|
||
struct MissingGetterSubscript1 { | ||
subscript (i : Int) -> Int { | ||
} // expected-error {{missing return in getter expected to return 'Int'}} | ||
} | ||
|
||
// MARK: `decl/var/properties` | ||
|
||
struct X {} | ||
|
||
var x13: X {} // expected-error {{missing return in getter expected to return 'X'}} | ||
|
||
struct X14 {} | ||
extension X14 { | ||
var x14: X { | ||
} // expected-error {{missing return in getter expected to return 'X'}} | ||
} | ||
|
||
// https://github.com/apple/swift/issues/57936 | ||
|
||
enum E1_57936 { | ||
var foo: Int {} // expected-error{{missing return in getter expected to return 'Int'}} | ||
} | ||
|
||
enum E2_57936<T> { | ||
var foo: T {} // expected-error{{missing return in getter expected to return 'T'}} | ||
} | ||
|
||
// MARK: `decl/var/result_builders` | ||
|
||
@resultBuilder | ||
struct Maker { | ||
static func buildBlock() -> Int { 42 } | ||
} | ||
|
||
@Maker | ||
var globalWithEmptyImplicitGetter: Int {} | ||
|
||
// MARK: `Parse/omit_return` | ||
|
||
var fv_nop: () { | ||
} | ||
|
||
var fv_missing: String { | ||
} // expected-error {{missing return in getter expected to return 'String'}} | ||
|
||
enum S_nop { | ||
subscript() -> () { | ||
} | ||
} | ||
|
||
enum S_missing { | ||
subscript() -> String { | ||
} // expected-error {{missing return in getter expected to return 'String'}} | ||
} | ||
|
||
// MARK: `Sema/generic-subscript` | ||
|
||
struct S_generic_subscript_missing_return { | ||
subscript<Value>(x: Int) -> Value { | ||
} // expected-error {{missing return in getter expected to return 'Value'}} | ||
} | ||
|
||
// MARK: New Test Cases | ||
|
||
enum MyEmptyType {} | ||
extension MyEmptyType { | ||
var i: Int {} // expected-error{{missing return in getter expected to return 'Int'}} | ||
var n: MyEmptyType {} // expected-error{{getter with uninhabited return type 'MyEmptyType' is missing call to another never-returning function on all paths}} | ||
|
||
static subscript<A>(root: MyEmptyType) -> A {} | ||
|
||
subscript(_ e: MyEmptyType) -> Int {} | ||
subscript<T>(_ e: MyEmptyType) -> T {} | ||
subscript(_ i: Int) -> Int {} // expected-error{{missing return in getter expected to return 'Int'}} | ||
subscript<T>(_ p: Int) -> T {} // expected-error{{missing return in getter expected to return 'T'}} | ||
subscript(_ i: Int) -> Self {} // expected-error{{getter with uninhabited return type 'MyEmptyType' is missing call to another never-returning function on all paths}} | ||
subscript(_ s: Self) -> Self {} | ||
|
||
static func unreachable_static_implicit_return(_ e: MyEmptyType) -> Int {} | ||
func unreachable(_ e: MyEmptyType) -> Int { // expected-note{{'e' is of type 'MyEmptyType' which cannot be constructed because it is an enum with no cases}} | ||
42 // expected-warning{{will never be executed}} | ||
} | ||
|
||
// FIXME: should these produce warnings since they implicity take an uninhabited 'self' param? | ||
func implicitly_unreachable() { _ = 42 } | ||
func implicitly_unreachable_implicit_return() -> Int { 42 } | ||
} | ||
|
||
extension Never { | ||
var i: Int {} // expected-error{{missing return in getter expected to return 'Int'}} | ||
var n: Never {} // expected-error{{getter with uninhabited return type 'Never' is missing call to another never-returning function on all paths}} | ||
|
||
static subscript<A>(root: Never) -> A {} | ||
|
||
subscript(_ n: Never) -> Int {} | ||
subscript<T>(_ e: Never) -> T {} | ||
subscript(_ i: Int) -> Int {} // expected-error{{missing return in getter expected to return 'Int'}} | ||
subscript<T>(_ p: Int) -> T {} // expected-error{{missing return in getter expected to return 'T'}} | ||
subscript(_ i: Int) -> Self {} // expected-error{{getter with uninhabited return type 'Never' is missing call to another never-returning function on all paths}} | ||
subscript(_ s: Self) -> Self {} | ||
|
||
static func unreachable_static_implicit_return(_ n: Never) -> Int {} | ||
func unreachable(_ n: Never) -> Int { // expected-note{{'n' is of type 'Never' which cannot be constructed because it is an enum with no cases}} | ||
42 // expected-warning{{will never be executed}} | ||
} | ||
|
||
// FIXME: should these produce unreachable code warnings since they implicity take an uninhabited 'self' param? | ||
func implicitly_unreachable() { _ = 42 } | ||
func implicitly_unreachable_implicit_return() -> Int { 42 } | ||
} | ||
|
||
enum InhabitedType { | ||
case inhabitant | ||
|
||
// Uninhabited params | ||
subscript(_ n: Never) -> Int {} | ||
subscript<T>(_ e: Never) -> T {} | ||
subscript(_ v: MyEmptyType, e: Int) -> Never {} | ||
|
||
// Inhabited params | ||
subscript(_ i: Int) -> Int {} // expected-error{{missing return in getter expected to return 'Int'}} | ||
subscript(_ j: Int) -> Void {} | ||
subscript(_ k: Int) -> Never {} // expected-error{{getter with uninhabited return type 'Never' is missing call to another never-returning function on all paths}} | ||
// FIXME: ^ this diagnostic should probably use the word 'subscript' rather than 'getter' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. noticed this wording change when moving to the SIL-based diagnostics. i have yet to determine how to special case the relevant logic to improve this. let me know if this seems like a blocker. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it's a blocker, it's the same diagnostic we give today for e.g: struct S {
subscript(_ x: Int) -> Never {
let x = 0
}
} |
||
} |
Uh oh!
There was an error while loading. Please reload this page.