Skip to content

Commit a67c7f7

Browse files
committed
Sema: Refactor CheckInconsistentImplementationOnlyImportsRequest to make the inconsistency detection general so that it can be reused for checking for inconsistent @_weakLinked imports.
1 parent 7106c60 commit a67c7f7

File tree

1 file changed

+55
-46
lines changed

1 file changed

+55
-46
lines changed

Diff for: lib/Sema/ImportResolution.cpp

+55-46
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,57 @@ void UnboundImport::diagnoseInvalidAttr(DeclAttrKind attrKind,
693693
attr->setInvalid();
694694
}
695695

696+
/// Finds all import declarations for a single module that inconsistently match
697+
/// \c predicate and passes each pair of inconsistent imports to \c diagnose.
698+
template <typename Pred, typename Diag>
699+
static void findInconsistentImports(ModuleDecl *mod, Pred predicate,
700+
Diag diagnose) {
701+
llvm::DenseMap<ModuleDecl *, const ImportDecl *> matchingImports;
702+
llvm::DenseMap<ModuleDecl *, std::vector<const ImportDecl *>> otherImports;
703+
704+
for (const FileUnit *file : mod->getFiles()) {
705+
auto *SF = dyn_cast<SourceFile>(file);
706+
if (!SF)
707+
continue;
708+
709+
for (auto *topLevelDecl : SF->getTopLevelDecls()) {
710+
auto *nextImport = dyn_cast<ImportDecl>(topLevelDecl);
711+
if (!nextImport)
712+
continue;
713+
714+
ModuleDecl *module = nextImport->getModule();
715+
if (!module)
716+
continue;
717+
718+
if (predicate(nextImport)) {
719+
// We found a matching import.
720+
bool isNew = matchingImports.insert({module, nextImport}).second;
721+
if (!isNew)
722+
continue;
723+
724+
auto seenOtherImportPosition = otherImports.find(module);
725+
if (seenOtherImportPosition != otherImports.end()) {
726+
for (auto *seenOtherImport : seenOtherImportPosition->getSecond())
727+
diagnose(seenOtherImport, nextImport);
728+
729+
// We're done with these; keep the map small if possible.
730+
otherImports.erase(seenOtherImportPosition);
731+
}
732+
continue;
733+
}
734+
735+
// We saw a non-matching import. Is that in conflict with what we've seen?
736+
if (auto *seenMatchingImport = matchingImports.lookup(module)) {
737+
diagnose(nextImport, seenMatchingImport);
738+
continue;
739+
}
740+
741+
// Otherwise, record it for later.
742+
otherImports[module].push_back(nextImport);
743+
}
744+
}
745+
}
746+
696747
evaluator::SideEffect
697748
CheckInconsistentImplementationOnlyImportsRequest::evaluate(
698749
Evaluator &evaluator, ModuleDecl *mod) const {
@@ -724,53 +775,11 @@ CheckInconsistentImplementationOnlyImportsRequest::evaluate(
724775
diag::implementation_only_conflict_here);
725776
};
726777

727-
llvm::DenseMap<ModuleDecl *, std::vector<const ImportDecl *>> normalImports;
728-
llvm::DenseMap<ModuleDecl *, const ImportDecl *> implementationOnlyImports;
729-
730-
for (const FileUnit *file : mod->getFiles()) {
731-
auto *SF = dyn_cast<SourceFile>(file);
732-
if (!SF)
733-
continue;
734-
735-
for (auto *topLevelDecl : SF->getTopLevelDecls()) {
736-
auto *nextImport = dyn_cast<ImportDecl>(topLevelDecl);
737-
if (!nextImport)
738-
continue;
739-
740-
ModuleDecl *module = nextImport->getModule();
741-
if (!module)
742-
continue;
743-
744-
if (nextImport->getAttrs().hasAttribute<ImplementationOnlyAttr>()) {
745-
// We saw an implementation-only import.
746-
bool isNew =
747-
implementationOnlyImports.insert({module, nextImport}).second;
748-
if (!isNew)
749-
continue;
750-
751-
auto seenNormalImportPosition = normalImports.find(module);
752-
if (seenNormalImportPosition != normalImports.end()) {
753-
for (auto *seenNormalImport : seenNormalImportPosition->getSecond())
754-
diagnose(seenNormalImport, nextImport);
755-
756-
// We're done with these; keep the map small if possible.
757-
normalImports.erase(seenNormalImportPosition);
758-
}
759-
continue;
760-
}
761-
762-
// We saw a non-implementation-only import. Is that in conflict with what
763-
// we've seen?
764-
if (auto *seenImplementationOnlyImport =
765-
implementationOnlyImports.lookup(module)) {
766-
diagnose(nextImport, seenImplementationOnlyImport);
767-
continue;
768-
}
778+
auto predicate = [](ImportDecl *decl) {
779+
return decl->getAttrs().hasAttribute<ImplementationOnlyAttr>();
780+
};
769781

770-
// Otherwise, record it for later.
771-
normalImports[module].push_back(nextImport);
772-
}
773-
}
782+
findInconsistentImports(mod, predicate, diagnose);
774783
return {};
775784
}
776785

0 commit comments

Comments
 (0)