Skip to content

Commit 74f97d4

Browse files
authored
Merge pull request #60519 from tshortli/inconsistent-weak-linked-import
Sema: Diagnose inconsistent use of `@_weakLinked` import
2 parents c0e652b + 1739528 commit 74f97d4

File tree

14 files changed

+285
-87
lines changed

14 files changed

+285
-87
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2978,6 +2978,13 @@ ERROR(implementation_only_override_import_without_attr,none,
29782978
"override of %0 imported as implementation-only must be declared "
29792979
"'@_implementationOnly'", (DescriptiveDeclKind))
29802980

2981+
ERROR(import_attr_conflict,none,
2982+
"%0 inconsistently imported with %1",
2983+
(Identifier, DeclAttribute))
2984+
NOTE(import_attr_conflict_here,none,
2985+
"imported with %0 here",
2986+
(DeclAttribute))
2987+
29812988
// Derived conformances
29822989
ERROR(cannot_synthesize_init_in_extension_of_nonfinal,none,
29832990
"implementation of %0 for non-final class cannot be automatically "

include/swift/AST/Import.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ enum class ImportFlags {
9494
/// \see ImportFlags
9595
using ImportOptions = OptionSet<ImportFlags>;
9696

97+
void simple_display(llvm::raw_ostream &out, ImportOptions options);
98+
9799
// MARK: - Import Paths
98100

99101
namespace detail {

include/swift/AST/SourceFile.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,16 @@ class SourceFile final : public FileUnit {
174174
ParserStatePtr DelayedParserState =
175175
ParserStatePtr(/*ptr*/ nullptr, /*deleter*/ nullptr);
176176

177+
friend class HasImportsMatchingFlagRequest;
178+
179+
/// Indicates which import options have valid caches. Storage for
180+
/// \c HasImportsMatchingFlagRequest.
181+
ImportOptions validCachedImportOptions;
182+
183+
/// The cached computation of which import flags are present in the file.
184+
/// Storage for \c HasImportsMatchingFlagRequest.
185+
ImportOptions cachedImportOptions;
186+
177187
friend ASTContext;
178188

179189
public:
@@ -342,9 +352,9 @@ class SourceFile final : public FileUnit {
342352
hasTestableOrPrivateImport(AccessLevel accessLevel, const ValueDecl *ofDecl,
343353
ImportQueryKind kind = TestableAndPrivate) const;
344354

345-
/// Does this source file have any implementation-only imports?
355+
/// Does this source file have any imports with \c flag?
346356
/// If not, we can fast-path module checks.
347-
bool hasImplementationOnlyImports() const;
357+
bool hasImportsWithFlag(ImportFlags flag) const;
348358

349359
/// Get the most permissive restriction applied to the imports of \p module.
350360
RestrictedImportKind getRestrictedImportKind(const ModuleDecl *module) const;

include/swift/AST/TypeCheckRequests.h

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3202,21 +3202,24 @@ class ModuleImplicitImportsRequest
32023202
bool isCached() const { return true; }
32033203
};
32043204

3205-
/// Checks whether a file performs an implementation-only import.
3206-
class HasImplementationOnlyImportsRequest
3207-
: public SimpleRequest<HasImplementationOnlyImportsRequest,
3208-
bool(SourceFile *), RequestFlags::Cached> {
3205+
/// Checks whether a file contains any import declarations with the given flag.
3206+
class HasImportsMatchingFlagRequest
3207+
: public SimpleRequest<HasImportsMatchingFlagRequest,
3208+
bool(SourceFile *, ImportFlags),
3209+
RequestFlags::SeparatelyCached> {
32093210
public:
32103211
using SimpleRequest::SimpleRequest;
32113212

32123213
private:
32133214
friend SimpleRequest;
32143215

3215-
bool evaluate(Evaluator &evaluator, SourceFile *SF) const;
3216+
bool evaluate(Evaluator &evaluator, SourceFile *SF, ImportFlags flag) const;
32163217

32173218
public:
32183219
// Cached.
32193220
bool isCached() const { return true; }
3221+
Optional<bool> getCachedResult() const;
3222+
void cacheResult(bool value) const;
32203223
};
32213224

32223225
/// Get the library level of a module.
@@ -3260,15 +3263,15 @@ class ResolveTypeRequest
32603263
void simple_display(llvm::raw_ostream &out, const TypeResolution *resolution);
32613264
SourceLoc extractNearestSourceLoc(const TypeRepr *repr);
32623265

3263-
/// Checks to see if any of the imports in a module use `@_implementationOnly`
3266+
/// Checks to see if any of the imports in a module use \c @_implementationOnly
32643267
/// in one file and not in another.
32653268
///
32663269
/// Like redeclaration checking, but for imports.
32673270
///
32683271
/// This is a request purely to ensure that we don't need to perform the same
32693272
/// checking for each file we resolve imports for.
32703273
/// FIXME: Once import resolution operates at module-level, this checking can
3271-
/// integrated into it.
3274+
/// be integrated into it.
32723275
class CheckInconsistentImplementationOnlyImportsRequest
32733276
: public SimpleRequest<CheckInconsistentImplementationOnlyImportsRequest,
32743277
evaluator::SideEffect(ModuleDecl *),
@@ -3286,6 +3289,32 @@ class CheckInconsistentImplementationOnlyImportsRequest
32863289
bool isCached() const { return true; }
32873290
};
32883291

3292+
/// Checks to see if any of the imports in a module use \c @_weakLinked
3293+
/// in one file and not in another.
3294+
///
3295+
/// Like redeclaration checking, but for imports.
3296+
///
3297+
/// This is a request purely to ensure that we don't need to perform the same
3298+
/// checking for each file we resolve imports for.
3299+
/// FIXME: Once import resolution operates at module-level, this checking can
3300+
/// be integrated into it.
3301+
class CheckInconsistentWeakLinkedImportsRequest
3302+
: public SimpleRequest<CheckInconsistentWeakLinkedImportsRequest,
3303+
evaluator::SideEffect(ModuleDecl *),
3304+
RequestFlags::Cached> {
3305+
public:
3306+
using SimpleRequest::SimpleRequest;
3307+
3308+
private:
3309+
friend SimpleRequest;
3310+
3311+
evaluator::SideEffect evaluate(Evaluator &evaluator, ModuleDecl *mod) const;
3312+
3313+
public:
3314+
// Cached.
3315+
bool isCached() const { return true; }
3316+
};
3317+
32893318
/// Retrieves the primary source files in the main module.
32903319
// FIXME: This isn't really a type-checking request, if we ever split off a
32913320
// zone for more basic AST requests, this should be moved there.

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ SWIFT_REQUEST(TypeChecker, CallerSideDefaultArgExprRequest,
3333
Expr *(DefaultArgumentExpr *), SeparatelyCached, NoLocationInfo)
3434
SWIFT_REQUEST(TypeChecker, CheckInconsistentImplementationOnlyImportsRequest,
3535
evaluator::SideEffect(ModuleDecl *), Cached, NoLocationInfo)
36+
SWIFT_REQUEST(TypeChecker, CheckInconsistentWeakLinkedImportsRequest,
37+
evaluator::SideEffect(ModuleDecl *), Cached, NoLocationInfo)
3638
SWIFT_REQUEST(TypeChecker, CheckRedeclarationRequest,
3739
evaluator::SideEffect(ValueDecl *),
3840
Uncached, NoLocationInfo)
@@ -169,8 +171,8 @@ SWIFT_REQUEST(TypeChecker, HasCircularInheritedProtocolsRequest,
169171
bool(ProtocolDecl *), Cached, NoLocationInfo)
170172
SWIFT_REQUEST(TypeChecker, HasCircularRawValueRequest,
171173
bool(EnumDecl *), Cached, NoLocationInfo)
172-
SWIFT_REQUEST(TypeChecker, HasImplementationOnlyImportsRequest,
173-
bool(SourceFile *), Cached, NoLocationInfo)
174+
SWIFT_REQUEST(TypeChecker, HasImportsMatchingFlagRequest,
175+
bool(SourceFile *, ImportOptions), Cached, NoLocationInfo)
174176
SWIFT_REQUEST(TypeChecker, ModuleLibraryLevelRequest,
175177
LibraryLevel(ModuleDecl *), Cached, NoLocationInfo)
176178
SWIFT_REQUEST(TypeChecker, InferredGenericSignatureRequest,

lib/AST/Module.cpp

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2389,19 +2389,64 @@ void SourceFile::setImportUsedPreconcurrency(
23892389
PreconcurrencyImportsUsed.insert(import);
23902390
}
23912391

2392-
bool HasImplementationOnlyImportsRequest::evaluate(Evaluator &evaluator,
2393-
SourceFile *SF) const {
2394-
return llvm::any_of(SF->getImports(),
2395-
[](AttributedImport<ImportedModule> desc) {
2396-
return desc.options.contains(ImportFlags::ImplementationOnly);
2397-
});
2392+
bool HasImportsMatchingFlagRequest::evaluate(Evaluator &evaluator,
2393+
SourceFile *SF,
2394+
ImportFlags flag) const {
2395+
for (auto desc : SF->getImports()) {
2396+
if (desc.options.contains(flag))
2397+
return true;
2398+
}
2399+
return false;
2400+
}
2401+
2402+
Optional<bool> HasImportsMatchingFlagRequest::getCachedResult() const {
2403+
SourceFile *sourceFile = std::get<0>(getStorage());
2404+
ImportFlags flag = std::get<1>(getStorage());
2405+
if (sourceFile->validCachedImportOptions.contains(flag))
2406+
return sourceFile->cachedImportOptions.contains(flag);
2407+
2408+
return None;
2409+
}
2410+
2411+
void HasImportsMatchingFlagRequest::cacheResult(bool value) const {
2412+
SourceFile *sourceFile = std::get<0>(getStorage());
2413+
ImportFlags flag = std::get<1>(getStorage());
2414+
2415+
sourceFile->validCachedImportOptions |= flag;
2416+
if (value)
2417+
sourceFile->cachedImportOptions |= flag;
2418+
}
2419+
2420+
void swift::simple_display(llvm::raw_ostream &out, ImportOptions options) {
2421+
using Flag = std::pair<ImportFlags, StringRef>;
2422+
Flag possibleFlags[] = {
2423+
#define FLAG(Name) {ImportFlags::Name, #Name},
2424+
FLAG(Exported)
2425+
FLAG(Testable)
2426+
FLAG(PrivateImport)
2427+
FLAG(ImplementationOnly)
2428+
FLAG(SPIAccessControl)
2429+
FLAG(Preconcurrency)
2430+
FLAG(WeakLinked)
2431+
FLAG(Reserved)
2432+
#undef FLAG
2433+
};
2434+
2435+
auto flagsToPrint = llvm::make_filter_range(
2436+
possibleFlags, [&](Flag flag) { return options & flag.first; });
2437+
2438+
out << "{ ";
2439+
interleave(
2440+
flagsToPrint, [&](Flag flag) { out << flag.second; },
2441+
[&] { out << ", "; });
2442+
out << " }";
23982443
}
23992444

2400-
bool SourceFile::hasImplementationOnlyImports() const {
2445+
bool SourceFile::hasImportsWithFlag(ImportFlags flag) const {
24012446
auto &ctx = getASTContext();
24022447
auto *mutableThis = const_cast<SourceFile *>(this);
24032448
return evaluateOrDefault(
2404-
ctx.evaluator, HasImplementationOnlyImportsRequest{mutableThis}, false);
2449+
ctx.evaluator, HasImportsMatchingFlagRequest{mutableThis, flag}, false);
24052450
}
24062451

24072452
bool SourceFile::hasTestableOrPrivateImport(

lib/AST/TypeCheckRequests.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,6 +1474,12 @@ void swift::simple_display(llvm::raw_ostream &out,
14741474
out << ")";
14751475
}
14761476

1477+
if (import.options.contains(ImportFlags::Preconcurrency))
1478+
out << " preconcurrency";
1479+
1480+
if (import.options.contains(ImportFlags::WeakLinked))
1481+
out << " weak-linked";
1482+
14771483
out << " ]";
14781484
}
14791485

0 commit comments

Comments
 (0)