Skip to content

Commit f3ec9d5

Browse files
committed
[AST] Mark repr invalid only if @autoclosure parameter doesn't point to function type
Instead on depending on repr to be a function, let's only check whether type resolved for `@autoclosure` points to a function type because it's allowed for `@autoclosure` parameters to be to wrapped into parens or be represented by a typealias. Resolves: rdar://problem/65704049 (cherry picked from commit f2c2aa5)
1 parent 62e6834 commit f3ec9d5

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2411,15 +2411,23 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs,
24112411
}
24122412
}
24132413

2414-
if (hasFunctionAttr && !fnRepr) {
2415-
if (attrs.has(TAK_autoclosure)) {
2414+
if (attrs.has(TAK_autoclosure)) {
2415+
// If this is a situation where function type is wrapped
2416+
// into a number of parens, let's try to look through them,
2417+
// because parens are insignificant here e.g.:
2418+
//
2419+
// let _: (@autoclosure (() -> Void)) -> Void = { _ in }
2420+
if (!ty->is<FunctionType>()) {
24162421
// @autoclosure is going to be diagnosed when type of
24172422
// the parameter is validated, because that attribute
24182423
// applies to the declaration now.
24192424
repr->setInvalid();
2420-
attrs.clearAttribute(TAK_autoclosure);
24212425
}
24222426

2427+
attrs.clearAttribute(TAK_autoclosure);
2428+
}
2429+
2430+
if (hasFunctionAttr && !fnRepr) {
24232431
const auto diagnoseInvalidAttr = [&](TypeAttrKind kind) {
24242432
if (kind == TAK_escaping) {
24252433
Type optionalObjectType = ty->getOptionalObjectType();

test/attr/attr_autoclosure.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,3 +295,36 @@ struct SR_11938_S : @autoclosure SR_11938_P {} // expected-error {{'@autoclosure
295295

296296
// SR-9178
297297
func bar<T>(_ x: @autoclosure T) {} // expected-error 1{{@autoclosure attribute only applies to function types}}
298+
299+
func test_autoclosure_type_in_parens() {
300+
let _: (@autoclosure (() -> Void)) -> Void = { _ in } // Ok
301+
302+
struct Test {
303+
func bugSingle<T: RawRepresentable>(defaultValue: @autoclosure (() -> T)) -> T { // Ok
304+
defaultValue()
305+
}
306+
307+
func bugMultiple<T: RawRepresentable>(defaultValue: @autoclosure ((() -> T))) -> T { // Ok
308+
defaultValue()
309+
}
310+
}
311+
312+
enum E : String {
313+
case foo = "foo"
314+
case bar = "bar"
315+
}
316+
317+
_ = Test().bugSingle(defaultValue: E.foo) // Ok
318+
_ = Test().bugMultiple(defaultValue: E.bar) // Ok
319+
}
320+
321+
func test_autoclosure_with_typealias() {
322+
typealias ConcreteFunc = () -> Int
323+
typealias GenericFunc<T> = () -> T
324+
325+
func test(cr: @autoclosure ConcreteFunc) -> Int { cr() } // Ok
326+
func test<Q>(gn: @autoclosure GenericFunc<Q>) -> Q { gn() } // Ok
327+
328+
_ = test(cr: 0) // Ok
329+
_ = test(gn: 1) // Ok
330+
}

0 commit comments

Comments
 (0)