Skip to content

Commit 684e8a5

Browse files
committed
[Name lookup] Don't allow unavailable-in-current-Swift declarations to shadow available ones.
The unavailable-in-current-Swift declarations introduced by the Clang importer to help with migrating Swift 2.x code to Swift 3's naming cause problems with unqualified name lookup when they shadow, e.g., types. The biggest problem in practice is with "URL", which is a common Cocoa property name (in Swift 2) that becomes "url" in Swift 3, but the old name conflicts with the Foundation value type "URL". Fixes <rdar://problem/26236989>.
1 parent e26bd64 commit 684e8a5

File tree

3 files changed

+47
-3
lines changed

3 files changed

+47
-3
lines changed

lib/AST/NameLookup.cpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,8 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
391391
if (IsKnownNonCascading)
392392
isCascadingUse = false;
393393

394+
SmallVector<UnqualifiedLookupResult, 4> UnavailableInnerResults;
395+
394396
// Never perform local lookup for operators.
395397
if (Name.isOperator()) {
396398
if (!isCascadingUse.hasValue()) {
@@ -565,9 +567,25 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
565567
}
566568

567569
if (FoundAny) {
568-
if (DebugClient)
569-
filterForDiscriminator(Results, DebugClient);
570-
return;
570+
// Predicate that determines whether a lookup result should
571+
// be unavailable except as a last-ditch effort.
572+
auto unavailableLookupResult =
573+
[&](const UnqualifiedLookupResult &result) {
574+
return result.getValueDecl()->getAttrs()
575+
.isUnavailableInCurrentSwift();
576+
};
577+
578+
// If all of the results we found are unavailable, keep looking.
579+
if (std::all_of(Results.begin(), Results.end(),
580+
unavailableLookupResult)) {
581+
UnavailableInnerResults.append(Results.begin(), Results.end());
582+
Results.clear();
583+
FoundAny = false;
584+
} else {
585+
if (DebugClient)
586+
filterForDiscriminator(Results, DebugClient);
587+
return;
588+
}
571589
}
572590

573591
// Check the generic parameters if our context is a generic type or
@@ -641,6 +659,14 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
641659
if (!Results.empty())
642660
return;
643661

662+
// If we still haven't found anything, but we do have some
663+
// declarations that are "unavailable in the current Swift", drop
664+
// those in.
665+
if (!UnavailableInnerResults.empty()) {
666+
Results = std::move(UnavailableInnerResults);
667+
return;
668+
}
669+
644670
if (!Name.isSimpleName())
645671
return;
646672

test/ClangModules/swift2_warnings.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import Foundation
77
import ImportAsMember.A
8+
import AppKit
89

910
func testOldTypeNames() {
1011
var ps: NSPostingStyle? // expected-error{{'NSPostingStyle' has been renamed to 'PostingStyle'}}{{11-25=PostingStyle}}
@@ -77,3 +78,16 @@ func testImportAsMember() {
7778
IAMStruct1SetRadius(iam1, 3.14159)
7879
// expected-error@-1{{'IAMStruct1SetRadius' has been replaced by property 'Struct1.radius'}}{{3-22=iam1.radius}} {{22-29= = }} {{36-37=}}
7980
}
81+
82+
// rdar://problem/26236989
83+
class X : NSDocument {
84+
func test(url: URL) {
85+
}
86+
func test2() {
87+
let url = URL(string: "ABC")
88+
self.url = url!
89+
}
90+
func getTheURL() -> URL {
91+
return url
92+
}
93+
}

test/Inputs/clang-importer-sdk/usr/include/AppKit.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,3 +300,7 @@ typedef NSPoint *NSPointPointer;
300300
- (void)addRect:(NSRect)rect;
301301
+ (void)conjureRect:(NSRect)rect;
302302
@end
303+
304+
@interface NSDocument (URL)
305+
@property (copy,nonnull) NSURL *URL;
306+
@end

0 commit comments

Comments
 (0)