Skip to content

Commit 4c2e88b

Browse files
Merge pull request #41849 from AnthonyLatsis/dyn_unbound_ref
CS: Handle unbound references to @objc optional methods
2 parents 70044d7 + 77b3f24 commit 4c2e88b

File tree

10 files changed

+648
-366
lines changed

10 files changed

+648
-366
lines changed

include/swift/AST/Decl.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8117,10 +8117,14 @@ inline EnumElementDecl *EnumDecl::getUniqueElement(bool hasValue) const {
81178117
return result;
81188118
}
81198119

8120-
/// Retrieve the parameter list for a given declaration, or nullputr if there
8120+
/// Retrieve the parameter list for a given declaration, or nullptr if there
81218121
/// is none.
81228122
ParameterList *getParameterList(ValueDecl *source);
81238123

8124+
/// Retrieve the parameter list for a given declaration context, or nullptr if
8125+
/// there is none.
8126+
ParameterList *getParameterList(DeclContext *source);
8127+
81248128
/// Retrieve parameter declaration from the given source at given index, or
81258129
/// nullptr if the source does not have a parameter list.
81268130
const ParamDecl *getParameterAt(const ValueDecl *source, unsigned index);

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2513,6 +2513,7 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
25132513

25142514
void visitAppliedPropertyWrapperExpr(AppliedPropertyWrapperExpr *E) {
25152515
printCommon(E, "applied_property_wrapper_expr");
2516+
OS << '\n';
25162517
printRec(E->getValue());
25172518
PrintWithColorRAII(OS, ParenthesisColor) << ')';
25182519
}

lib/AST/Decl.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7533,6 +7533,18 @@ ParameterList *swift::getParameterList(ValueDecl *source) {
75337533
return nullptr;
75347534
}
75357535

7536+
ParameterList *swift::getParameterList(DeclContext *source) {
7537+
if (auto *D = source->getAsDecl()) {
7538+
if (auto *VD = dyn_cast<ValueDecl>(D)) {
7539+
return getParameterList(VD);
7540+
}
7541+
} else if (auto *CE = dyn_cast<AbstractClosureExpr>(source)) {
7542+
return CE->getParameters();
7543+
}
7544+
7545+
return nullptr;
7546+
}
7547+
75367548
const ParamDecl *swift::getParameterAt(const ValueDecl *source,
75377549
unsigned index) {
75387550
if (auto *params = getParameterList(const_cast<ValueDecl *>(source))) {

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3374,8 +3374,9 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
33743374
"method does not have a witness table entry");
33753375
}
33763376

3377-
// Get the expected type of a dynamic method reference.
3378-
SILType getDynamicMethodType(SILType selfType, SILDeclRef method) {
3377+
/// Verify the given type of a dynamic or @objc optional method reference.
3378+
bool verifyDynamicMethodType(CanSILFunctionType verifiedTy, SILType selfType,
3379+
SILDeclRef method) {
33793380
auto &C = F.getASTContext();
33803381

33813382
// The type of the dynamic method must match the usual type of the method,
@@ -3394,28 +3395,50 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
33943395
}
33953396
assert(!methodTy->isPolymorphic());
33963397

3397-
// Replace Self parameter with type of 'self' at the call site.
3398-
auto params = methodTy->getParameters();
3399-
SmallVector<SILParameterInfo, 4>
3400-
dynParams(params.begin(), params.end() - 1);
3401-
dynParams.push_back(SILParameterInfo(selfType.getASTType(),
3402-
params.back().getConvention()));
3398+
// Assume the parameter conventions are correct.
3399+
SmallVector<SILParameterInfo, 4> params;
3400+
{
3401+
const auto actualParams = methodTy->getParameters();
3402+
const auto verifiedParams = verifiedTy->getParameters();
3403+
if (actualParams.size() != verifiedParams.size())
3404+
return false;
3405+
3406+
for (const auto idx : indices(actualParams)) {
3407+
params.push_back(actualParams[idx].getWithConvention(
3408+
verifiedParams[idx].getConvention()));
3409+
}
3410+
}
3411+
3412+
// Have the 'self' parameter assume the type of 'self' at the call site.
3413+
params.back() = params.back().getWithInterfaceType(selfType.getASTType());
34033414

3404-
auto results = methodTy->getResults();
3405-
SmallVector<SILResultInfo, 4> dynResults(results.begin(), results.end());
3415+
// Assume the result conventions are correct.
3416+
SmallVector<SILResultInfo, 4> results;
3417+
{
3418+
const auto actualResults = methodTy->getResults();
3419+
const auto verifiedResults = verifiedTy->getResults();
3420+
if (actualResults.size() != verifiedResults.size())
3421+
return false;
3422+
3423+
for (const auto idx : indices(actualResults)) {
3424+
results.push_back(actualResults[idx].getWithConvention(
3425+
verifiedResults[idx].getConvention()));
3426+
}
3427+
}
34063428

3407-
// If the method returns Self, substitute AnyObject for the result type.
3429+
// If the method returns dynamic Self, substitute AnyObject for the
3430+
// result type.
34083431
if (auto fnDecl = dyn_cast<FuncDecl>(method.getDecl())) {
34093432
if (fnDecl->hasDynamicSelfResult()) {
34103433
auto anyObjectTy = C.getAnyObjectType();
3411-
for (auto &dynResult : dynResults) {
3434+
for (auto &result : results) {
34123435
auto newResultTy =
3413-
dynResult
3436+
result
34143437
.getReturnValueType(F.getModule(), methodTy,
34153438
F.getTypeExpansionContext())
34163439
->replaceCovariantResultType(anyObjectTy, 0);
3417-
dynResult = SILResultInfo(newResultTy->getCanonicalType(),
3418-
dynResult.getConvention());
3440+
result = SILResultInfo(newResultTy->getCanonicalType(),
3441+
result.getConvention());
34193442
}
34203443
}
34213444
}
@@ -3424,13 +3447,14 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
34243447
methodTy->getExtInfo(),
34253448
methodTy->getCoroutineKind(),
34263449
methodTy->getCalleeConvention(),
3427-
dynParams,
3450+
params,
34283451
methodTy->getYields(),
3429-
dynResults,
3452+
results,
34303453
methodTy->getOptionalErrorResult(),
34313454
SubstitutionMap(), SubstitutionMap(),
34323455
F.getASTContext());
3433-
return SILType::getPrimitiveObjectType(fnTy);
3456+
3457+
return fnTy->isBindableTo(verifiedTy);
34343458
}
34353459

34363460
/// Visitor class that checks whether a given decl ref has an entry in the
@@ -4853,9 +4877,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
48534877
"true bb for dynamic_method_br must take an argument");
48544878

48554879
auto bbArgTy = DMBI->getHasMethodBB()->args_begin()[0]->getType();
4856-
require(getDynamicMethodType(operandType, DMBI->getMember())
4857-
.getASTType()
4858-
->isBindableTo(bbArgTy.getASTType()),
4880+
require(verifyDynamicMethodType(cast<SILFunctionType>(bbArgTy.getASTType()),
4881+
operandType, DMBI->getMember()),
48594882
"bb argument for dynamic_method_br must be of the method's type");
48604883
}
48614884

0 commit comments

Comments
 (0)