Skip to content

Commit 4660af6

Browse files
authored
Merge pull request #17339 from rjmccall/autoclosure-conversion-application
Perform function conversions when converting between autoclosures
2 parents 4a59552 + 9e90512 commit 4660af6

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

lib/Sema/CSApply.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6865,10 +6865,18 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
68656865
isInDefaultArgumentContext = (initalizerCtx->getInitializerKind() ==
68666866
InitializerKind::DefaultArgument);
68676867
auto toEI = toFunc->getExtInfo();
6868+
6869+
auto fromFunc = fromType->getAs<FunctionType>();
6870+
68686871
// Coercion to an autoclosure type produces an implicit closure.
6872+
// The constraint solver only performs this conversion when the source
6873+
// type is not an autoclosure function type. That's a weird rule in
6874+
// some rules, but it's easy to follow here. Really we just shouldn't
6875+
// represent autoclosures as a bit on function types.
68696876
// FIXME: The type checker is more lenient, and allows @autoclosures to
68706877
// be subtypes of non-@autoclosures, which is bogus.
6871-
if (toFunc->isAutoClosure()) {
6878+
if (toFunc->isAutoClosure() &&
6879+
(!fromFunc || !fromFunc->isAutoClosure())) {
68726880
// The function type without @noescape if we are in the default argument
68736881
// context.
68746882
auto newToFuncType = toFunc;
@@ -6909,7 +6917,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
69096917

69106918
// Coercion from one function type to another, this produces a
69116919
// FunctionConversionExpr in its full generality.
6912-
if (auto fromFunc = fromType->getAs<FunctionType>()) {
6920+
if (fromFunc) {
69136921
// If we have a ClosureExpr, then we can safely propagate the 'no escape'
69146922
// bit to the closure without invalidating prior analysis.
69156923
auto fromEI = fromFunc->getExtInfo();

test/attr/attr_autoclosure.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ func migrateAC(@autoclosure _: () -> ()) { }
146146
func migrateACE(@autoclosure(escaping) _: () -> ()) { }
147147

148148
func takesAutoclosure(_ fn: @autoclosure () -> Int) {}
149+
func takesThrowingAutoclosure(_: @autoclosure () throws -> Int) {}
149150

150151
func callAutoclosureWithNoEscape(_ fn: () -> Int) {
151152
takesAutoclosure(1+1) // ok
@@ -161,3 +162,16 @@ func callAutoclosureWithNoEscape_3(_ fn: @autoclosure () -> Int) {
161162
func variadicAutoclosure(_ fn: @autoclosure () -> ()...) {
162163
for _ in fn {}
163164
}
165+
166+
// rdar://41219750
167+
// These are all arguably invalid; the autoclosure should have to be called.
168+
// But as long as we allow them, we shouldn't crash.
169+
func passNonThrowingToNonThrowingAC(_ fn: @autoclosure () -> Int) {
170+
takesAutoclosure(fn)
171+
}
172+
func passNonThrowingToThrowingAC(_ fn: @autoclosure () -> Int) {
173+
takesThrowingAutoclosure(fn)
174+
}
175+
func passThrowingToThrowingAC(_ fn: @autoclosure () throws -> Int) {
176+
takesThrowingAutoclosure(fn)
177+
}

0 commit comments

Comments
 (0)