@@ -849,18 +849,16 @@ ASTContext::ASTContext(
849
849
registerNameLookupRequestFunctions (evaluator);
850
850
851
851
// Register canImport module info.
852
- for (auto &info: SearchPathOpts.CanImportModuleInfo ) {
853
- addSucceededCanImportModule (info.ModuleName , false , info.Version );
854
- addSucceededCanImportModule (info.ModuleName , true , info.UnderlyingVersion );
855
- }
852
+ for (auto &info: SearchPathOpts.CanImportModuleInfo )
853
+ addSucceededCanImportModule (info.ModuleName , info.Version , info.UnderlyingVersion );
856
854
857
855
// Provide a default OnDiskOutputBackend if user didn't supply one.
858
856
if (!OutputBackend)
859
857
OutputBackend = llvm::makeIntrusiveRefCnt<llvm::vfs::OnDiskOutputBackend>();
858
+
860
859
// Insert all block list config paths.
861
- for (auto path: langOpts.BlocklistConfigFilePaths ) {
860
+ for (auto path: langOpts.BlocklistConfigFilePaths )
862
861
blockListConfig.addConfigureFilePath (path);
863
- }
864
862
}
865
863
866
864
void ASTContext::Implementation::dump (llvm::raw_ostream &os) const {
@@ -2655,34 +2653,25 @@ static bool isClangModuleVersion(const ModuleLoader::ModuleVersionInfo &info) {
2655
2653
}
2656
2654
}
2657
2655
2658
- static StringRef
2659
- getModuleVersionKindString (const ModuleLoader::ModuleVersionInfo &info) {
2660
- switch (info.getSourceKind ()) {
2661
- case ModuleLoader::ModuleVersionSourceKind::ClangModuleTBD:
2662
- return " Clang" ;
2663
- case ModuleLoader::ModuleVersionSourceKind::SwiftBinaryModule:
2664
- case ModuleLoader::ModuleVersionSourceKind::SwiftInterface:
2665
- return " Swift" ;
2666
- }
2667
- }
2668
-
2669
2656
void ASTContext::addSucceededCanImportModule (
2670
- StringRef moduleName, bool underlyingVersion,
2671
- const llvm::VersionTuple &versionInfo) {
2657
+ StringRef moduleName,
2658
+ const llvm::VersionTuple &versionInfo,
2659
+ const llvm::VersionTuple &underlyingVersionInfo) {
2660
+ // We have previously recorded a successful canImport
2661
+ // information for this module.
2662
+ if (CanImportModuleVersions.count (moduleName.str ()))
2663
+ return ;
2664
+
2672
2665
auto &entry = CanImportModuleVersions[moduleName.str ()];
2673
- if (!versionInfo.empty ()) {
2674
- if (underlyingVersion)
2675
- entry.UnderlyingVersion = versionInfo;
2676
- else
2677
- entry.Version = versionInfo;
2678
- }
2666
+ entry.Version = versionInfo;
2667
+ entry.UnderlyingVersion = underlyingVersionInfo;
2679
2668
}
2680
2669
2681
- bool ASTContext::canImportModuleImpl (ImportPath::Module ModuleName,
2682
- SourceLoc loc, llvm::VersionTuple version,
2683
- bool underlyingVersion ,
2684
- bool updateFailingList ,
2685
- llvm::VersionTuple &foundVersion ) const {
2670
+ bool ASTContext::canImportModuleImpl (
2671
+ ImportPath::Module ModuleName, SourceLoc loc, llvm::VersionTuple version,
2672
+ bool underlyingVersion, bool isSourceCanImport ,
2673
+ llvm::VersionTuple &foundVersion ,
2674
+ llvm::VersionTuple &foundUnderlyingClangVersion ) const {
2686
2675
SmallString<64 > FullModuleName;
2687
2676
ModuleName.getString (FullModuleName);
2688
2677
auto ModuleNameStr = FullModuleName.str ().str ();
@@ -2691,6 +2680,20 @@ bool ASTContext::canImportModuleImpl(ImportPath::Module ModuleName,
2691
2680
if (FailedModuleImportNames.count (ModuleNameStr))
2692
2681
return false ;
2693
2682
2683
+ auto missingVersion = [this , &loc, &ModuleName,
2684
+ &underlyingVersion]() -> bool {
2685
+ // The module version could not be parsed from the preferred source for
2686
+ // this query. Diagnose and return `true` to indicate that the unversioned module
2687
+ // will satisfy the query.
2688
+ auto mID = ModuleName[0 ];
2689
+ auto diagLoc = mID .Loc ;
2690
+ if (mID .Loc .isInvalid ())
2691
+ diagLoc = loc;
2692
+ Diags.diagnose (diagLoc, diag::cannot_find_project_version, mID .Item .str (),
2693
+ underlyingVersion);
2694
+ return true ;
2695
+ };
2696
+
2694
2697
// If this module has already been checked or there is information for the
2695
2698
// module from commandline, use that information instead of loading the
2696
2699
// module.
@@ -2699,35 +2702,95 @@ bool ASTContext::canImportModuleImpl(ImportPath::Module ModuleName,
2699
2702
if (version.empty ())
2700
2703
return true ;
2701
2704
2702
- if (underlyingVersion) {
2703
- if (!Found->second .UnderlyingVersion .empty ())
2704
- return version <= Found->second .UnderlyingVersion ;
2705
- } else {
2706
- if (!Found->second .Version .empty ())
2707
- return version <= Found->second .Version ;
2705
+ const auto &foundComparisonVersion = underlyingVersion
2706
+ ? Found->second .UnderlyingVersion
2707
+ : Found->second .Version ;
2708
+ if (!foundComparisonVersion.empty ())
2709
+ return version <= foundComparisonVersion;
2710
+ else
2711
+ return missingVersion ();
2712
+ }
2713
+
2714
+ // When looking up a module, each module importer will report back
2715
+ // if it finds a module with a specified version. This routine verifies
2716
+ // whether said version is valid and if it superceeds the best
2717
+ // previously-discovered version of this module found.
2718
+ auto validateVersion =
2719
+ [](const ModuleLoader::ModuleVersionInfo &bestVersionInfo,
2720
+ const ModuleLoader::ModuleVersionInfo &versionInfo,
2721
+ bool underlyingVersion) {
2722
+ if (!versionInfo.isValid ())
2723
+ return false ; // The loader didn't attempt to parse a version.
2724
+
2725
+ if (underlyingVersion && !isClangModuleVersion (versionInfo))
2726
+ return false ; // We're only matching Clang module versions.
2727
+
2728
+ if (bestVersionInfo.isValid () &&
2729
+ versionInfo.getSourceKind () <= bestVersionInfo.getSourceKind ())
2730
+ return false ; // This module version's source is lower priority.
2731
+
2732
+ return true ;
2733
+ };
2734
+
2735
+ // For each module loader, attempt to discover queried module,
2736
+ // along the way record the discovered module's version as well as
2737
+ // the discovered module's underlying Clang module's version.
2738
+ auto lookupVersionedModule =
2739
+ [&](ModuleLoader::ModuleVersionInfo &bestVersionInfo,
2740
+ ModuleLoader::ModuleVersionInfo &bestUnderlyingVersionInfo) -> bool {
2741
+ for (auto &importer : getImpl ().ModuleLoaders ) {
2742
+ ModuleLoader::ModuleVersionInfo versionInfo;
2743
+ if (!importer->canImportModule (ModuleName, loc, &versionInfo))
2744
+ continue ; // The loader can't find the module.
2745
+
2746
+ if (validateVersion (bestVersionInfo, versionInfo,
2747
+ /* underlyingVersion */ false ))
2748
+ bestVersionInfo = versionInfo;
2749
+ if (validateVersion (bestUnderlyingVersionInfo, versionInfo,
2750
+ /* underlyingVersion */ true ))
2751
+ bestUnderlyingVersionInfo = versionInfo;
2708
2752
}
2709
2753
2710
- // If the canImport information is coming from the command-line, then no
2711
- // need to continue the search, return false. For checking modules that are
2712
- // not passed from command-line, allow fallback to the module loading since
2713
- // this is not in a canImport request context that has already been resolved
2714
- // by scanner.
2715
- if (!SearchPathOpts.CanImportModuleInfo .empty ())
2754
+ if (!underlyingVersion && !bestVersionInfo.isValid ())
2716
2755
return false ;
2717
- }
2756
+
2757
+ if (underlyingVersion && !bestUnderlyingVersionInfo.isValid ())
2758
+ return false ;
2759
+
2760
+ foundVersion = bestVersionInfo.getVersion ();
2761
+ foundUnderlyingClangVersion = bestUnderlyingVersionInfo.getVersion ();
2762
+ return true ;
2763
+ };
2764
+
2765
+ // For queries which do not care about any kind of module information
2766
+ // such as e.g. `testImportModule`, simply return `true` as soon
2767
+ // as *any* loader can find the queried module.
2768
+ auto lookupModule = [&]() -> bool {
2769
+ for (auto &importer : getImpl ().ModuleLoaders ) {
2770
+ ModuleLoader::ModuleVersionInfo versionInfo;
2771
+ if (!importer->canImportModule (ModuleName, loc, &versionInfo))
2772
+ continue ; // The loader can't find the module.
2773
+ return true ;
2774
+ }
2775
+ return false ;
2776
+ };
2718
2777
2719
2778
if (version.empty ()) {
2720
2779
// If this module has already been successfully imported, it is importable.
2721
2780
if (getLoadedModule (ModuleName) != nullptr )
2722
2781
return true ;
2782
+
2783
+ if (!isSourceCanImport)
2784
+ return lookupModule ();
2785
+
2786
+ // Otherwise, ask whether any module loader can load the module,
2787
+ // and record the module version that the succeeding loader
2788
+ // observed.
2789
+ ModuleLoader::ModuleVersionInfo versionInfo, underlyingVersionInfo;
2790
+ if (lookupVersionedModule (versionInfo, underlyingVersionInfo))
2791
+ return true ;
2723
2792
2724
- // Otherwise, ask whether any module loader can load the module.
2725
- for (auto &importer : getImpl ().ModuleLoaders ) {
2726
- if (importer->canImportModule (ModuleName, loc, nullptr ))
2727
- return true ;
2728
- }
2729
-
2730
- if (updateFailingList)
2793
+ if (isSourceCanImport)
2731
2794
FailedModuleImportNames.insert (ModuleNameStr);
2732
2795
2733
2796
return false ;
@@ -2736,43 +2799,15 @@ bool ASTContext::canImportModuleImpl(ImportPath::Module ModuleName,
2736
2799
// We need to check whether the version of the module is high enough.
2737
2800
// Retrieve a module version from each module loader that can find the module
2738
2801
// and use the best source available for the query.
2739
- ModuleLoader::ModuleVersionInfo bestVersionInfo;
2740
- for (auto &importer : getImpl ().ModuleLoaders ) {
2741
- ModuleLoader::ModuleVersionInfo versionInfo;
2742
-
2743
- if (!importer->canImportModule (ModuleName, loc, &versionInfo))
2744
- continue ; // The loader can't find the module.
2745
-
2746
- if (!versionInfo.isValid ())
2747
- continue ; // The loader didn't attempt to parse a version.
2748
-
2749
- if (underlyingVersion && !isClangModuleVersion (versionInfo))
2750
- continue ; // We're only matching Clang module versions.
2751
-
2752
- if (bestVersionInfo.isValid () &&
2753
- versionInfo.getSourceKind () <= bestVersionInfo.getSourceKind ())
2754
- continue ; // This module version's source is lower priority.
2755
-
2756
- bestVersionInfo = versionInfo;
2757
- }
2758
-
2759
- if (!bestVersionInfo.isValid ())
2802
+ ModuleLoader::ModuleVersionInfo versionInfo, underlyingVersionInfo;
2803
+ if (!lookupVersionedModule (versionInfo, underlyingVersionInfo))
2760
2804
return false ;
2761
2805
2762
- if (bestVersionInfo.getVersion ().empty ()) {
2763
- // The module version could not be parsed from the preferred source for
2764
- // this query. Diagnose and treat the query as if it succeeded.
2765
- auto mID = ModuleName[0 ];
2766
- auto diagLoc = mID .Loc ;
2767
- if (mID .Loc .isInvalid ())
2768
- diagLoc = loc;
2769
- Diags.diagnose (diagLoc, diag::cannot_find_project_version,
2770
- getModuleVersionKindString (bestVersionInfo), mID .Item .str ());
2771
- return true ;
2772
- }
2806
+ const auto &queryVersion = underlyingVersion ? underlyingVersionInfo : versionInfo;
2807
+ if (queryVersion.getVersion ().empty ())
2808
+ return missingVersion ();
2773
2809
2774
- foundVersion = bestVersionInfo.getVersion ();
2775
- return version <= bestVersionInfo.getVersion ();
2810
+ return version <= queryVersion.getVersion ();
2776
2811
}
2777
2812
2778
2813
void ASTContext::forEachCanImportVersionCheck (
@@ -2787,22 +2822,26 @@ bool ASTContext::canImportModule(ImportPath::Module moduleName, SourceLoc loc,
2787
2822
llvm::VersionTuple version,
2788
2823
bool underlyingVersion) {
2789
2824
llvm::VersionTuple versionInfo;
2825
+ llvm::VersionTuple underlyingVersionInfo;
2790
2826
if (!canImportModuleImpl (moduleName, loc, version, underlyingVersion, true ,
2791
- versionInfo))
2827
+ versionInfo, underlyingVersionInfo ))
2792
2828
return false ;
2793
2829
2794
2830
SmallString<64 > fullModuleName;
2795
2831
moduleName.getString (fullModuleName);
2796
- addSucceededCanImportModule (fullModuleName, underlyingVersion, versionInfo);
2832
+
2833
+ addSucceededCanImportModule (fullModuleName, versionInfo, underlyingVersionInfo);
2797
2834
return true ;
2798
2835
}
2799
2836
2800
2837
bool ASTContext::testImportModule (ImportPath::Module ModuleName,
2801
2838
llvm::VersionTuple version,
2802
2839
bool underlyingVersion) const {
2803
2840
llvm::VersionTuple versionInfo;
2841
+ llvm::VersionTuple underlyingVersionInfo;
2804
2842
return canImportModuleImpl (ModuleName, SourceLoc (), version,
2805
- underlyingVersion, false , versionInfo);
2843
+ underlyingVersion, false , versionInfo,
2844
+ underlyingVersionInfo);
2806
2845
}
2807
2846
2808
2847
ModuleDecl *
0 commit comments