Skip to content

Commit c5fe743

Browse files
authored
Merge pull request #59545 from beccadax/you-completion-me-5.7
2 parents 2c292a0 + d4ee34c commit c5fe743

22 files changed

+174
-59
lines changed

include/swift/AST/Decl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6740,7 +6740,7 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
67406740
bool hasDynamicSelfResult() const;
67416741

67426742
/// The async function marked as the alternative to this function, if any.
6743-
AbstractFunctionDecl *getAsyncAlternative() const;
6743+
AbstractFunctionDecl *getAsyncAlternative(bool isKnownObjC = false) const;
67446744

67456745
/// If \p asyncAlternative is set, then compare its parameters to this
67466746
/// (presumed synchronous) function's parameters to find the index of the

include/swift/AST/ModuleLoader.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,11 @@ class ModuleLoader {
226226
virtual void loadExtensions(NominalTypeDecl *nominal,
227227
unsigned previousGeneration) { }
228228

229-
/// Load the methods within the given class that produce
229+
/// Load the methods within the given type that produce
230230
/// Objective-C class or instance methods with the given selector.
231231
///
232-
/// \param classDecl The class in which we are searching for @objc methods.
233-
/// The search only considers this class and its extensions; not any
232+
/// \param typeDecl The type in which we are searching for @objc methods.
233+
/// The search only considers this type and its extensions; not any
234234
/// superclasses.
235235
///
236236
/// \param selector The selector to search for.
@@ -246,7 +246,7 @@ class ModuleLoader {
246246
/// selector and are instance/class methods as requested. This list will be
247247
/// extended with any methods found in subsequent generations.
248248
virtual void loadObjCMethods(
249-
ClassDecl *classDecl,
249+
NominalTypeDecl *typeDecl,
250250
ObjCSelector selector,
251251
bool isInstanceMethod,
252252
unsigned previousGeneration,

include/swift/AST/SourceFile.h

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/AST/Import.h"
1818
#include "swift/AST/SynthesizedFileUnit.h"
1919
#include "swift/Basic/Debug.h"
20+
#include "llvm/ADT/Hashing.h"
2021
#include "llvm/ADT/SetVector.h"
2122
#include "llvm/ADT/SmallPtrSet.h"
2223

@@ -243,11 +244,20 @@ class SourceFile final : public FileUnit {
243244
std::vector<ObjCUnsatisfiedOptReq> ObjCUnsatisfiedOptReqs;
244245

245246
/// A selector that is used by two different declarations in the same class.
246-
/// Fields: typeDecl, selector, isInstanceMethod.
247-
using ObjCMethodConflict = std::tuple<NominalTypeDecl *, ObjCSelector, bool>;
247+
struct ObjCMethodConflict {
248+
NominalTypeDecl *typeDecl;
249+
ObjCSelector selector;
250+
bool isInstanceMethod;
251+
252+
ObjCMethodConflict(NominalTypeDecl *typeDecl, ObjCSelector selector,
253+
bool isInstanceMethod)
254+
: typeDecl(typeDecl), selector(selector),
255+
isInstanceMethod(isInstanceMethod)
256+
{}
257+
};
248258

249259
/// List of Objective-C member conflicts we have found during type checking.
250-
std::vector<ObjCMethodConflict> ObjCMethodConflicts;
260+
llvm::SetVector<ObjCMethodConflict> ObjCMethodConflicts;
251261

252262
/// List of attributes added by access notes, used to emit remarks for valid
253263
/// ones.
@@ -636,4 +646,30 @@ inline void simple_display(llvm::raw_ostream &out, const SourceFile *SF) {
636646
}
637647
} // end namespace swift
638648

649+
namespace llvm {
650+
651+
template<>
652+
struct DenseMapInfo<swift::SourceFile::ObjCMethodConflict> {
653+
using ObjCMethodConflict = swift::SourceFile::ObjCMethodConflict;
654+
655+
static inline ObjCMethodConflict getEmptyKey() {
656+
return ObjCMethodConflict(nullptr, {}, false);
657+
}
658+
static inline ObjCMethodConflict getTombstoneKey() {
659+
return ObjCMethodConflict(nullptr, {}, true);
660+
}
661+
static inline unsigned getHashValue(ObjCMethodConflict a) {
662+
return hash_combine(hash_value(a.typeDecl),
663+
DenseMapInfo<swift::ObjCSelector>::getHashValue(a.selector),
664+
hash_value(a.isInstanceMethod));
665+
}
666+
static bool isEqual(ObjCMethodConflict a, ObjCMethodConflict b) {
667+
return a.typeDecl == b.typeDecl && a.selector == b.selector &&
668+
a.isInstanceMethod == b.isInstanceMethod;
669+
}
670+
};
671+
672+
}
673+
674+
639675
#endif

include/swift/AST/TypeCheckRequests.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3631,7 +3631,8 @@ class ConditionalRequirementsRequest
36313631

36323632
class RenamedDeclRequest
36333633
: public SimpleRequest<RenamedDeclRequest,
3634-
ValueDecl *(const ValueDecl *, const AvailableAttr *),
3634+
ValueDecl *(const ValueDecl *, const AvailableAttr *,
3635+
bool isKnownObjC),
36353636
RequestFlags::Cached> {
36363637
public:
36373638
using SimpleRequest::SimpleRequest;
@@ -3640,7 +3641,7 @@ class RenamedDeclRequest
36403641
friend SimpleRequest;
36413642

36423643
ValueDecl *evaluate(Evaluator &evaluator, const ValueDecl *attached,
3643-
const AvailableAttr *attr) const;
3644+
const AvailableAttr *attr, bool isKnownObjC) const;
36443645

36453646
public:
36463647
bool isCached() const { return true; }

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ SWIFT_REQUEST(TypeChecker, GetImplicitSendableRequest,
423423
ProtocolConformance *(NominalTypeDecl *),
424424
Cached, NoLocationInfo)
425425
SWIFT_REQUEST(TypeChecker, RenamedDeclRequest,
426-
ValueDecl *(const ValueDecl *),
426+
ValueDecl *(const ValueDecl *, const AvailableAttr *, bool),
427427
Cached, NoLocationInfo)
428428
SWIFT_REQUEST(TypeChecker, ClosureEffectsRequest,
429429
FunctionType::ExtInfo(ClosureExpr *),

include/swift/ClangImporter/ClangImporter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ class ClangImporter final : public ClangModuleLoader {
309309
unsigned previousGeneration) override;
310310

311311
virtual void loadObjCMethods(
312-
ClassDecl *classDecl,
312+
NominalTypeDecl *typeDecl,
313313
ObjCSelector selector,
314314
bool isInstanceMethod,
315315
unsigned previousGeneration,

include/swift/Sema/SourceLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ class SourceLoader : public ModuleLoader {
8585
unsigned previousGeneration) override;
8686

8787
virtual void loadObjCMethods(
88-
ClassDecl *classDecl,
88+
NominalTypeDecl *typeDecl,
8989
ObjCSelector selector,
9090
bool isInstanceMethod,
9191
unsigned previousGeneration,

include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ class SerializedModuleLoaderBase : public ModuleLoader {
190190
unsigned previousGeneration) override;
191191

192192
virtual void loadObjCMethods(
193-
ClassDecl *classDecl,
193+
NominalTypeDecl *typeDecl,
194194
ObjCSelector selector,
195195
bool isInstanceMethod,
196196
unsigned previousGeneration,

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,24 +1916,12 @@ void ASTContext::loadObjCMethods(
19161916
PrettyStackTraceSelector stackTraceSelector("looking for", selector);
19171917
PrettyStackTraceDecl stackTraceDecl("...in", tyDecl);
19181918

1919-
// @objc protocols cannot have @objc extension members, so if we've recorded
1920-
// everything in the protocol definition, we've recorded everything. And we
1921-
// only ever use the ObjCSelector version of `NominalTypeDecl::lookupDirect()`
1922-
// on protocols in primary file typechecking, so we don't care about protocols
1923-
// that need to be loaded from files.
1924-
// TODO: Rework `ModuleLoader::loadObjCMethods()` to support protocols too if
1925-
// selector-based `NominalTypeDecl::lookupDirect()` ever needs to work
1926-
// in more situations.
1927-
ClassDecl *classDecl = dyn_cast<ClassDecl>(tyDecl);
1928-
if (!classDecl)
1929-
return;
1930-
19311919
for (auto &loader : getImpl().ModuleLoaders) {
19321920
// Ignore the Clang importer if we've been asked for Swift-only results.
19331921
if (swiftOnly && loader.get() == getClangModuleLoader())
19341922
continue;
19351923

1936-
loader->loadObjCMethods(classDecl, selector, isInstanceMethod,
1924+
loader->loadObjCMethods(tyDecl, selector, isInstanceMethod,
19371925
previousGeneration, methods);
19381926
}
19391927
}

lib/AST/Decl.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7588,7 +7588,8 @@ bool AbstractFunctionDecl::hasDynamicSelfResult() const {
75887588
return isa<ConstructorDecl>(this);
75897589
}
75907590

7591-
AbstractFunctionDecl *AbstractFunctionDecl::getAsyncAlternative() const {
7591+
AbstractFunctionDecl *
7592+
AbstractFunctionDecl::getAsyncAlternative(bool isKnownObjC) const {
75927593
// Async functions can't have async alternatives
75937594
if (hasAsync())
75947595
return nullptr;
@@ -7612,7 +7613,8 @@ AbstractFunctionDecl *AbstractFunctionDecl::getAsyncAlternative() const {
76127613
}
76137614

76147615
auto *renamedDecl = evaluateOrDefault(
7615-
getASTContext().evaluator, RenamedDeclRequest{this, avAttr}, nullptr);
7616+
getASTContext().evaluator, RenamedDeclRequest{this, avAttr, isKnownObjC},
7617+
nullptr);
76167618
auto *alternative = dyn_cast_or_null<AbstractFunctionDecl>(renamedDecl);
76177619
if (!alternative || !alternative->hasAsync())
76187620
return nullptr;

lib/AST/NameLookup.cpp

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,7 +1310,24 @@ class swift::ObjCMethodLookupTable
13101310
: public llvm::DenseMap<std::pair<ObjCSelector, char>,
13111311
StoredObjCMethods>,
13121312
public ASTAllocated<ObjCMethodLookupTable>
1313-
{};
1313+
{
1314+
SWIFT_DEBUG_DUMP {
1315+
llvm::errs() << "ObjCMethodLookupTable:\n";
1316+
for (auto pair : *this) {
1317+
auto selector = pair.getFirst().first;
1318+
auto isInstanceMethod = pair.getFirst().second;
1319+
auto &methods = pair.getSecond();
1320+
1321+
llvm::errs() << " \"" << (isInstanceMethod ? "-" : "+") << selector
1322+
<< "\":\n";
1323+
for (auto method : methods.Methods) {
1324+
llvm::errs() << " - \"";
1325+
method->dumpRef(llvm::errs());
1326+
llvm::errs() << "\"\n";
1327+
}
1328+
}
1329+
}
1330+
};
13141331

13151332
MemberLookupTable::MemberLookupTable(ASTContext &ctx) {
13161333
// Register a cleanup with the ASTContext to call the lookup table
@@ -1699,6 +1716,16 @@ NominalTypeDecl::lookupDirect(ObjCSelector selector, bool isInstance) {
16991716
return stored.Methods;
17001717
}
17011718

1719+
/// Is the new method an async alternative of any existing method, or vice
1720+
/// versa?
1721+
static bool isAnAsyncAlternative(AbstractFunctionDecl *newDecl,
1722+
llvm::TinyPtrVector<AbstractFunctionDecl *> &vec) {
1723+
return llvm::any_of(vec, [&](AbstractFunctionDecl *oldDecl) {
1724+
return newDecl->getAsyncAlternative(/*isKnownObjC=*/true) == oldDecl
1725+
|| oldDecl->getAsyncAlternative(/*isKnownObjC=*/true) == newDecl;
1726+
});
1727+
}
1728+
17021729
void NominalTypeDecl::recordObjCMethod(AbstractFunctionDecl *method,
17031730
ObjCSelector selector) {
17041731
if (!ObjCMethodLookup && !createObjCMethodLookup())
@@ -1714,12 +1741,11 @@ void NominalTypeDecl::recordObjCMethod(AbstractFunctionDecl *method,
17141741
return;
17151742

17161743
if (auto *sf = method->getParentSourceFile()) {
1717-
if (vec.size() == 1) {
1718-
// We have a conflict.
1719-
sf->ObjCMethodConflicts.push_back(std::make_tuple(this, selector,
1720-
isInstanceMethod));
1721-
} if (vec.empty()) {
1744+
if (vec.empty()) {
17221745
sf->ObjCMethodList.push_back(method);
1746+
} else if (!isa<ProtocolDecl>(this) || !isAnAsyncAlternative(method, vec)) {
1747+
// We have a conflict.
1748+
sf->ObjCMethodConflicts.insert({ this, selector, isInstanceMethod });
17231749
}
17241750
}
17251751

lib/ClangImporter/ClangImporter.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3435,11 +3435,16 @@ void ClangImporter::loadExtensions(NominalTypeDecl *nominal,
34353435
}
34363436

34373437
void ClangImporter::loadObjCMethods(
3438-
ClassDecl *classDecl,
3438+
NominalTypeDecl *typeDecl,
34393439
ObjCSelector selector,
34403440
bool isInstanceMethod,
34413441
unsigned previousGeneration,
34423442
llvm::TinyPtrVector<AbstractFunctionDecl *> &methods) {
3443+
// TODO: We don't currently need to load methods from imported ObjC protocols.
3444+
auto classDecl = dyn_cast<ClassDecl>(typeDecl);
3445+
if (!classDecl)
3446+
return;
3447+
34433448
const auto *objcClass =
34443449
dyn_cast_or_null<clang::ObjCInterfaceDecl>(classDecl->getClangDecl());
34453450
if (!objcClass)

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,7 +1052,8 @@ class DeclAndTypePrinter::Implementation
10521052
assert(!AvAttr->Rename.empty());
10531053

10541054
auto *renamedDecl = evaluateOrDefault(
1055-
getASTContext().evaluator, RenamedDeclRequest{D, AvAttr}, nullptr);
1055+
getASTContext().evaluator, RenamedDeclRequest{D, AvAttr, false},
1056+
nullptr);
10561057
if (renamedDecl) {
10571058
assert(shouldInclude(renamedDecl) &&
10581059
"ObjC printer logic mismatch with renamed decl");
@@ -2016,12 +2017,31 @@ auto DeclAndTypePrinter::getImpl() -> Implementation {
20162017
return Implementation(os, *this, outputLang);
20172018
}
20182019

2020+
static bool isAsyncAlternativeOfOtherDecl(const ValueDecl *VD) {
2021+
auto AFD = dyn_cast<AbstractFunctionDecl>(VD);
2022+
if (!AFD || !AFD->isAsyncContext() || !AFD->getObjCSelector())
2023+
return false;
2024+
2025+
auto type = AFD->getDeclContext()->getSelfNominalTypeDecl();
2026+
if (!type)
2027+
return false;
2028+
auto others = type->lookupDirect(AFD->getObjCSelector(),
2029+
AFD->isInstanceMember());
2030+
2031+
for (auto other : others)
2032+
if (other->getAsyncAlternative() == AFD)
2033+
return true;
2034+
2035+
return false;
2036+
}
2037+
20192038
bool DeclAndTypePrinter::shouldInclude(const ValueDecl *VD) {
20202039
return !VD->isInvalid() &&
20212040
(outputLang == OutputLanguageMode::Cxx
20222041
? cxx_translation::isVisibleToCxx(VD, minRequiredAccess)
20232042
: isVisibleToObjC(VD, minRequiredAccess)) &&
2024-
!VD->getAttrs().hasAttribute<ImplementationOnlyAttr>();
2043+
!VD->getAttrs().hasAttribute<ImplementationOnlyAttr>() &&
2044+
!isAsyncAlternativeOfOtherDecl(VD);
20252045
}
20262046

20272047
void DeclAndTypePrinter::print(const Decl *D) {

lib/Sema/TypeCheckAttr.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6177,7 +6177,8 @@ static bool parametersMatch(const AbstractFunctionDecl *a,
61776177

61786178
ValueDecl *RenamedDeclRequest::evaluate(Evaluator &evaluator,
61796179
const ValueDecl *attached,
6180-
const AvailableAttr *attr) const {
6180+
const AvailableAttr *attr,
6181+
bool isKnownObjC) const {
61816182
if (!attached || !attr)
61826183
return nullptr;
61836184

@@ -6208,7 +6209,7 @@ ValueDecl *RenamedDeclRequest::evaluate(Evaluator &evaluator,
62086209
auto minAccess = AccessLevel::Private;
62096210
if (attached->getModuleContext()->isExternallyConsumed())
62106211
minAccess = AccessLevel::Public;
6211-
bool attachedIsObjcVisible =
6212+
bool attachedIsObjcVisible = isKnownObjC ||
62126213
objc_translation::isVisibleToObjC(attached, minAccess);
62136214

62146215
SmallVector<ValueDecl *, 4> lookupResults;

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,11 +2422,8 @@ bool swift::diagnoseUnintendedObjCMethodOverrides(SourceFile &sf) {
24222422
/// Retrieve the source file for the given Objective-C member conflict.
24232423
static TinyPtrVector<AbstractFunctionDecl *>
24242424
getObjCMethodConflictDecls(const SourceFile::ObjCMethodConflict &conflict) {
2425-
NominalTypeDecl *typeDecl = std::get<0>(conflict);
2426-
ObjCSelector selector = std::get<1>(conflict);
2427-
bool isInstanceMethod = std::get<2>(conflict);
2428-
2429-
return typeDecl->lookupDirect(selector, isInstanceMethod);
2425+
return conflict.typeDecl->lookupDirect(conflict.selector,
2426+
conflict.isInstanceMethod);
24302427
}
24312428

24322429
static ObjCAttr *getObjCAttrIfFromAccessNote(ValueDecl *VD) {
@@ -2452,7 +2449,8 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) {
24522449
// Sort the set of conflicts so we get a deterministic order for
24532450
// diagnostics. We use the first conflicting declaration in each set to
24542451
// perform the sort.
2455-
auto localConflicts = sf.ObjCMethodConflicts;
2452+
llvm::SmallVector<SourceFile::ObjCMethodConflict, 4> localConflicts;
2453+
llvm::copy(sf.ObjCMethodConflicts, std::back_inserter(localConflicts));
24562454
std::sort(localConflicts.begin(), localConflicts.end(),
24572455
[&](const SourceFile::ObjCMethodConflict &lhs,
24582456
const SourceFile::ObjCMethodConflict &rhs) {
@@ -2463,9 +2461,6 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) {
24632461
// Diagnose each conflict.
24642462
bool anyConflicts = false;
24652463
for (const auto &conflict : localConflicts) {
2466-
NominalTypeDecl *tyDecl = std::get<0>(conflict);
2467-
ObjCSelector selector = std::get<1>(conflict);
2468-
24692464
auto methods = getObjCMethodConflictDecls(conflict);
24702465

24712466
// Erase any invalid or stub declarations. We don't want to complain about
@@ -2545,10 +2540,10 @@ bool swift::diagnoseObjCMethodConflicts(SourceFile &sf) {
25452540
: diag::objc_redecl,
25462541
diagInfo.first, diagInfo.second,
25472542
origDiagInfo.first, origDiagInfo.second,
2548-
selector);
2543+
conflict.selector);
25492544

25502545
// Protocols weren't checked for selector conflicts in 5.0.
2551-
diag.warnUntilSwiftVersionIf(!isa<ClassDecl>(tyDecl), 6);
2546+
diag.warnUntilSwiftVersionIf(!isa<ClassDecl>(conflict.typeDecl), 6);
25522547

25532548
auto objcAttr = getObjCAttrIfFromAccessNote(conflictingDecl);
25542549
swift::softenIfAccessNote(conflictingDecl, objcAttr, diag);

0 commit comments

Comments
 (0)