Skip to content

Commit 0959f0c

Browse files
committed
Take the IUO-ness of a parameter declaration into account in ranking.
Normally we wouldn't need this because we do not allow overloading by parameter optionality. In this case, though, we import two Objective-C methods that end up getting renamed to the same name in Swift, one of which has a nullability annotation and the other of which doesn't. Before IUOs were removed from the type system, we would have failed a subtype test when ranking overloads, but now that subtype test passes because we're comparing two optionals of the same type. So the change here is to compare the optionality of the parameters and reject cases where we are testing whether a plain optional is a subtype of something declared to be an IUO. Fixes rdar://problem/38719575.
1 parent 7cb869a commit 0959f0c

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

lib/Sema/CSRanking.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,21 @@ static Type getAdjustedParamType(const AnyFunctionType::Param &param) {
384384
return param.getType();
385385
}
386386

387+
// Is a particular parameter of a function or subscript declaration
388+
// declared to be an IUO?
389+
static bool paramIsIUO(Decl *decl, int paramNum) {
390+
if (auto *fn = dyn_cast<AbstractFunctionDecl>(decl)) {
391+
auto *paramList =
392+
fn->getParameterList(fn->getDeclContext()->isTypeContext());
393+
auto *param = paramList->get(paramNum);
394+
return param->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
395+
}
396+
397+
auto *subscript = cast<SubscriptDecl>(decl);
398+
auto *index = subscript->getIndices()->get(paramNum);
399+
return index->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
400+
}
401+
387402
/// \brief Determine whether the first declaration is as "specialized" as
388403
/// the second declaration.
389404
///
@@ -676,6 +691,17 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
676691
continue;
677692
}
678693

694+
// Emulate behavior from when IUO was a type, where IUOs
695+
// were considered subtypes of plain optionals, but not
696+
// vice-versa. This wouldn't normally happen, but there are
697+
// cases where we can rename imported APIs so that we have a
698+
// name collision, and where the parameter type(s) are the
699+
// same except for details of the kind of optional declared.
700+
auto param1IsIUO = paramIsIUO(decl1, param1);
701+
auto param2IsIUO = paramIsIUO(decl2, param2);
702+
if (param2IsIUO && !param1IsIUO)
703+
return false;
704+
679705
if (!maybeAddSubtypeConstraint(params1[param1], params2[param2]))
680706
return false;
681707

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
@import Foundation;
2+
3+
@interface NSObject (NSMyTest)
4+
- (BOOL)isEqualTo:(nullable id)object;
5+
@end
6+
7+
@interface Obj : NSObject
8+
- (BOOL)isEqualToObject:(id)value;
9+
@end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %build-clang-importer-objc-overlays
3+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -import-objc-header %S/Inputs/disambiguate_iuo_param.h %s -emit-ir | %FileCheck %s
4+
// -module-name objc_ir -I %S/Inputs/custom-modules -emit-ir -g -o - -primary-file %s | %FileCheck %s
5+
6+
// REQUIRES: objc_interop
7+
8+
// CHECK: define {{.*}} @main
9+
// CHECK: load {{.*}}, {{.*}}@"\01L_selector(isEqualToObject:)"
10+
let c = Obj()
11+
_ = c.isEqual(to: c)

0 commit comments

Comments
 (0)