Skip to content

CS: Handle unbound references to @objc optional methods #41849

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Mar 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8058,10 +8058,14 @@ inline EnumElementDecl *EnumDecl::getUniqueElement(bool hasValue) const {
return result;
}

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

/// Retrieve the parameter list for a given declaration context, or nullptr if
/// there is none.
ParameterList *getParameterList(DeclContext *source);

/// Retrieve parameter declaration from the given source at given index, or
/// nullptr if the source does not have a parameter list.
const ParamDecl *getParameterAt(const ValueDecl *source, unsigned index);
Expand Down
1 change: 1 addition & 0 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2513,6 +2513,7 @@ class PrintExpr : public ExprVisitor<PrintExpr> {

void visitAppliedPropertyWrapperExpr(AppliedPropertyWrapperExpr *E) {
printCommon(E, "applied_property_wrapper_expr");
OS << '\n';
printRec(E->getValue());
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
Expand Down
12 changes: 12 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7533,6 +7533,18 @@ ParameterList *swift::getParameterList(ValueDecl *source) {
return nullptr;
}

ParameterList *swift::getParameterList(DeclContext *source) {
if (auto *D = source->getAsDecl()) {
if (auto *VD = dyn_cast<ValueDecl>(D)) {
return getParameterList(VD);
}
} else if (auto *CE = dyn_cast<AbstractClosureExpr>(source)) {
return CE->getParameters();
}

return nullptr;
}

const ParamDecl *swift::getParameterAt(const ValueDecl *source,
unsigned index) {
if (auto *params = getParameterList(const_cast<ValueDecl *>(source))) {
Expand Down
65 changes: 44 additions & 21 deletions lib/SIL/Verifier/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3374,8 +3374,9 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
"method does not have a witness table entry");
}

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

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

// Replace Self parameter with type of 'self' at the call site.
auto params = methodTy->getParameters();
SmallVector<SILParameterInfo, 4>
dynParams(params.begin(), params.end() - 1);
dynParams.push_back(SILParameterInfo(selfType.getASTType(),
params.back().getConvention()));
// Assume the parameter conventions are correct.
SmallVector<SILParameterInfo, 4> params;
{
const auto actualParams = methodTy->getParameters();
const auto verifiedParams = verifiedTy->getParameters();
if (actualParams.size() != verifiedParams.size())
return false;

for (const auto idx : indices(actualParams)) {
params.push_back(actualParams[idx].getWithConvention(
verifiedParams[idx].getConvention()));
}
}

// Have the 'self' parameter assume the type of 'self' at the call site.
params.back() = params.back().getWithInterfaceType(selfType.getASTType());

auto results = methodTy->getResults();
SmallVector<SILResultInfo, 4> dynResults(results.begin(), results.end());
// Assume the result conventions are correct.
SmallVector<SILResultInfo, 4> results;
{
const auto actualResults = methodTy->getResults();
const auto verifiedResults = verifiedTy->getResults();
if (actualResults.size() != verifiedResults.size())
return false;

for (const auto idx : indices(actualResults)) {
results.push_back(actualResults[idx].getWithConvention(
verifiedResults[idx].getConvention()));
}
}

// If the method returns Self, substitute AnyObject for the result type.
// If the method returns dynamic Self, substitute AnyObject for the
// result type.
if (auto fnDecl = dyn_cast<FuncDecl>(method.getDecl())) {
if (fnDecl->hasDynamicSelfResult()) {
auto anyObjectTy = C.getAnyObjectType();
for (auto &dynResult : dynResults) {
for (auto &result : results) {
auto newResultTy =
dynResult
result
.getReturnValueType(F.getModule(), methodTy,
F.getTypeExpansionContext())
->replaceCovariantResultType(anyObjectTy, 0);
dynResult = SILResultInfo(newResultTy->getCanonicalType(),
dynResult.getConvention());
result = SILResultInfo(newResultTy->getCanonicalType(),
result.getConvention());
}
}
}
Expand All @@ -3424,13 +3447,14 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
methodTy->getExtInfo(),
methodTy->getCoroutineKind(),
methodTy->getCalleeConvention(),
dynParams,
params,
methodTy->getYields(),
dynResults,
results,
methodTy->getOptionalErrorResult(),
SubstitutionMap(), SubstitutionMap(),
F.getASTContext());
return SILType::getPrimitiveObjectType(fnTy);

return fnTy->isBindableTo(verifiedTy);
}

/// Visitor class that checks whether a given decl ref has an entry in the
Expand Down Expand Up @@ -4881,9 +4905,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
"true bb for dynamic_method_br must take an argument");

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

Expand Down
Loading