swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.49k stars 10.35k forks source link

[SR-13515] Incorrect fix-it when attempting to extend an `objc` protocol with a default implementation #55951

Open amomchilov opened 4 years ago

amomchilov commented 4 years ago
Previous ID SR-13515
Radar rdar://problem/68476523
Original Reporter @amomchilov
Type Bug
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Bug, DiagnosticsQoI, TypeChecker | |Assignee | @theblixguy | |Priority | Medium | md5: 1e0dc6ae6b02f489a3c7f3c42370108b

Issue Description:

@objc protocols don't support default implementations for methods via extensions. Attempting to do so makes the compiler suggest that you add the @objc attribute to your default method implementation, which instead it should tell you that the entire construct is invalid.

Example code:

import Foundation

@objc protocol ObjCProtocol {
    @objc func requiredMethod()
}

extension ObjCProtocol {
    /* @objc */ func requiredMethod() {
        print("Default implementation")
    }
}

class ConformingClass: NSObject, ObjCProtocol {

}

ConformingClass().requiredMethod()

Error:

Untitled.swift:13:7: error: non-'@objc' method 'requiredMethod()' does not satisfy requirement of '@objc' protocol 'ObjCProtocol'
class ConformingClass: NSObject, ObjCProtocol {
      ^
Untitled.swift:8:19: note: add '@objc' to expose this instance method to Objective-C
        /* @objc */ func requiredMethod() {
                         ^
                    @objc 
Untitled.swift:4:13: note: requirement 'requiredMethod()' declared here
        @objc func requiredMethod()
                   ^

If you follow the fix-it, you another error which correctly tells you that this is invalid. But strangely, you still get a suggestion to add @objc:

Untitled.swift:8:3: error: @objc can only be used with members of classes, @objc protocols, and concrete extensions of classes
        @objc func requiredMethod() {
        ~^~~~~

Untitled.swift:13:7: error: non-'@objc' method 'requiredMethod()' does not satisfy requirement of '@objc' protocol 'ObjCProtocol'
class ConformingClass: NSObject, ObjCProtocol {
      ^
Untitled.swift:8:13: note: add '@objc' to expose this instance method to Objective-C
        @objc func requiredMethod() {
                   ^
        @objc 
Untitled.swift:4:13: note: requirement 'requiredMethod()' declared here
        @objc func requiredMethod()
                   ^
typesanitizer commented 4 years ago

@swift-ci create

theblixguy commented 4 years ago

https://github.com/apple/swift/pull/33891