mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
finalizeDecl() would kick off certain requests. This was necessary before we had the long-lived type checker to ensure that requests that required a type checker could be completed in time for SILGen. It was also necessary to always emit diagnostics for declarations in primary files. Since we now have a long lived type checker, the first reason is no longer valid, so we can move this work from finalizeDecl() to typeCheckDecl(), where it will run for declarations in primary files only. To ensure that @objc selector conflict diagnostics still get emitted, we also walk the superclass chain and force isObjC() to be computed for each declaration in each superclass.
156 lines
6.4 KiB
Swift
156 lines
6.4 KiB
Swift
// RUN: %target-typecheck-verify-swift -enable-objc-interop
|
|
|
|
// Test "near misses" where a member of a class or extension thereof
|
|
// nearly matches an optional requirement, but does not exactly match.
|
|
|
|
@objc protocol P1 {
|
|
@objc optional func doSomething(a: Int, b: Double) // expected-note 2{{requirement 'doSomething(a:b:)' declared here}}
|
|
}
|
|
|
|
class C1a : P1 {
|
|
@objc func doSomething(a: Int, c: Double) { }
|
|
// expected-warning@-1{{instance method 'doSomething(a:c:)' nearly matches optional requirement 'doSomething(a:b:)' of protocol 'P1'}}
|
|
// expected-note@-2{{rename to 'doSomething(a:b:)' to satisfy this requirement}}{{34-34=b }}
|
|
// expected-note@-3{{move 'doSomething(a:c:)' to an extension to silence this warning}}
|
|
// expected-note@-4{{make 'doSomething(a:c:)' private to silence this warning}}{{9-9=private }}
|
|
}
|
|
|
|
class C1b : P1 {
|
|
}
|
|
|
|
extension C1b {
|
|
@objc func doSomething(a: Int, c: Double) { } // don't warn
|
|
}
|
|
|
|
class C1c {
|
|
}
|
|
|
|
extension C1c : P1 {
|
|
func doSomething(a: Int, c: Double) { }
|
|
// expected-warning@-1{{instance method 'doSomething(a:c:)' nearly matches optional requirement 'doSomething(a:b:)' of protocol 'P1'}}
|
|
// expected-note@-2{{rename to 'doSomething(a:b:)' to satisfy this requirement}}{{28-28=b }}{{none}}
|
|
// expected-note@-3{{move 'doSomething(a:c:)' to another extension to silence this warning}}
|
|
// expected-note@-4{{make 'doSomething(a:c:)' private to silence this warning}}{{3-3=private }}
|
|
}
|
|
|
|
class C1d : P1 {
|
|
@objc private func doSomething(a: Int, c: Double) { } // don't warn
|
|
}
|
|
|
|
class C1e : P1 {
|
|
@nonobjc func doSomething(a: Int, c: Double) { } // don't warn
|
|
}
|
|
|
|
// Don't try to match an optional requirement against a declaration
|
|
// that already satisfies one witness.
|
|
@objc protocol P2 {
|
|
@objc optional func doSomething(a: Int, b: Double)
|
|
@objc optional func doSomething(a: Int, d: Double)
|
|
}
|
|
|
|
class C2a : P2 {
|
|
@objc func doSomething(a: Int, b: Double) { } // don't warn: this matches something
|
|
}
|
|
|
|
// Cope with base names that change.
|
|
@objc protocol P3 {
|
|
@objc optional func doSomethingWithPriority(_ a: Int, d: Double) // expected-note{{requirement 'doSomethingWithPriority(_:d:)' declared here}}
|
|
}
|
|
|
|
class C3a : P3 {
|
|
func doSomething(priority: Int, d: Double) { }
|
|
// expected-warning@-1{{instance method 'doSomething(priority:d:)' nearly matches optional requirement 'doSomethingWithPriority(_:d:)' of protocol 'P3'}}
|
|
// expected-note@-2{{rename to 'doSomethingWithPriority(_:d:)' to satisfy this requirement}}{{20-20=_ }}
|
|
// expected-note@-3{{move 'doSomething(priority:d:)' to an extension to silence this warning}}
|
|
// expected-note@-4{{make 'doSomething(priority:d:)' private to silence this warning}}{{3-3=private }}
|
|
}
|
|
|
|
@objc protocol P4 {
|
|
@objc optional func doSomething(priority: Int, d: Double) // expected-note{{requirement 'doSomething(priority:d:)' declared here}}
|
|
}
|
|
|
|
class C4a : P4 {
|
|
func doSomethingWithPriority(_ a: Int, d: Double) { }
|
|
// expected-warning@-1{{instance method 'doSomethingWithPriority(_:d:)' nearly matches optional requirement 'doSomething(priority:d:)' of protocol 'P4'}}
|
|
// expected-note@-2{{rename to 'doSomething(priority:d:)' to satisfy this requirement}}{{32-33=priority}}
|
|
// expected-note@-3{{move 'doSomethingWithPriority(_:d:)' to an extension to silence this warning}}
|
|
// expected-note@-4{{make 'doSomethingWithPriority(_:d:)' private to silence this warning}}{{3-3=private }}
|
|
}
|
|
|
|
@objc class SomeClass { }
|
|
|
|
@objc protocol P5 {
|
|
@objc optional func methodWithInt(_: Int, forSomeClass: SomeClass, dividingDouble: Double)
|
|
// expected-note@-1{{requirement 'methodWithInt(_:forSomeClass:dividingDouble:)' declared here}}
|
|
}
|
|
|
|
class C5a : P5 {
|
|
func method(_: Int, for someClass: SomeClass, dividing double: Double) { }
|
|
// expected-warning@-1{{instance method 'method(_:for:dividing:)' nearly matches optional requirement 'methodWithInt(_:forSomeClass:dividingDouble:)' of protocol 'P5'}}
|
|
// expected-note@-2{{rename to 'methodWithInt(_:forSomeClass:dividingDouble:)' to satisfy this requirement}}{{8-14=methodWithInt}}{{23-26=forSomeClass}}{{49-57=dividingDouble}}{{none}}
|
|
// expected-note@-3{{move 'method(_:for:dividing:)' to an extension to silence this warning}}
|
|
// expected-note@-4{{make 'method(_:for:dividing:)' private to silence this warning}}{{3-3=private }}
|
|
}
|
|
|
|
@objc protocol P6 {
|
|
@objc optional func method(_: Int, for someClass: SomeClass, dividing double: Double)
|
|
// expected-note@-1{{requirement 'method(_:for:dividing:)' declared here}}
|
|
}
|
|
|
|
class C6a : P6 {
|
|
func methodWithInt(_: Int, forSomeClass: SomeClass, dividingDouble: Double) { }
|
|
// expected-warning@-1{{instance method 'methodWithInt(_:forSomeClass:dividingDouble:)' nearly matches optional requirement 'method(_:for:dividing:)' of protocol 'P6'}}
|
|
// expected-note@-2{{rename to 'method(_:for:dividing:)' to satisfy this requirement}}{{8-21=method}}{{30-30=for }}{{55-55=dividing }}{{none}}
|
|
// expected-note@-3{{move 'methodWithInt(_:forSomeClass:dividingDouble:)' to an extension to silence this warning}}
|
|
// expected-note@-4{{make 'methodWithInt(_:forSomeClass:dividingDouble:)' private to silence this warning}}{{3-3=private }}
|
|
}
|
|
|
|
// Use the first note to always describe why it didn't match.
|
|
@objc protocol P7 {
|
|
@objc optional func method(foo: Float)
|
|
// expected-note@-1{{requirement 'method(foo:)' declared here}}
|
|
}
|
|
|
|
class C7a : P7 {
|
|
@objc func method(foo: Double) { }
|
|
// expected-warning@-1{{instance method 'method(foo:)' nearly matches optional requirement 'method(foo:)' of protocol 'P7'}}
|
|
// expected-note@-2{{candidate has non-matching type '(Double) -> ()'}}
|
|
// expected-note@-3{{move 'method(foo:)' to an extension to silence this warning}}
|
|
// expected-note@-4{{make 'method(foo:)' private to silence this warning}}
|
|
}
|
|
|
|
// Don't complain about near misses that satisfy other protocol
|
|
// requirements.
|
|
@objc protocol P8 {
|
|
@objc optional func foo(exactMatch: Int)
|
|
}
|
|
|
|
@objc protocol P9 : P8 {
|
|
@objc optional func foo(nearMatch: Int)
|
|
}
|
|
|
|
class C8Super : P8 { }
|
|
|
|
class C9Sub : C8Super, P9 {
|
|
func foo(exactMatch: Int) { }
|
|
}
|
|
|
|
// Don't complain about overriding methods that are near misses;
|
|
// the user cannot make it satisfy the protocol requirement.
|
|
class C10Super {
|
|
func foo(nearMatch: Int) { }
|
|
}
|
|
|
|
class C10Sub : C10Super, P8 {
|
|
override func foo(nearMatch: Int) { }
|
|
}
|
|
|
|
// Be more strict about near misses than we had previously.
|
|
@objc protocol P11 {
|
|
@objc optional func foo(wibble: Int)
|
|
}
|
|
|
|
class C11 : P11 {
|
|
func f(waggle: Int) { } // no warning
|
|
}
|