Skip to content

Commit 4e48c40

Browse files
committed
wip: fix parameter matching
1 parent 08e2382 commit 4e48c40

File tree

5 files changed

+103
-8
lines changed

5 files changed

+103
-8
lines changed

include/swift/AST/Types.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,15 @@ class alignas(1 << TypeAlignInBits) TypeBase {
765765
/// \p matchOptions.
766766
bool matches(Type other, TypeMatchOptions matchOptions);
767767

768+
bool matchesParameter(Type other, TypeMatchOptions matchMode);
769+
770+
/// \brief Determines whether this function type is similar to \p
771+
/// other as defined by \p matchOptions and the callback \p
772+
/// paramsAndResultMatch which determines in a client-specific way
773+
/// whether the parameters and result of the types match.
774+
bool matchesFunctionType(Type other, TypeMatchOptions matchOptions,
775+
std::function<bool()> paramsAndResultMatch);
776+
768777
/// \brief Determines whether this type has a retainable pointer
769778
/// representation, i.e. whether it is representable as a single,
770779
/// possibly nil pointer that can be unknown-retained and

lib/AST/Decl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4936,6 +4936,7 @@ static bool requiresNewVTableEntry(const AbstractFunctionDecl *decl) {
49364936
auto overrideInterfaceTy = selfInterfaceTy->adjustSuperclassMemberDeclType(
49374937
base, decl, baseInterfaceTy);
49384938

4939+
// FIXME: IUO
49394940
return !derivedInterfaceTy->matches(overrideInterfaceTy,
49404941
TypeMatchFlags::AllowABICompatible);
49414942
}

lib/AST/Type.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,10 +2178,10 @@ namespace {
21782178
};
21792179
} // end anonymous namespace
21802180

2181-
static bool matchFunctionTypes(CanAnyFunctionType fn1, CanAnyFunctionType fn2,
2182-
TypeMatchOptions matchMode,
2183-
OptionalUnwrapping insideOptional,
2184-
std::function<bool()> paramsAndResultMatch) {
2181+
static bool matchesFunctionType(CanAnyFunctionType fn1, CanAnyFunctionType fn2,
2182+
TypeMatchOptions matchMode,
2183+
OptionalUnwrapping insideOptional,
2184+
std::function<bool()> paramsAndResultMatch) {
21852185
// FIXME: Handle generic functions in non-ABI matches.
21862186
if (!matchMode.contains(TypeMatchFlags::AllowABICompatible)) {
21872187
if (!isa<FunctionType>(fn1) || !isa<FunctionType>(fn2))
@@ -2299,8 +2299,8 @@ static bool matches(CanType t1, CanType t2, TypeMatchOptions matchMode,
22992299
OptionalUnwrapping::None));
23002300
};
23012301

2302-
return matchFunctionTypes(fn1, fn2, matchMode, insideOptional,
2303-
paramsAndResultMatch);
2302+
return matchesFunctionType(fn1, fn2, matchMode, insideOptional,
2303+
paramsAndResultMatch);
23042304
}
23052305

23062306
if (matchMode.contains(TypeMatchFlags::AllowNonOptionalForIUOParam) &&
@@ -2331,6 +2331,21 @@ bool TypeBase::matches(Type other, TypeMatchOptions matchMode) {
23312331
ParameterPosition::NotParameter, OptionalUnwrapping::None);
23322332
}
23332333

2334+
bool TypeBase::matchesParameter(Type other, TypeMatchOptions matchMode) {
2335+
return ::matches(getCanonicalType(), other->getCanonicalType(), matchMode,
2336+
ParameterPosition::Parameter, OptionalUnwrapping::None);
2337+
}
2338+
2339+
bool TypeBase::matchesFunctionType(Type other, TypeMatchOptions matchMode,
2340+
std::function<bool()> paramsAndResultMatch) {
2341+
auto thisFnTy = dyn_cast<AnyFunctionType>(getCanonicalType());
2342+
auto otherFnTy = dyn_cast<AnyFunctionType>(other->getCanonicalType());
2343+
2344+
assert(thisFnTy && otherFnTy);
2345+
return ::matchesFunctionType(thisFnTy, otherFnTy, matchMode,
2346+
OptionalUnwrapping::None, paramsAndResultMatch);
2347+
}
2348+
23342349
/// getNamedElementId - If this tuple has a field with the specified name,
23352350
/// return the field index, otherwise return -1.
23362351
int TupleType::getNamedElementId(Identifier I) const {

lib/SIL/SILFunctionType.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2137,6 +2137,7 @@ SILParameterInfo TypeConverter::getConstantSelfParameter(SILDeclRef constant) {
21372137
// @guaranteed or whatever.
21382138
static bool checkASTTypeForABIDifferences(CanType type1,
21392139
CanType type2) {
2140+
// FIXME: IUO
21402141
return !type1->matches(type2, TypeMatchFlags::AllowABICompatible);
21412142
}
21422143

lib/Sema/TypeCheckDecl.cpp

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5934,6 +5934,61 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
59345934
}
59355935
}
59365936

