Skip to content

Commit 4fa8296

Browse files
committed
Added feature flag ShadowFoundation
1 parent a2d4505 commit 4fa8296

File tree

4 files changed

+59
-13
lines changed

4 files changed

+59
-13
lines changed

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ EXPERIMENTAL_FEATURE(BuiltinMacros, false)
161161
/// declare an attribute which is discoverable and constructable at runtime.
162162
EXPERIMENTAL_FEATURE(RuntimeDiscoverableAttrs, false)
163163

164+
/// Whether to allow types from Foundation to be implicitly shadowed
165+
EXPERIMENTAL_FEATURE(ShadowFoundation, false)
166+
164167
#undef EXPERIMENTAL_FEATURE
165168
#undef UPCOMING_FEATURE
166169
#undef SUPPRESSIBLE_LANGUAGE_FEATURE

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3156,6 +3156,10 @@ static bool usesFeatureBuiltinMacros(Decl *decl) {
31563156
return false;
31573157
}
31583158

3159+
static bool usesFeatureShadowFoundation(Decl *decl) {
3160+
return false;
3161+
}
3162+
31593163
static void
31603164
suppressingFeatureNoAsyncAvailability(PrintOptions &options,
31613165
llvm::function_ref<void()> action) {

lib/AST/NameLookup.cpp

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -660,19 +660,58 @@ static void recordShadowedDeclsAfterTypeMatch(
660660
}
661661
}
662662

663-
// Next, prefer any other module over the Foundation module
664-
if (auto foundationModule = ctx.getLoadedModule(ctx.Id_Foundation)) {
665-
if ((firstModule == foundationModule) !=
666-
(secondModule == foundationModule)) {
667-
// If second module is Foundation, then it is shadowed by first
668-
if (secondModule == foundationModule) {
669-
shadowed.insert(secondDecl);
670-
continue;
671-
}
663+
if (ctx.LangOpts.hasFeature(Feature::ShadowFoundation)) {
664+
// If `ShadowFoundation` is enabled, allow all types from Foundation
665+
// to be implicitly shadowed.
666+
if (auto foundationModule = ctx.getLoadedModule(ctx.Id_Foundation)) {
667+
if ((firstModule == foundationModule) !=
668+
(secondModule == foundationModule)) {
669+
// If second module is Foundation, then it is shadowed by first
670+
if (secondModule == foundationModule) {
671+
shadowed.insert(secondDecl);
672+
continue;
673+
}
672674

673-
// Otherwise, the first declaration is shadowed by the second.
674-
shadowed.insert(firstDecl);
675-
break;
675+
// Otherwise, the first declaration is shadowed by the second.
676+
shadowed.insert(firstDecl);
677+
break;
678+
}
679+
}
680+
} else {
681+
// The Foundation overlay introduced Data.withUnsafeBytes, which is
682+
// treated as being ambiguous with SwiftNIO's Data.withUnsafeBytes
683+
// extension. Apply a special-case name shadowing rule to use the
684+
// latter rather than the former, which be the consequence of a more
685+
// significant change to name shadowing in the future.
686+
if (auto owningStruct1
687+
= firstDecl->getDeclContext()->getSelfStructDecl()) {
688+
if (auto owningStruct2
689+
= secondDecl->getDeclContext()->getSelfStructDecl()) {
690+
if (owningStruct1 == owningStruct2 &&
691+
owningStruct1->getName().is("Data") &&
692+
isa<FuncDecl>(firstDecl) && isa<FuncDecl>(secondDecl) &&
693+
firstDecl->getName() == secondDecl->getName() &&
694+
firstDecl->getBaseName().userFacingName() == "withUnsafeBytes") {
695+
// If the second module is the Foundation module and the first
696+
// is the NIOFoundationCompat module, the second is shadowed by the
697+
// first.
698+
if (firstDecl->getModuleContext()->getName()
699+
.is("NIOFoundationCompat") &&
700+
secondDecl->getModuleContext()->getName().is("Foundation")) {
701+
shadowed.insert(secondDecl);
702+
continue;
703+
}
704+
705+
// If it's the other way around, the first declaration is shadowed
706+
// by the second.
707+
if (secondDecl->getModuleContext()->getName()
708+
.is("NIOFoundationCompat") &&
709+
firstDecl->getModuleContext()->getName().is("Foundation")) {
710+
shadowed.insert(firstDecl);
711+
break;
712+
}
713+
}
714+
}
676715
}
677716
}
678717

test/Frontend/foundation-module-shadowing.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// REQUIRES: objc_interop
22
// RUN: %empty-directory(%t)
33
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/ShadowFoundation.swiftmodule -module-name ShadowFoundation %S/Inputs/ShadowFoundation.swift -disable-availability-checking
4-
// RUN: %target-typecheck-verify-swift -I %t -disable-availability-checking
4+
// RUN: %target-typecheck-verify-swift -I %t -disable-availability-checking -enable-experimental-feature ShadowFoundation
55

66
import Foundation
77
import ShadowFoundation

0 commit comments

Comments
 (0)