Skip to content

Commit 63e4ec6

Browse files
authored
Merge pull request #30038 from hamishknight/plenty-of-scope-for-requestification
Requestify scoped import validation
2 parents cc8db01 + 0c785aa commit 63e4ec6

File tree

16 files changed

+195
-121
lines changed

16 files changed

+195
-121
lines changed

include/swift/AST/ClangModuleLoader.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ namespace clang {
2020
class ASTContext;
2121
class CompilerInstance;
2222
class Decl;
23+
class Module;
2324
class Preprocessor;
2425
class Sema;
2526
class TargetInfo;
@@ -125,6 +126,10 @@ class ClangModuleLoader : public ModuleLoader {
125126
/// Objective-C header files.
126127
virtual ModuleDecl *getImportedHeaderModule() const = 0;
127128

129+
/// Retrieves the Swift wrapper for the given Clang module, creating
130+
/// it if necessary.
131+
virtual ModuleDecl *getWrapperForModule(const clang::Module *mod) const = 0;
132+
128133
/// Adds a new search path to the Clang CompilerInstance, as if specified with
129134
/// -I or -F.
130135
///

include/swift/AST/Decl.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,8 +1527,6 @@ class ImportDecl final : public Decl,
15271527

15281528
/// The resolved module.
15291529
ModuleDecl *Mod = nullptr;
1530-
/// The resolved decls if this is a decl import.
1531-
ArrayRef<ValueDecl *> Decls;
15321530

15331531
ImportDecl(DeclContext *DC, SourceLoc ImportLoc, ImportKind K,
15341532
SourceLoc KindLoc, ArrayRef<AccessPathElement> Path);
@@ -1581,8 +1579,9 @@ class ImportDecl final : public Decl,
15811579
ModuleDecl *getModule() const { return Mod; }
15821580
void setModule(ModuleDecl *M) { Mod = M; }
15831581

1584-
ArrayRef<ValueDecl *> getDecls() const { return Decls; }
1585-
void setDecls(ArrayRef<ValueDecl *> Ds) { Decls = Ds; }
1582+
/// For a scoped import such as 'import class Foundation.NSString', retrieve
1583+
/// the decls it references. Otherwise, returns an empty array.
1584+
ArrayRef<ValueDecl *> getDecls() const;
15861585

15871586
const clang::Module *getClangModule() const {
15881587
return getClangNode().getClangModule();

include/swift/AST/Module.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,11 @@ class ModuleDecl : public DeclContext, public TypeDecl {
355355
Bits.ModuleDecl.IsNonSwiftModule = flag;
356356
}
357357

358+
/// Retrieve the top-level module. If this module is already top-level, this
359+
/// returns itself. If this is a submodule such as \c Foo.Bar.Baz, this
360+
/// returns the module \c Foo.
361+
ModuleDecl *getTopLevelModule();
362+
358363
bool isResilient() const {
359364
return getResilienceStrategy() != ResilienceStrategy::Default;
360365
}

include/swift/AST/TypeCheckRequests.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,6 +2073,32 @@ class TypeEraserHasViableInitRequest
20732073
bool isCached() const { return true; }
20742074
};
20752075

2076+
/// Looks up the decls that a scoped import references, ensuring the import is
2077+
/// valid.
2078+
///
2079+
/// A "scoped import" is an import which only covers one particular
2080+
/// declaration, such as:
2081+
///
2082+
/// import class Foundation.NSString
2083+
///
2084+
class ScopedImportLookupRequest
2085+
: public SimpleRequest<ScopedImportLookupRequest,
2086+
ArrayRef<ValueDecl *>(ImportDecl *),
2087+
CacheKind::Cached> {
2088+
public:
2089+
using SimpleRequest::SimpleRequest;
2090+
2091+
private:
2092+
friend SimpleRequest;
2093+
2094+
llvm::Expected<ArrayRef<ValueDecl *>> evaluate(Evaluator &evaluator,
2095+
ImportDecl *import) const;
2096+
2097+
public:
2098+
// Cached.
2099+
bool isCached() const { return true; }
2100+
};
2101+
20762102
// Allow AnyValue to compare two Type values, even though Type doesn't
20772103
// support ==.
20782104
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,5 @@ SWIFT_REQUEST(TypeChecker, ValueWitnessRequest,
225225
SWIFT_REQUEST(TypeChecker, PatternTypeRequest,
226226
Type(ContextualPattern),
227227
Cached, HasNearestLocation)
228+
SWIFT_REQUEST(TypeChecker, ScopedImportLookupRequest,
229+
ArrayRef<ValueDecl *>(ImportDecl *), Cached, NoLocationInfo)

include/swift/ClangImporter/ClangImporter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,10 @@ class ClangImporter final : public ClangModuleLoader {
328328
/// \sa importHeader
329329
ModuleDecl *getImportedHeaderModule() const override;
330330

331+
/// Retrieves the Swift wrapper for the given Clang module, creating
332+
/// it if necessary.
333+
ModuleDecl *getWrapperForModule(const clang::Module *mod) const override;
334+
331335
std::string getBridgingHeaderContents(StringRef headerPath, off_t &fileSize,
332336
time_t &fileModTime);
333337

lib/AST/Decl.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,17 @@ ImportDecl::findBestImportKind(ArrayRef<ValueDecl *> Decls) {
11741174
return FirstKind;
11751175
}
11761176

1177+
ArrayRef<ValueDecl *> ImportDecl::getDecls() const {
1178+
// If this isn't a scoped import, there's nothing to do.
1179+
if (getImportKind() == ImportKind::Module)
1180+
return {};
1181+
1182+
auto &ctx = getASTContext();
1183+
auto *mutableThis = const_cast<ImportDecl *>(this);
1184+
return evaluateOrDefault(ctx.evaluator,
1185+
ScopedImportLookupRequest{mutableThis}, {});
1186+
}
1187+
11771188
void NominalTypeDecl::setConformanceLoader(LazyMemberLoader *lazyLoader,
11781189
uint64_t contextData) {
11791190
assert(!Bits.NominalTypeDecl.HasLazyConformances &&

lib/AST/Module.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/ASTPrinter.h"
2222
#include "swift/AST/ASTWalker.h"
2323
#include "swift/AST/Builtins.h"
24+
#include "swift/AST/ClangModuleLoader.h"
2425
#include "swift/AST/DiagnosticsSema.h"
2526
#include "swift/AST/ExistentialLayout.h"
2627
#include "swift/AST/FileUnit.h"
@@ -440,6 +441,21 @@ SourceLookupCache &ModuleDecl::getSourceLookupCache() const {
440441
return *Cache;
441442
}
442443

444+
ModuleDecl *ModuleDecl::getTopLevelModule() {
445+
// If this is a Clang module, ask the Clang importer for the top-level module.
446+
// We need to check isNonSwiftModule() to ensure we don't look through
447+
// overlays.
448+
if (isNonSwiftModule()) {
449+
if (auto *underlying = findUnderlyingClangModule()) {
450+
auto &ctx = getASTContext();
451+
auto *clangLoader = ctx.getClangModuleLoader();
452+
return clangLoader->getWrapperForModule(underlying->getTopLevelModule());
453+
}
454+
}
455+
// Swift modules don't currently support submodules.
456+
return this;
457+
}
458+
443459
static bool isParsedModule(const ModuleDecl *mod) {
444460
// FIXME: If we ever get mixed modules that contain both SourceFiles and other
445461
// kinds of file units, this will break; there all callers of this function should

lib/ClangImporter/ClangImporter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,6 +1858,10 @@ ModuleDecl *ClangImporter::getImportedHeaderModule() const {
18581858
return Impl.ImportedHeaderUnit->getParentModule();
18591859
}
18601860

1861+
ModuleDecl *ClangImporter::getWrapperForModule(const clang::Module *mod) const {
1862+
return Impl.getWrapperForModule(mod)->getParentModule();
1863+
}
1864+
18611865
PlatformAvailability::PlatformAvailability(LangOptions &langOpts)
18621866
: platformKind(targetPlatform(langOpts)) {
18631867
switch (platformKind) {

0 commit comments

Comments
 (0)