mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Implement 'rethrows' checking in Sema.
Now with amazing new fixes and tests for methods and generics! Swift SVN r28499
This commit is contained in:
@@ -1798,6 +1798,8 @@ ERROR(isa_pattern_value,sema_tcp,none,
|
|||||||
|
|
||||||
ERROR(try_unhandled,sema,none,
|
ERROR(try_unhandled,sema,none,
|
||||||
"errors thrown from here are not handled", ())
|
"errors thrown from here are not handled", ())
|
||||||
|
ERROR(throwing_call_unhandled,sema,none,
|
||||||
|
"call can throw, but the error is not handled", ())
|
||||||
ERROR(tryless_throwing_call_unhandled,sema,none,
|
ERROR(tryless_throwing_call_unhandled,sema,none,
|
||||||
"call can throw, but it is not marked with 'try' and "
|
"call can throw, but it is not marked with 'try' and "
|
||||||
"the error is not handled", ())
|
"the error is not handled", ())
|
||||||
@@ -1805,6 +1807,21 @@ ERROR(throw_in_nonthrowing_function,sema,none,
|
|||||||
"error is not handled because the enclosing function "
|
"error is not handled because the enclosing function "
|
||||||
"is not declared 'throws'", ())
|
"is not declared 'throws'", ())
|
||||||
|
|
||||||
|
ERROR(throwing_call_in_rethrows_function,sema,none,
|
||||||
|
"throwing call in 'rethrows' function is not to a parameter "
|
||||||
|
"function", ())
|
||||||
|
ERROR(tryless_throwing_call_in_rethrows_function,sema,none,
|
||||||
|
"throwing call in 'rethrows' function is not to a parameter "
|
||||||
|
"function and is not marked with 'try'", ())
|
||||||
|
ERROR(throw_in_rethrows_function,sema,none,
|
||||||
|
"'rethrows' function may only throw by calling a parameter "
|
||||||
|
"function", ())
|
||||||
|
NOTE(because_rethrows_argument_throws,sema,none,
|
||||||
|
"call is to 'rethrows' function, but argument function can throw", ())
|
||||||
|
NOTE(because_rethrows_default_argument_throws,sema,none,
|
||||||
|
"call is to 'rethrows' function, but a defaulted argument function"
|
||||||
|
" can throw", ())
|
||||||
|
|
||||||
ERROR(throwing_call_in_nonthrowing_autoclosure,sema,none,
|
ERROR(throwing_call_in_nonthrowing_autoclosure,sema,none,
|
||||||
"call can throw, but it is executed in a non-throwing "
|
"call can throw, but it is executed in a non-throwing "
|
||||||
"autoclosure",())
|
"autoclosure",())
|
||||||
@@ -1818,11 +1835,11 @@ ERROR(throw_in_nonthrowing_autoclosure,sema,none,
|
|||||||
ERROR(try_unhandled_in_nonexhaustive_catch,sema,none,
|
ERROR(try_unhandled_in_nonexhaustive_catch,sema,none,
|
||||||
"errors thrown from here are not handled because the "
|
"errors thrown from here are not handled because the "
|
||||||
"enclosing catch is not exhaustive", ())
|
"enclosing catch is not exhaustive", ())
|
||||||
|
ERROR(throwing_call_in_nonexhaustive_catch,sema,none,
|
||||||
|
"call can throw, but the enclosing catch is not exhaustive", ())
|
||||||
ERROR(tryless_throwing_call_in_nonexhaustive_catch,sema,none,
|
ERROR(tryless_throwing_call_in_nonexhaustive_catch,sema,none,
|
||||||
"call can throw, but it is not marked with 'try' and "
|
"call can throw, but it is not marked with 'try' and "
|
||||||
"the enclosing catch is not exhaustive", ())
|
"the enclosing catch is not exhaustive", ())
|
||||||
ERROR(throwing_call_in_nonexhaustive_catch,sema,none,
|
|
||||||
"call can throw, but the enclosing catch is not exhaustive", ())
|
|
||||||
ERROR(throw_in_nonexhaustive_catch,sema,none,
|
ERROR(throw_in_nonexhaustive_catch,sema,none,
|
||||||
"error is not handled because the enclosing catch is not exhaustive", ())
|
"error is not handled because the enclosing catch is not exhaustive", ())
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -92,3 +92,230 @@ class C3 : Super {
|
|||||||
override func nhf(f: () throws -> ()) rethrows {} // expected-error {{cannot override non-throwing method with throwing method}}
|
override func nhf(f: () throws -> ()) rethrows {} // expected-error {{cannot override non-throwing method with throwing method}}
|
||||||
override func rhf(f: () throws -> ()) rethrows {}
|
override func rhf(f: () throws -> ()) rethrows {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Semantics ****************************************************************/
|
||||||
|
|
||||||
|
func call(fn: () throws -> Int) rethrows -> Int { return try fn() }
|
||||||
|
func callAC(@autoclosure fn: () throws -> Int) rethrows -> Int { return try fn() }
|
||||||
|
func raise() throws -> Int { return 0 }
|
||||||
|
func noraise() -> Int { return 0 }
|
||||||
|
|
||||||
|
/** Global functions **/
|
||||||
|
|
||||||
|
func testCallUnhandled() {
|
||||||
|
call(noraise)
|
||||||
|
try call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
call(raise) // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try call(raise) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCallHandled() throws {
|
||||||
|
call(noraise)
|
||||||
|
try call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
call(raise) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try call(raise)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCallACUnhandled() {
|
||||||
|
callAC(noraise())
|
||||||
|
try callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
callAC(raise()) // expected-error {{call can throw but is not marked with 'try'}} \
|
||||||
|
// expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} \
|
||||||
|
// expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try callAC(raise()) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCallACHandled() throws {
|
||||||
|
callAC(noraise())
|
||||||
|
try callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
callAC(raise()) // expected-error 2 {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try callAC(raise())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func testForward1(fn: () throws -> Int) rethrows {
|
||||||
|
try call(fn)
|
||||||
|
}
|
||||||
|
func testForward2(fn: () throws -> Int) rethrows {
|
||||||
|
try call({ try fn() })
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Methods **/
|
||||||
|
|
||||||
|
struct MyStruct : MyProto {
|
||||||
|
func call(fn: () throws -> Int) rethrows -> Int { return try fn() }
|
||||||
|
func callAC(@autoclosure fn: () throws -> Int) rethrows -> Int { return try fn() }
|
||||||
|
|
||||||
|
static func static_call(fn: () throws -> Int) rethrows -> Int { return try fn() }
|
||||||
|
static func static_callAC(@autoclosure fn: () throws -> Int) rethrows -> Int { return try fn() }
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMethodCallUnhandled(s: MyStruct) {
|
||||||
|
s.call(noraise)
|
||||||
|
try s.call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.call(raise) // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.call(raise) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
|
||||||
|
MyStruct.static_call(noraise)
|
||||||
|
try MyStruct.static_call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
MyStruct.static_call(raise) // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try MyStruct.static_call(raise) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMethodCallHandled(s: MyStruct) throws {
|
||||||
|
s.call(noraise)
|
||||||
|
try s.call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.call(raise) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.call(raise)
|
||||||
|
|
||||||
|
MyStruct.static_call(noraise)
|
||||||
|
try MyStruct.static_call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
MyStruct.static_call(raise) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try MyStruct.static_call(raise)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMethodCallACUnhandled(s: MyStruct) {
|
||||||
|
s.callAC(noraise())
|
||||||
|
try s.callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.callAC(raise()) // expected-error {{call can throw but is not marked with 'try'}} \
|
||||||
|
// expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} \
|
||||||
|
// expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.callAC(raise()) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
|
||||||
|
MyStruct.static_callAC(noraise())
|
||||||
|
try MyStruct.static_callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
MyStruct.static_callAC(raise()) // expected-error {{call can throw but is not marked with 'try'}} \
|
||||||
|
// expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} \
|
||||||
|
// expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try MyStruct.static_callAC(raise()) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMethodCallACHandled(s: MyStruct) throws {
|
||||||
|
s.callAC(noraise())
|
||||||
|
try s.callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.callAC(raise()) // expected-error 2 {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.callAC(raise())
|
||||||
|
|
||||||
|
MyStruct.static_callAC(noraise())
|
||||||
|
try MyStruct.static_callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
MyStruct.static_callAC(raise()) // expected-error 2 {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try MyStruct.static_callAC(raise())
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Protocol methods **/
|
||||||
|
|
||||||
|
protocol MyProto {
|
||||||
|
func call(fn: () throws -> Int) rethrows -> Int
|
||||||
|
func callAC(@autoclosure fn: () throws -> Int) rethrows -> Int
|
||||||
|
|
||||||
|
static func static_call(fn: () throws -> Int) rethrows -> Int
|
||||||
|
static func static_callAC(@autoclosure fn: () throws -> Int) rethrows -> Int
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Existentials **/
|
||||||
|
|
||||||
|
func testProtoMethodCallUnhandled(s: MyProto) {
|
||||||
|
s.call(noraise)
|
||||||
|
try s.call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.call(raise) // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.call(raise) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
|
||||||
|
s.dynamicType.static_call(noraise)
|
||||||
|
try s.dynamicType.static_call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.dynamicType.static_call(raise) // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.dynamicType.static_call(raise) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testProtoMethodCallHandled(s: MyProto) throws {
|
||||||
|
s.call(noraise)
|
||||||
|
try s.call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.call(raise) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.call(raise)
|
||||||
|
|
||||||
|
s.dynamicType.static_call(noraise)
|
||||||
|
try s.dynamicType.static_call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.dynamicType.static_call(raise) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.dynamicType.static_call(raise)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testProtoMethodCallACUnhandled(s: MyProto) {
|
||||||
|
s.callAC(noraise())
|
||||||
|
try s.callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.callAC(raise()) // expected-error {{call can throw but is not marked with 'try'}} \
|
||||||
|
// expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} \
|
||||||
|
// expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.callAC(raise()) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
|
||||||
|
s.dynamicType.static_callAC(noraise())
|
||||||
|
try s.dynamicType.static_callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.dynamicType.static_callAC(raise()) // expected-error {{call can throw but is not marked with 'try'}} \
|
||||||
|
// expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} \
|
||||||
|
// expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.dynamicType.static_callAC(raise()) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testProtoMethodCallACHandled(s: MyProto) throws {
|
||||||
|
s.callAC(noraise())
|
||||||
|
try s.callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.callAC(raise()) // expected-error 2 {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.callAC(raise())
|
||||||
|
|
||||||
|
s.dynamicType.static_callAC(noraise())
|
||||||
|
try s.dynamicType.static_callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.dynamicType.static_callAC(raise()) // expected-error 2 {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.dynamicType.static_callAC(raise())
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Generics **/
|
||||||
|
|
||||||
|
func testGenericMethodCallUnhandled<P: MyProto>(s: P) {
|
||||||
|
s.call(noraise)
|
||||||
|
try s.call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.call(raise) // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.call(raise) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
|
||||||
|
P.static_call(noraise)
|
||||||
|
try P.static_call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
P.static_call(raise) // expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try P.static_call(raise) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testGenericMethodCallHandled<P: MyProto>(s: P) throws {
|
||||||
|
s.call(noraise)
|
||||||
|
try s.call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.call(raise) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.call(raise)
|
||||||
|
|
||||||
|
P.static_call(noraise)
|
||||||
|
try P.static_call(noraise) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
P.static_call(raise) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try P.static_call(raise)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testGenericMethodCallACUnhandled<P: MyProto>(s: P) {
|
||||||
|
s.callAC(noraise())
|
||||||
|
try s.callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.callAC(raise()) // expected-error {{call can throw but is not marked with 'try'}} \
|
||||||
|
// expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} \
|
||||||
|
// expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.callAC(raise()) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
|
||||||
|
P.static_callAC(noraise())
|
||||||
|
try P.static_callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
P.static_callAC(raise()) // expected-error {{call can throw but is not marked with 'try'}} \
|
||||||
|
// expected-error {{call can throw, but it is not marked with 'try' and the error is not handled}} \
|
||||||
|
// expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try P.static_callAC(raise()) // expected-error {{call can throw, but the error is not handled}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testGenericMethodCallACHandled<P: MyProto>(s: P) throws {
|
||||||
|
s.callAC(noraise())
|
||||||
|
try s.callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
s.callAC(raise()) // expected-error 2 {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try s.callAC(raise())
|
||||||
|
|
||||||
|
P.static_callAC(noraise())
|
||||||
|
try P.static_callAC(noraise()) // expected-warning {{no calls to throwing functions occur within 'try'}}
|
||||||
|
P.static_callAC(raise()) // expected-error 2 {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
|
||||||
|
try P.static_callAC(raise())
|
||||||
|
}
|
||||||
|
|||||||
@@ -70,3 +70,17 @@ struct seven {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protocol ThrowingProto {
|
||||||
|
func foo() throws
|
||||||
|
static func bar() throws
|
||||||
|
}
|
||||||
|
|
||||||
|
func testExistential(p : ThrowingProto) throws {
|
||||||
|
try p.foo()
|
||||||
|
try p.dynamicType.bar()
|
||||||
|
}
|
||||||
|
func testGeneric<P : ThrowingProto>(p : P) throws {
|
||||||
|
try p.foo()
|
||||||
|
try P.bar()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user