Skip to content

Commit 68648f7

Browse files
committed
[CS] Use adjusted type for single curry thunks
This matches the double curry thunk logic and ensures that the resulting autoclosure matches the expected type of the reference, avoiding mismatches with parent expressions. rdar://140212823
1 parent 683c7ce commit 68648f7

File tree

5 files changed

+119
-45
lines changed

5 files changed

+119
-45
lines changed

lib/Sema/CSApply.cpp

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -759,22 +759,27 @@ namespace {
759759
new (ctx) DeclRefExpr(ref, loc, implicit, semantics, fullType);
760760
cs.cacheType(declRefExpr);
761761
declRefExpr->setFunctionRefKind(choice.getFunctionRefKind());
762-
Expr *result = adjustTypeForDeclReference(
763-
declRefExpr, fullType, adjustedFullType, locator);
764-
// If we have to load, do so now.
765-
if (loadImmediately)
766-
result = cs.addImplicitLoadExpr(result);
767762

768-
result = forceUnwrapIfExpected(result, locator);
763+
Expr *result = forceUnwrapIfExpected(declRefExpr, locator);
769764

770765
if (auto *fnDecl = dyn_cast<AbstractFunctionDecl>(decl)) {
771766
if (AnyFunctionRef(fnDecl).hasExternalPropertyWrapperParameters() &&
772767
(declRefExpr->getFunctionRefKind() == FunctionRefKind::Compound ||
773768
declRefExpr->getFunctionRefKind() == FunctionRefKind::Unapplied)) {
774-
result = buildSingleCurryThunk(result, fnDecl, locator);
769+
// We don't need to do any further adjustment once we've built the
770+
// curry thunk.
771+
return buildSingleCurryThunk(result, fnDecl,
772+
adjustedFullType->castTo<FunctionType>(),
773+
locator);
775774
}
776775
}
777776

777+
result = adjustTypeForDeclReference(result, fullType, adjustedFullType,
778+
locator);
779+
// If we have to load, do so now.
780+
if (loadImmediately)
781+
result = cs.addImplicitLoadExpr(result);
782+
778783
return result;
779784
}
780785

