Skip to content

Commit

Permalink
Don't look for near-miss witnesses for unavailable requirements. (#2604)
Browse files Browse the repository at this point in the history
We use unavailable requirements as migration hints, but conformance
checking would try a little too hard to actually satisfy them, even
though they wouldn't actually be used. This led to errors about the
/new/ name not matching the /old/ name.

(We now get /two/ diagnostics for using the old name, but we can fix
that later. Filed rdar://problem/26358593.)

rdar://problem/26313044
(cherry picked from commit e003e5e)
  • Loading branch information
jrose-apple authored and tkremenek committed May 19, 2016
1 parent df3b4d9 commit eac62a4
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 1 deletion.
7 changes: 6 additions & 1 deletion lib/Sema/TypeCheckProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2036,7 +2036,8 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
bool doNotDiagnoseMatches = false;
bool ignoringNames = false;
bool considerRenames =
!canDerive && !requirement->getAttrs().hasAttribute<OptionalAttr>();
!canDerive && !requirement->getAttrs().hasAttribute<OptionalAttr>() &&
!requirement->getAttrs().isUnavailable(TC.Context);

if (findBestWitness(requirement,
considerRenames ? &ignoringNames : nullptr,
Expand All @@ -2049,6 +2050,7 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
// If the name didn't actually line up, complain.
if (ignoringNames &&
requirement->getFullName() != best.Witness->getFullName()) {

diagnoseOrDefer(requirement, false,
[witness, requirement](TypeChecker &tc,
NormalProtocolConformance *conformance) {
Expand Down Expand Up @@ -4570,6 +4572,9 @@ void TypeChecker::checkConformancesInContext(DeclContext *dc,
SmallVector<ValueDecl *, 4> bestOptionalReqs;
unsigned bestScore = UINT_MAX;
for (auto req : unsatisfiedReqs) {
// Skip unavailable requirements.
if (req->getAttrs().isUnavailable(Context)) continue;

// Score this particular optional requirement.
auto score = scorePotentiallyMatching(req, value, bestScore);

Expand Down
13 changes: 13 additions & 0 deletions test/ClangModules/Inputs/protocol-member-renaming.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@import ObjectiveC;

@interface Foo : NSObject
@end

@protocol FooDelegate
- (void)foo:(Foo *)foo willConsumeObject:(id)obj __attribute__((swift_name("foo(_:willConsume:)")));
@end

@protocol OptionalButUnavailable
@optional
- (void)doTheThing:(id)thingToDoItWith __attribute__((unavailable));
@end
18 changes: 18 additions & 0 deletions test/ClangModules/protocol-member-renaming.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: %target-swift-frontend -parse -import-objc-header %S/Inputs/protocol-member-renaming.h -verify %s

// REQUIRES: objc_interop

class Modern : NSObject, FooDelegate {
func foo(_ foo: Foo, willConsume object: AnyObject) {}
}

class PreMigration : NSObject, FooDelegate {
func foo(_ foo: Foo, willConsumeObject object: AnyObject) {}
// expected-error@-1 {{'foo(_:willConsumeObject:)' has been renamed to 'foo(_:willConsume:)'}} {{24-41=willConsume}}
// expected-error@-2 {{method 'foo(_:willConsumeObject:)' has different argument names from those required by protocol 'FooDelegate' ('foo(_:willConsume:)')}} {{24-41=willConsume}}
}

class OptionalButUnavailableImpl : OptionalButUnavailable {
// Note the argument label that causes this not to match the requirement.
func doTheThing(object: AnyObject) {} // no-warning
}

0 comments on commit eac62a4

Please sign in to comment.