@@ -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+
696747evaluator::SideEffect
697748CheckInconsistentImplementationOnlyImportsRequest::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