Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@
> [!NOTE]
> This is in reverse chronological order, so newer entries are added to the top.

## Swift (next)

* Concurrency-related APIs like `Task` and string-processing-related APIs like `Regex` can now be qualified by the name
`Swift`, just like other standard library APIs:

```swift
Swift.Task { ... }
func match(_ regex: Swift.Regex<(Substring)>) { ... }
```

The old `_Concurrency` and `_StringProcessing` names are still supported for backwards compatibility, and Embedded
Swift projects must still explicitly `import _Concurrency` to access concurrency APIs.

## Swift 6.2

* [SE-0472][]:
Expand Down
4 changes: 4 additions & 0 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1294,6 +1294,10 @@ class ASTContext final {
return const_cast<ASTContext *>(this)->getStdlibModule(false);
}

/// Names of underscored modules whose contents, if imported, should be
/// treated as separately-imported overlays of the standard library module.
ArrayRef<Identifier> StdlibOverlayNames;

/// Insert an externally-sourced module into the set of known loaded modules
/// in this context.
void addLoadedModule(ModuleDecl *M);
Expand Down
6 changes: 6 additions & 0 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,12 @@ ASTContext::ASTContext(
#define IDENTIFIER_WITH_NAME(Name, IdStr) Id_##Name = getIdentifier(IdStr);
#include "swift/AST/KnownIdentifiers.def"

Identifier stdlibOverlayNames[] = {
Id_Concurrency,
Id_StringProcessing
};
StdlibOverlayNames = AllocateCopy(stdlibOverlayNames);

// Record the initial set of search paths.
for (const auto &path : SearchPathOpts.getImportSearchPaths())
getImpl().SearchPathsSet[path.Path] |= SearchPathKind::Import;
Expand Down
10 changes: 10 additions & 0 deletions lib/AST/DeclContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,16 @@ DeclContext *DeclContext::getModuleScopeContext() const {

void DeclContext::getSeparatelyImportedOverlays(
ModuleDecl *declaring, SmallVectorImpl<ModuleDecl *> &overlays) const {
if (declaring->isStdlibModule()) {
auto &ctx = getASTContext();
for (auto overlayName: ctx.StdlibOverlayNames) {
if (auto module = ctx.getLoadedModule(overlayName))
overlays.push_back(module);
}
overlays.push_back(declaring);
return;
}

if (auto SF = getOutermostParentSourceFile())
SF->getSeparatelyImportedOverlays(declaring, overlays);
}
Expand Down
50 changes: 35 additions & 15 deletions lib/AST/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2374,28 +2374,41 @@ void ModuleDecl::findDeclaredCrossImportOverlaysTransitive(
if (auto *clangModule = getUnderlyingModuleIfOverlay())
worklist.push_back(clangModule);

auto addOverlay = [&](Identifier overlay) {
// We don't present non-underscored overlays as part of the underlying
// module, so ignore them.
if (!overlay.hasUnderscoredNaming())
return;

ModuleDecl *overlayMod =
getASTContext().getModuleByIdentifier(overlay);
if (!overlayMod && overlayMod != this)
return;

if (seen.insert(overlayMod).second) {
overlayModules.push_back(overlayMod);
worklist.push_back(overlayMod);
if (auto *clangModule = overlayMod->getUnderlyingModuleIfOverlay())
worklist.push_back(clangModule);
}
};

while (!worklist.empty()) {
ModuleDecl *current = worklist.back();
worklist.pop_back();

if (current->isStdlibModule()) {
for (auto overlay : getASTContext().StdlibOverlayNames) {
addOverlay(overlay);
}
}

for (auto &pair: current->declaredCrossImports) {
Identifier &bystander = std::get<0>(pair);
for (auto *file: std::get<1>(pair)) {
auto overlays = file->getOverlayModuleNames(current, unused, bystander);
for (Identifier overlay: overlays) {
// We don't present non-underscored overlays as part of the underlying
// module, so ignore them.
if (!overlay.hasUnderscoredNaming())
continue;
ModuleDecl *overlayMod =
getASTContext().getModuleByName(overlay.str());
if (!overlayMod)
continue;
if (seen.insert(overlayMod).second) {
overlayModules.push_back(overlayMod);
worklist.push_back(overlayMod);
if (auto *clangModule = overlayMod->getUnderlyingModuleIfOverlay())
worklist.push_back(clangModule);
}
addOverlay(overlay);
}
}
}
Expand Down Expand Up @@ -2432,6 +2445,12 @@ ModuleDecl::getDeclaringModuleAndBystander() {
if (!hasUnderscoredNaming())
return *(declaringModuleAndBystander = {nullptr, Identifier()});

// If this is one of the stdlib overlays, indicate as much.
auto &ctx = getASTContext();
if (llvm::is_contained(ctx.StdlibOverlayNames, getRealName()))
return *(declaringModuleAndBystander = { ctx.getStdlibModule(),
Identifier() });

// Search the transitive set of imported @_exported modules to see if any have
// this module as their overlay.
SmallPtrSet<ModuleDecl *, 16> seen;
Expand Down Expand Up @@ -2511,7 +2530,8 @@ bool ModuleDecl::getRequiredBystandersIfCrossImportOverlay(
auto *clangModule = declaring->getUnderlyingModuleIfOverlay();
auto current = std::make_pair(this, Identifier());
while ((current = current.first->getDeclaringModuleAndBystander()).first) {
bystanderNames.push_back(current.second);
if (!current.second.empty())
bystanderNames.push_back(current.second);
if (current.first == declaring || current.first == clangModule)
return true;
}
Expand Down
13 changes: 10 additions & 3 deletions lib/AST/ModuleNameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,18 @@ void ModuleNameLookup<LookupStrategy>::lookupInModule(
moduleOrFile->getParentModule(), overlays);
if (!overlays.empty()) {
// If so, look in each of those overlays.
for (auto overlay : overlays)
lookupInModule(decls, overlay, accessPath, moduleScopeContext, options);
bool selfOverlay = false;
for (auto overlay : overlays) {
if (overlay == moduleOrFile->getParentModule())
selfOverlay = true;
else
lookupInModule(decls, overlay, accessPath, moduleScopeContext,
options);
}
// FIXME: This may not work gracefully if more than one of these lookups
// finds something.
return;
if (!selfOverlay)
return;
}

const size_t initialCount = decls.size();
Expand Down
8 changes: 3 additions & 5 deletions lib/IDE/CompletionLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2182,11 +2182,9 @@ bool CompletionLookup::tryModuleCompletions(Type ExprType,
// If the module is shadowed by a separately imported overlay(s), look up
// the symbols from the overlay(s) instead.
SmallVector<ModuleDecl *, 1> ShadowingOrOriginal;
if (auto *SF = CurrDeclContext->getParentSourceFile()) {
SF->getSeparatelyImportedOverlays(M, ShadowingOrOriginal);
if (ShadowingOrOriginal.empty())
ShadowingOrOriginal.push_back(M);
}
CurrDeclContext->getSeparatelyImportedOverlays(M, ShadowingOrOriginal);
if (ShadowingOrOriginal.empty())
ShadowingOrOriginal.push_back(M);
for (ModuleDecl *M : ShadowingOrOriginal) {
RequestedResultsTy Request =
RequestedResultsTy::fromModule(M, Filter).needLeadingDot(needDot());
Expand Down
5 changes: 5 additions & 0 deletions test/Concurrency/concurrency_module_shadowing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ func f(_ t : UnsafeCurrentTask) -> Bool {

@available(SwiftStdlib 5.1, *)
func g(_: _Concurrency.UnsafeCurrentTask) {}

// Should also be allowed since _Concurrency is a separately-imported overlay of
// the standard library.
@available(SwiftStdlib 5.1, *)
func h(_: Swift.UnsafeCurrentTask) {}
2 changes: 1 addition & 1 deletion test/Concurrency/global_actor_function_types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ struct GlobalType {}

@_Concurrency.MainActor
extension GlobalType {
@_Concurrency.MainActor static func ==(
@Swift.MainActor static func ==(
lhs: GlobalType,
rhs: GlobalType
) -> Bool { true }
Expand Down
9 changes: 6 additions & 3 deletions validation-test/stdlib/Assert.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -Xfrontend -disable-access-control -o %t/Assert_Debug -Onone
// RUN: %target-build-swift %s -Xfrontend -disable-access-control -o %t/Assert_Release -O
// RUN: %target-build-swift %s -Xfrontend -disable-access-control -o %t/Assert_Unchecked -Ounchecked
//
// With -disable-access-control on, `_StringProcessing._internalInvariant` would shadow `Swift._internalInvariant`
// RUN: %target-build-swift %s -Xfrontend -disable-access-control -Xfrontend -disable-implicit-string-processing-module-import -o %t/Assert_Debug -Onone
// RUN: %target-build-swift %s -Xfrontend -disable-access-control -Xfrontend -disable-implicit-string-processing-module-import -o %t/Assert_Release -O
// RUN: %target-build-swift %s -Xfrontend -disable-access-control -Xfrontend -disable-implicit-string-processing-module-import -o %t/Assert_Unchecked -Ounchecked
//
// RUN: %target-codesign %t/Assert_Debug
// RUN: %target-codesign %t/Assert_Release
// RUN: %target-codesign %t/Assert_Unchecked
Expand Down