@@ -693,6 +693,57 @@ void UnboundImport::diagnoseInvalidAttr(DeclAttrKind attrKind,
693
693
attr->setInvalid ();
694
694
}
695
695
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
+
696
747
evaluator::SideEffect
697
748
CheckInconsistentImplementationOnlyImportsRequest::evaluate (
698
749
Evaluator &evaluator, ModuleDecl *mod) const {
@@ -724,53 +775,11 @@ CheckInconsistentImplementationOnlyImportsRequest::evaluate(
724
775
diag::implementation_only_conflict_here);
725
776
};
726
777
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
+ };
769
781
770
- // Otherwise, record it for later.
771
- normalImports[module].push_back (nextImport);
772
- }
773
- }
782
+ findInconsistentImports (mod, predicate, diagnose);
774
783
return {};
775
784
}
776
785
0 commit comments