mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Sema] Ban placeholders in typed throws
This never worked correctly and would crash in SILGen, ban the use of placeholder types. While here, ensure we replace any ErrorTypes with holes when solving the closure in the constraint system.
This commit is contained in:
@@ -2542,8 +2542,11 @@ namespace {
|
||||
Type thrownErrorTy = [&] {
|
||||
// Explicitly-specified thrown type.
|
||||
if (closure->getExplicitThrownTypeRepr()) {
|
||||
if (Type explicitType = closure->getExplicitThrownType())
|
||||
return explicitType;
|
||||
if (Type explicitType = closure->getExplicitThrownType()) {
|
||||
// The thrown type may have errors, open as placeholders if needed.
|
||||
return CS.replaceInferableTypesWithTypeVars(explicitType,
|
||||
thrownErrorLocator);
|
||||
}
|
||||
}
|
||||
|
||||
// Explicitly-specified 'throws' without a type is untyped throws.
|
||||
|
||||
@@ -6999,7 +6999,7 @@ Type ExplicitCaughtTypeRequest::evaluate(
|
||||
|
||||
return TypeResolution::forInterface(func, options,
|
||||
/*unboundTyOpener*/ nullptr,
|
||||
PlaceholderType::get,
|
||||
/*placeholderOpener*/ nullptr,
|
||||
/*packElementOpener*/ nullptr)
|
||||
.resolveType(thrownTypeRepr);
|
||||
}
|
||||
@@ -7011,7 +7011,7 @@ Type ExplicitCaughtTypeRequest::evaluate(
|
||||
return TypeResolution::resolveContextualType(
|
||||
thrownTypeRepr, closure,
|
||||
TypeResolutionOptions(TypeResolverContext::None),
|
||||
/*unboundTyOpener*/ nullptr, PlaceholderType::get,
|
||||
/*unboundTyOpener*/ nullptr, /*placeholderOpener*/ nullptr,
|
||||
/*packElementOpener*/ nullptr);
|
||||
}
|
||||
|
||||
@@ -7045,7 +7045,7 @@ Type ExplicitCaughtTypeRequest::evaluate(
|
||||
return TypeResolution::resolveContextualType(
|
||||
typeRepr, doCatch->getDeclContext(),
|
||||
TypeResolutionOptions(TypeResolverContext::None),
|
||||
/*unboundTyOpener*/ nullptr, PlaceholderType::get,
|
||||
/*unboundTyOpener*/ nullptr, /*placeholderOpener*/ nullptr,
|
||||
/*packElementOpener*/ nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -216,3 +216,8 @@ struct NotAnError<T> {}
|
||||
|
||||
func badThrowingFunctionType<T>(_: () throws(NotAnError<T>) -> ()) {}
|
||||
// expected-error@-1 {{thrown type 'NotAnError<T>' does not conform to the 'Error' protocol}}
|
||||
|
||||
struct GenericError<T>: Error {}
|
||||
|
||||
func placeholderThrowing1() throws(_) {} // expected-error {{type placeholder not allowed here}}
|
||||
func placeholderThrowing2() throws(GenericError<_>) {} // expected-error {{type placeholder not allowed here}}
|
||||
|
||||
@@ -8,6 +8,8 @@ enum MyBadError {
|
||||
case fail
|
||||
}
|
||||
|
||||
struct GenericError<T>: Error {}
|
||||
|
||||
func testClosures() {
|
||||
let c1 = { () throws(MyError) in
|
||||
throw .fail
|
||||
@@ -36,5 +38,8 @@ func testClosures() {
|
||||
let c2 = { throw MyError.fail }
|
||||
let _: Int = c2
|
||||
// expected-error@-1{{cannot convert value of type '() throws -> ()'}}
|
||||
|
||||
_ = { () throws(_) in } // expected-error {{type placeholder not allowed here}}
|
||||
_ = { () throws(GenericError<_>) in } // expected-error {{type placeholder not allowed here}}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ case dogAteIt
|
||||
case forgot
|
||||
}
|
||||
|
||||
struct GenericError<T>: Error {}
|
||||
|
||||
func processMyError(_: MyError) { }
|
||||
|
||||
func doSomething() throws(MyError) { }
|
||||
@@ -418,3 +420,12 @@ func testSequenceExpr() async throws(Never) {
|
||||
try true ? 0 : try! getInt() ~~~ getInt()
|
||||
// expected-error@-1 {{'try!' following conditional operator does not cover everything to its right}}
|
||||
}
|
||||
|
||||
func testPlaceholder() {
|
||||
do throws(_) {} catch {}
|
||||
// expected-error@-1 {{type placeholder not allowed here}}
|
||||
// expected-warning@-2 {{'catch' block is unreachable because no errors are thrown in 'do' block}}
|
||||
do throws(GenericError<_>) {} catch {}
|
||||
// expected-error@-1 {{type placeholder not allowed here}}
|
||||
// expected-warning@-2 {{'catch' block is unreachable because no errors are thrown in 'do' block}}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user