@@ -1406,41 +1411,20 @@ namespace {
14061411
/// parameters.
14071412
/// \param declOrClosure The underlying function-like declaration or
14081413
/// closure we're going to call.
1414+
/// \param thunkTy The type of the resulting thunk. This should be the
1415+
/// type of the \c fnExpr, with any potential adjustments for things like
1416+
/// concurrency.
14091417
/// \param locator The locator pinned on the function reference carried
14101418
/// by \p fnExpr. If the function has associated applied property wrappers,
14111419
/// the locator is used to pull them in.
14121420
AutoClosureExpr *buildSingleCurryThunk(Expr *fnExpr,
14131421
DeclContext *declOrClosure,
1422+
FunctionType *thunkTy,
14141423
ConstraintLocatorBuilder locator) {
1415-
auto *const thunkTy = cs.getType(fnExpr)->castTo<FunctionType>();
1416-
14171424
return buildSingleCurryThunk(/*baseExpr=*/nullptr, fnExpr, declOrClosure,
14181425
thunkTy, locator);
14191426
}
14201427

1421-
/// Build a "{ args in base.fn(args) }" single-expression curry thunk.
1422-
///
1423-
/// \param baseExpr The base expression to be captured.
1424-
/// \param fnExpr The expression to be called by consecutively applying
1425-
/// the \p baseExpr and thunk parameters.
1426-
/// \param declOrClosure The underlying function-like declaration or
1427-
/// closure we're going to call.
1428-
/// \param locator The locator pinned on the function reference carried
1429-
/// by \p fnExpr. If the function has associated applied property wrappers,
1430-
/// the locator is used to pull them in.
1431-
AutoClosureExpr *buildSingleCurryThunk(Expr *baseExpr, Expr *fnExpr,
1432-
DeclContext *declOrClosure,
1433-
ConstraintLocatorBuilder locator) {
1434-
assert(baseExpr);
1435-
auto *const thunkTy = cs.getType(fnExpr)
1436-
->castTo<FunctionType>()
1437-
->getResult()
1438-
->castTo<FunctionType>();
1439-
1440-
return buildSingleCurryThunk(baseExpr, fnExpr, declOrClosure, thunkTy,
1441-
locator);
1442-
}
1443-
14441428
/// Build a "{ self in { args in self.fn(args) } }" nested curry thunk.
14451429
///
14461430
/// \param memberRef The expression to be called in the inner thunk by
@@ -1909,9 +1893,10 @@ namespace {
19091893
// have side effects, instead of abstracting out a 'self' parameter.
19101894
const auto isSuperPartialApplication = needsCurryThunk && isSuper;
19111895
if (isSuperPartialApplication) {
1912-
ref = buildSingleCurryThunk(base, declRefExpr,
1913-
cast<AbstractFunctionDecl>(member),
1914-
memberLocator);
1896+
ref = buildSingleCurryThunk(
1897+
base, declRefExpr, cast<AbstractFunctionDecl>(member),
1898+
adjustedOpenedType->castTo<FunctionType>(),
1899+
memberLocator);
19151900
} else if (needsCurryThunk) {
19161901
// Another case where we want to build a single closure is when
19171902
// we have a partial application of a static member. It is better
@@ -1927,14 +1912,13 @@ namespace {
19271912
cs.getType(base));
19281913
cs.setType(base, base->getType());
19291914

1930-
auto *closure = buildSingleCurryThunk(
1931-
base, declRefExpr, cast<AbstractFunctionDecl>(member),
1932-
memberLocator);
1933-
19341915
// Skip the code below -- we're not building an extra level of
19351916
// call by applying the metatype; instead, the closure we just
19361917
// built is the curried reference.
1937-
return closure;
1918+
return buildSingleCurryThunk(
1919+
base, declRefExpr, cast<AbstractFunctionDecl>(member),
1920+
adjustedOpenedType->castTo<FunctionType>(),
1921+
memberLocator);
19381922
} else {
19391923
// Add a useless ".self" to avoid downstream diagnostics, in case
19401924
// the type ref is still a TypeExpr.
@@ -8874,8 +8858,10 @@ namespace {
88748858
rewriteFunction(closure);
88758859

88768860
if (AnyFunctionRef(closure).hasExternalPropertyWrapperParameters()) {
8861+
auto *thunkTy = Rewriter.cs.getType(closure)->castTo<FunctionType>();
88778862
return Action::SkipNode(Rewriter.buildSingleCurryThunk(
8878-
closure, closure, Rewriter.cs.getConstraintLocator(closure)));
8863+
closure, closure, thunkTy,
8864+
Rewriter.cs.getConstraintLocator(closure)));
88798865
}
88808866

88818867
return Action::SkipNode(closure);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-emit-silgen -verify -disable-objc-attr-requires-foundation-module %s
2+
// RUN: %target-swift-emit-silgen -verify -swift-version 6 -disable-objc-attr-requires-foundation-module %s
3+
4+
// REQUIRES: objc_interop
5+
6+
@objc class C {
7+
@preconcurrency @objc func foo(_ x: Sendable) {}
8+
}
9+
10+
func bar(_ fn: (Any) -> Void) {}
11+
func bar(_ fn: (Sendable) -> Void) {}
12+
13+
// Make sure we can handle both the implicit unwrap and concurrency adjustment.
14+
func foo(_ x: AnyObject) {
15+
bar(x.foo)
16+
let _ = AnyObject.foo
17+
}

test/Constraints/rdar140212823.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %target-swift-emit-silgen %s -verify -swift-version 6
2+
3+
// rdar://140212823 - Make sure we build curry thunks using the adjusted
4+
// reference type, such that the ParenExpr agrees with the type.
5+
6+
class C: @unchecked Sendable {
7+
func foo() {}
8+
}
9+
class D: C, @unchecked Sendable {
10+
func bar() {
11+
let _ = (super.foo)
12+
}
13+
}
14+
15+
struct S {
16+
func instanceMethod() {}
17+
func foo() {
18+
let _ = (self.instanceMethod)
19+
}
20+
static func staticMethod() {}
21+
}
22+
23+
let _ = (S.instanceMethod)
24+
let _ = (type(of: S()).instanceMethod)
25+
26+
let _ = (S.staticMethod)
27+
let _ = (type(of: S()).staticMethod)
28+
29+
let _: (Int, Int) -> Int = (+)

test/SILGen/dynamic_self.swift

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ class Base {
362362

363363
class Derived : Base {
364364
// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self7DerivedC9superCallyyF : $@convention(method) (@guaranteed Derived) -> ()
365-
// CHECK: convert_function %{{[0-9]+}} : $@callee_guaranteed () -> @owned Base to $@callee_guaranteed () -> @owned Derived
365+
// CHECK: function_ref @$s12dynamic_self7DerivedC9superCallyyFACycfu_ : $@convention(thin) (@guaranteed Derived) -> @owned Derived
366366
// CHECK-COUNT-3: unchecked_ref_cast %{{[0-9]+}} : $Base to $Derived
367367
// CHECK-NOT: unchecked_ref_cast
368368
// CHECK: end sil function '$s12dynamic_self7DerivedC9superCallyyF'
@@ -372,9 +372,12 @@ class Derived : Base {
372372
_ = super.property
373373
_ = super[]
374374
}
375+
// CHECK-LABEL: sil private [ossa] @$s12dynamic_self7DerivedC9superCallyyFACycfu_ : $@convention(thin) (@guaranteed Derived) -> @owned Derived
376+
// CHECK: unchecked_ref_cast %{{[0-9]+}} : $Base to $Derived
377+
// CHECK: end sil function '$s12dynamic_self7DerivedC9superCallyyFACycfu_'
375378

376379
// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self7DerivedC15superCallStaticyyFZ : $@convention(method) (@thick Derived.Type) -> ()
377-
// CHECK: convert_function %{{[0-9]+}} : $@callee_guaranteed () -> @owned Base to $@callee_guaranteed () -> @owned Derived
380+
// CHECK: function_ref @$s12dynamic_self7DerivedC15superCallStaticyyFZACycfu_ : $@convention(thin) (@thick Derived.Type) -> @owned Derived
378381
// CHECK-COUNT-3: unchecked_ref_cast %{{[0-9]+}} : $Base to $Derived
379382
// CHECK-NOT: unchecked_ref_cast
380383
// CHECK: end sil function '$s12dynamic_self7DerivedC15superCallStaticyyFZ'
@@ -384,9 +387,12 @@ class Derived : Base {
384387
_ = super.staticProperty
385388
_ = super[]
386389
}
390+
// CHECK-LABEL: sil private [ossa] @$s12dynamic_self7DerivedC15superCallStaticyyFZACycfu_ : $@convention(thin) (@thick Derived.Type) -> @owned Derived
391+
// CHECK: unchecked_ref_cast %{{[0-9]+}} : $Base to $Derived
392+
// CHECK: end sil function '$s12dynamic_self7DerivedC15superCallStaticyyFZACycfu_'
387393

388394
// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self7DerivedC32superCallFromMethodReturningSelfACXDyF : $@convention(method) (@guaranteed Derived) -> @owned Derived
389-
// CHECK: convert_function %{{[0-9]+}} : $@callee_guaranteed () -> @owned Base to $@callee_guaranteed () -> @owned Derived
395+
// CHECK: function_ref @$s12dynamic_self7DerivedC32superCallFromMethodReturningSelfACXDyFACXDycfu_ : $@convention(thin) (@guaranteed Derived) -> @owned Derived
390396
// CHECK-COUNT-3: unchecked_ref_cast %{{[0-9]+}} : $Base to $Derived
391397
// CHECK-NOT: unchecked_ref_cast
392398
// CHECK: end sil function '$s12dynamic_self7DerivedC32superCallFromMethodReturningSelfACXDyF'
@@ -396,9 +402,12 @@ class Derived : Base {
396402
_ = super[]
397403
return super.property
398404
}
405+
// CHECK-LABEL: sil private [ossa] @$s12dynamic_self7DerivedC32superCallFromMethodReturningSelfACXDyFACXDycfu_ : $@convention(thin) (@guaranteed Derived) -> @owned Derived
406+
// CHECK: unchecked_ref_cast %{{[0-9]+}} : $Base to $Derived
407+
// CHECK: end sil function '$s12dynamic_self7DerivedC32superCallFromMethodReturningSelfACXDyFACXDycfu_'
399408

400409
// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self7DerivedC38superCallFromMethodReturningSelfStaticACXDyFZ : $@convention(method) (@thick Derived.Type) -> @owned Derived
401-
// CHECK: convert_function %{{[0-9]+}} : $@callee_guaranteed () -> @owned Base to $@callee_guaranteed () -> @owned Derived
410+
// CHECK: function_ref @$s12dynamic_self7DerivedC38superCallFromMethodReturningSelfStaticACXDyFZACXDycfu_ : $@convention(thin) (@thick @dynamic_self Derived.Type) -> @owned Derived
402411
// CHECK-COUNT-3: unchecked_ref_cast %{{[0-9]+}} : $Base to $Derived
403412
// CHECK-NOT: unchecked_ref_cast
404413
// CHECK: end sil function '$s12dynamic_self7DerivedC38superCallFromMethodReturningSelfStaticACXDyFZ'
@@ -408,6 +417,9 @@ class Derived : Base {
408417
_ = super[]
409418
return super.staticProperty
410419
}
420+
// CHECK-LABEL: sil private [ossa] @$s12dynamic_self7DerivedC38superCallFromMethodReturningSelfStaticACXDyFZACXDycfu_ : $@convention(thin) (@thick @dynamic_self Derived.Type) -> @owned Derived
421+
// CHECK: unchecked_ref_cast %{{[0-9]+}} : $Base to $Derived
422+
// CHECK: end sil function '$s12dynamic_self7DerivedC38superCallFromMethodReturningSelfStaticACXDyFZACXDycfu_'
411423
}
412424

413425
class Generic<T> {

test/SILGen/preconcurrency.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,33 @@ func test(from request: Request) {
3737
// for preconcurrency
3838
let _ = request.identifier
3939
}
40+
41+
@propertyWrapper
42+
struct Wrapper<T> {
43+
var wrappedValue: T
44+
45+
init(wrappedValue: T) {
46+
self.wrappedValue = wrappedValue
47+
}
48+
init(projectedValue: Self) {
49+
self = projectedValue
50+
}
51+
var projectedValue: Self { self }
52+
}
53+
54+
// rdar://140212823 - Make sure we can handle the Sendable promotion of `y` in
55+
// the curry thunk.
56+
@preconcurrency func hasWrapperAndPreconcurrency(@Wrapper _ x: Int, _ y: Sendable) {}
57+
struct HasWrapperAndPreconcurrency {
58+
@preconcurrency func instanceMethod(@Wrapper _ x: Int, _ y: Sendable) {}
59+
@preconcurrency static func staticMethod(@Wrapper _ x: Int, _ y: Sendable) {}
60+
}
61+
func testPropertyWrapperPreconcurrencyThunk(_ x: HasWrapperAndPreconcurrency) {
62+
let fn = (hasWrapperAndPreconcurrency)
63+
fn(0, C())
64+
65+
_ = (HasWrapperAndPreconcurrency.staticMethod)
66+
_ = (type(of: x).staticMethod)
67+
_ = (x.instanceMethod)
68+
_ = (type(of: x).instanceMethod)
69+
}

0 commit comments

Comments
 (0)