Skip to content

Commit adc6d1c

Browse files
committed
Introduce more AST function conversions for @preconcurrency-adjusted types.
When referring to a `@preconcurrency` function as a value, use the normal type for the initial declaration reference and then introduce an appropriate function conversion expression to the adjusted type. Fixes more issues related to rdar://94597323.
1 parent e4943b1 commit adc6d1c

File tree

4 files changed

+69
-24
lines changed

4 files changed

+69
-24
lines changed

lib/SILGen/SILGenPoly.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ collectExistentialConformances(ModuleDecl *M, CanType fromType, CanType toType)
183183
SmallVector<ProtocolConformanceRef, 4> conformances;
184184
for (auto proto : protocols) {
185185
auto conformance =
186-
M->lookupConformance(fromType, proto);
186+
M->lookupConformance(fromType, proto, /*allowMissing=*/true);
187187
assert(conformance);
188188
conformances.push_back(conformance);
189189
}

lib/Sema/CSApply.cpp

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,8 @@ namespace {
527527
auto choice = overload.choice;
528528
assert(choice.getKind() != OverloadChoiceKind::DeclViaDynamic);
529529
auto *decl = choice.getDecl();
530-
auto fullType = simplifyType(overload.adjustedOpenedFullType);
530+
Type fullType = simplifyType(overload.openedFullType);
531+
Type adjustedFullType = simplifyType(overload.adjustedOpenedFullType);
531532

532533
// Determine the declaration selected for this overloaded reference.
533534
auto &ctx = cs.getASTContext();
@@ -540,7 +541,7 @@ namespace {
540541
if (decl->getDeclContext()->isTypeContext() && isa<FuncDecl>(decl)) {
541542
assert(cast<FuncDecl>(decl)->isOperator() && "Must be an operator");
542543

543-
auto baseTy = getBaseType(fullType->castTo<FunctionType>());
544+
auto baseTy = getBaseType(adjustedFullType->castTo<FunctionType>());
544545

545546
// Handle operator requirements found in protocols.
546547
if (auto proto = dyn_cast<ProtocolDecl>(decl->getDeclContext())) {
@@ -564,9 +565,9 @@ namespace {
564565
// function.
565566
Type refType;
566567
if (isMemberOperator)
567-
refType = fullType;
568+
refType = adjustedFullType;
568569
else
569-
refType = fullType->castTo<AnyFunctionType>()->getResult();
570+
refType = adjustedFullType->castTo<AnyFunctionType>()->getResult();
570571

571572
// Build the AST for the call to the witness.
572573
auto subMap = getOperatorSubstitutions(witness, refType);
@@ -588,7 +589,7 @@ namespace {
588589

589590
refExpr = DotSyntaxCallExpr::create(ctx, declRefExpr,
590591
SourceLoc(), base);
591-
auto refType = fullType->castTo<FunctionType>()->getResult();
592+
auto refType = adjustedFullType->castTo<FunctionType>()->getResult();
592593
cs.setType(refExpr, refType);
593594
} else {
594595
refExpr = declRefExpr;
@@ -612,7 +613,7 @@ namespace {
612613

613614
if (isa<TypeDecl>(decl) && !isa<ModuleDecl>(decl)) {
614615
auto typeExpr = TypeExpr::createImplicitHack(
615-
loc.getBaseNameLoc(), fullType->getMetatypeInstanceType(), ctx);
616+
loc.getBaseNameLoc(), adjustedFullType->getMetatypeInstanceType(), ctx);
616617
cs.cacheType(typeExpr);
617618
return typeExpr;
618619
}
@@ -622,7 +623,9 @@ namespace {
622623
new (ctx) DeclRefExpr(ref, loc, implicit, semantics, fullType);
623624
cs.cacheType(declRefExpr);
624625
declRefExpr->setFunctionRefKind(choice.getFunctionRefKind());
625-
Expr *result = forceUnwrapIfExpected(declRefExpr, locator);
626+
Expr *result = adjustTypeForDeclReference(
627+
declRefExpr, fullType, adjustedFullType);
628+
result = forceUnwrapIfExpected(result, locator);
626629

627630
if (auto *fnDecl = dyn_cast<AbstractFunctionDecl>(decl)) {
628631
if (AnyFunctionRef(fnDecl).hasExternalPropertyWrapperParameters() &&
@@ -1501,19 +1504,22 @@ namespace {
15011504
return result;
15021505
}
15031506

1504-
auto refTy = simplifyType(overload.adjustedOpenedFullType);
1507+
Type refTy = simplifyType(overload.openedFullType);
1508+
Type adjustedRefTy = simplifyType(overload.adjustedOpenedFullType);
15051509

15061510
// If we're referring to the member of a module, it's just a simple
15071511
// reference.
15081512
if (baseTy->is<ModuleType>()) {
15091513
assert(semantics == AccessSemantics::Ordinary &&
15101514
"Direct property access doesn't make sense for this");
1511-
auto ref = new (context) DeclRefExpr(memberRef, memberLoc, Implicit);
1512-
cs.setType(ref, refTy);
1513-
ref->setFunctionRefKind(choice.getFunctionRefKind());
1514-
auto *DSBI = cs.cacheType(new (context) DotSyntaxBaseIgnoredExpr(
1515-
base, dotLoc, ref, cs.getType(ref)));
1516-
return forceUnwrapIfExpected(DSBI, memberLocator);
1515+
auto *dre = new (context) DeclRefExpr(memberRef, memberLoc, Implicit);
1516+
cs.setType(dre, refTy);
1517+
dre->setFunctionRefKind(choice.getFunctionRefKind());
1518+
Expr *ref = cs.cacheType(new (context) DotSyntaxBaseIgnoredExpr(
1519+
base, dotLoc, dre, refTy));
1520+
1521+
ref = adjustTypeForDeclReference(ref, refTy, adjustedRefTy);
1522+
return forceUnwrapIfExpected(ref, memberLocator);
15171523
}
15181524

15191525
const bool isUnboundInstanceMember =
@@ -1689,11 +1695,15 @@ namespace {
16891695
memberLoc, Implicit, semantics);
16901696
memberRefExpr->setIsSuper(isSuper);
16911697

1692-
if (hasDynamicSelf)
1698+
if (hasDynamicSelf) {
16931699
refTy = refTy->replaceCovariantResultType(containerTy, 1);
1700+
adjustedRefTy = adjustedRefTy->replaceCovariantResultType(
1701+
containerTy, 1);
1702+
}
16941703
cs.setType(memberRefExpr, refTy->castTo<FunctionType>()->getResult());
16951704

16961705
Expr *result = memberRefExpr;
1706+
result = adjustTypeForDeclReference(result, refTy, adjustedRefTy);
16971707
closeExistentials(result, locator);
16981708

16991709
// If the property is of dynamic 'Self' type, wrap an implicit
@@ -1710,8 +1720,11 @@ namespace {
17101720
return forceUnwrapIfExpected(result, memberLocator);
17111721
}
17121722

1713-
if (member->getInterfaceType()->hasDynamicSelfType())
1723+
if (member->getInterfaceType()->hasDynamicSelfType()) {
17141724
refTy = refTy->replaceCovariantResultType(containerTy, 2);
1725+
adjustedRefTy = adjustedRefTy->replaceCovariantResultType(
1726+
containerTy, 2);
1727+
}
17151728

17161729
// Handle all other references.
17171730
auto declRefExpr = new (context) DeclRefExpr(memberRef, memberLoc,
@@ -1721,6 +1734,8 @@ namespace {
17211734
cs.setType(declRefExpr, refTy);
17221735
Expr *ref = declRefExpr;
17231736

1737+
ref = adjustTypeForDeclReference(ref, refTy, adjustedRefTy);
1738+
17241739
// A partial application thunk consists of two nested closures:
17251740
//
17261741
// { self in { args... in self.method(args...) } }
@@ -1778,7 +1793,7 @@ namespace {
17781793
// on 'CovariantReturnConversionExpr'.
17791794
curryThunkTy = simplifyType(adjustedOpenedType)->castTo<FunctionType>();
17801795
} else {
1781-
curryThunkTy = refTy->castTo<FunctionType>();
1796+
curryThunkTy = adjustedRefTy->castTo<FunctionType>();
17821797

17831798
// Check if we need to open an existential stored inside 'self'.
17841799
auto knownOpened = solution.OpenedExistentialTypes.find(
@@ -1816,7 +1831,7 @@ namespace {
18161831
baseTy, member, memberLocator.getBaseLocator());
18171832
if (!replacementTy->isEqual(containerTy)) {
18181833
Type conversionTy =
1819-
refTy->replaceCovariantResultType(replacementTy, 2);
1834+
adjustedRefTy->replaceCovariantResultType(replacementTy, 2);
18201835
if (isSuperPartialApplication) {
18211836
conversionTy =
18221837
conversionTy->castTo<FunctionType>()->getResult();
@@ -1841,11 +1856,8 @@ namespace {
18411856
ref = forceUnwrapIfExpected(ref, memberLocator);
18421857
apply = ConstructorRefCallExpr::create(context, ref, base);
18431858
} else if (isUnboundInstanceMember) {
1844-
auto refType = cs.simplifyType(adjustedOpenedType);
1845-
if (!cs.getType(ref)->isEqual(refType)) {
1846-
ref = new (context) FunctionConversionExpr(ref, refType);
1847-
cs.cacheType(ref);
1848-
}
1859+
ref = adjustTypeForDeclReference(
1860+
ref, cs.getType(ref), cs.simplifyType(adjustedOpenedType));
18491861

18501862
// Reference to an unbound instance method.
18511863
Expr *result = new (context) DotSyntaxBaseIgnoredExpr(base, dotLoc,

test/SILGen/objc_preconcurrency.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,8 @@
1111
// CHECK: bb{{[0-9]+}}(%{{[0-9]+}} : $@convention(objc_method) (@convention(block) @Sendable () -> (), @opened
1212
func testDynamicDispatch(p: P, completionHandler: @escaping () -> Void) {
1313
p.f?(completionHandler)
14+
15+
// CHECK: dynamic_method_br
16+
// CHECK: bb{{[0-9]+}}(%{{[0-9]+}} : $@convention(objc_method) (@convention(block) @Sendable () -> (), @opened
17+
let _ = p.f
1418
}

test/SILGen/preconcurrency.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 -module-name preconcurrency -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | %FileCheck %s
2+
3+
class C {
4+
@preconcurrency func f(_: Sendable) { }
5+
@preconcurrency static func g(_: Sendable) { }
6+
}
7+
8+
@preconcurrency func f(_: Sendable) { }
9+
10+
// CHECK-LABEL: sil hidden [ossa] @$s14preconcurrency28testModuleMethodWithSendable3anyyyp_tF
11+
func testModuleMethodWithSendable(any: Any) {
12+
// CHECK: function_ref @$s14preconcurrency1fyyypF : $@convention(thin) (@in_guaranteed Sendable) -> ()
13+
let _ = f
14+
15+
// CHECK: function_ref @$s14preconcurrency1fyyypF : $@convention(thin) (@in_guaranteed Sendable) -> ()
16+
let _ = preconcurrency.f
17+
// f(any)
18+
// preconcurrency.f(any)
19+
}
20+
21+
// CHECK-LABEL: sil hidden [ossa] @$s14preconcurrency30testInstanceMethodWithSendable1c3anyyAA1CC_yptF : $@convention(thin) (@guaranteed C, @in_guaranteed Any) -> () {
22+
func testInstanceMethodWithSendable(c: C, any: Any) {
23+
// CHECK-LABEL: sil private [ossa] @$s14preconcurrency30testInstanceMethodWithSendable1c3anyyAA1CC_yptFyypcAFcfu_yypcfu0_
24+
// CHECK: class_method %1 : $C, #C.f : (C) -> (Sendable) -> ()
25+
let _ = c.f
26+
let _ = C.f
27+
let _ = C.g
28+
// c.f(any)
29+
}

0 commit comments

Comments
 (0)