5937+
static bool parameterTypesMatch(const ValueDecl *derivedDecl,
5938+
const ValueDecl *baseDecl,
5939+
TypeMatchOptions matchMode) {
5940+
const ParameterList *derivedParams;
5941+
const ParameterList *baseParams;
5942+
if (auto *derived = dyn_cast<AbstractFunctionDecl>(derivedDecl)) {
5943+
auto *base = dyn_cast<AbstractFunctionDecl>(baseDecl);
5944+
if (!base)
5945+
return false;
5946+
baseParams = base->getParameterList(1);
5947+
derivedParams = derived->getParameterList(1);
5948+
} else {
5949+
auto *base = dyn_cast<SubscriptDecl>(baseDecl);
5950+
if (!base)
5951+
return false;
5952+
baseParams = base->getIndices();
5953+
derivedParams = cast<SubscriptDecl>(derivedDecl)->getIndices();
5954+
}
5955+
5956+
if (baseParams->size() != derivedParams->size())
5957+
return false;
5958+
5959+
auto subs = SubstitutionMap::getOverrideSubstitutions(baseDecl, derivedDecl,
5960+
/*derivedSubs=*/None);
5961+
5962+
for (auto i : indices(baseParams->getArray())) {
5963+
auto *baseParam = baseParams->get(i);
5964+
auto baseParamTy = baseParam->getInterfaceType();
5965+
auto baseParamMappedTy = baseDecl->getDeclContext()->mapTypeIntoContext(baseParamTy);
5966+
auto baseParamSubstTy = baseParamMappedTy.subst(subs);
5967+
5968+
auto *derivedParam = derivedParams->get(i);
5969+
auto derivedParamTy = derivedParam->getInterfaceType();
5970+
5971+
// Attempt contravariant match.
5972+
if (baseParamSubstTy->matchesParameter(derivedParamTy, matchMode))
5973+
continue;
5974+
5975+
// Try once more for a match, using the underlying type of an
5976+
// IUO if we're allowing that.
5977+
if (baseParam->getAttrs()
5978+
.hasAttribute<ImplicitlyUnwrappedOptionalAttr>() &&
5979+
matchMode.contains(TypeMatchFlags::AllowNonOptionalForIUOParam)) {
5980+
baseParamSubstTy = baseParamSubstTy->getAnyOptionalObjectType();
5981+
if (baseParamSubstTy->matches(derivedParamTy, matchMode))
5982+
continue;
5983+
}
5984+
5985+
// If there is no match, then we're done.
5986+
return false;
5987+
}
5988+
5989+
return true;
5990+
}
5991+
59375992
/// Determine which method or subscript this method or subscript overrides
59385993
/// (if any).
59395994
///
@@ -6146,8 +6201,22 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
61466201
TypeMatchFlags::IgnoreNonEscapingForOptionalFunctionParam;
61476202
}
61486203

6149-
if (declTy->matches(parentDeclTy, matchMode)) {
6150-
// If the Objective-C selectors match, always call it exact.
6204+
auto declFnTy = declTy->getAs<AnyFunctionType>();
6205+
auto parentDeclFnTy = parentDeclTy->getAs<AnyFunctionType>();
6206+
if (declFnTy && parentDeclFnTy) {
6207+
auto paramsAndResultMatch = [=]() -> bool {
6208+
return parameterTypesMatch(decl, parentDecl, matchMode) &&
6209+
declFnTy->getResult()->matches(parentDeclFnTy->getResult(),
6210+
matchMode);
6211+
};
6212+
6213+
if (declFnTy->matchesFunctionType(parentDeclFnTy, matchMode,
6214+
paramsAndResultMatch)) {
6215+
matches.push_back({parentDecl, objCMatch, parentDeclTy});
6216+
hadExactMatch |= objCMatch;
6217+
continue;
6218+
}
6219+
} else if (declTy->matches(parentDeclTy, matchMode)) {
61516220
matches.push_back({parentDecl, objCMatch, parentDeclTy});
61526221
hadExactMatch |= objCMatch;
61536222
continue;

0 commit comments

Comments
 (0)