Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-13372] Confusing error messages about property protocol conformance #55812

Open
swift-ci opened this issue Aug 9, 2020 · 5 comments
Open
Labels
compiler The Swift compiler in itself diagnostics QoI Bug: Diagnostics Quality of Implementation improvement type checker Area → compiler: Semantic analysis

Comments

@swift-ci
Copy link
Collaborator

swift-ci commented Aug 9, 2020

Previous ID SR-13372
Radar rdar://problem/67360659
Original Reporter vilarneto (JIRA User)
Type Improvement
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Improvement, DiagnosticsQoI, TypeChecker
Assignee None
Priority Medium

md5: eabb02acaadfb1fdb1dfefdc615deae8

Issue Description:

(Using Swift 5.2.4 under Xcode 11.6)

The following code tries to enforce a behaviour on the child property of the Parent type:

import Foundation

// Identifiable types must have a readable “id” String property

protocol Identifiable {
    var id: String { get }
}

// Basic types

struct Parent: Identifiable {
    let id: String
    let child: Child
}

struct Child: Identifiable {
    let id: String
}

// Now I want to generalise a behaviour on the ‘child’ property

protocol IdentifiableChild {
    var child: Identifiable { get }
}

As everything above compiles cleanly, I didn't expect the following error:

// Compiler error: Type 'Parent' does not conform to protocol 'IdentifiableChild'
// - Detail: Candidate has non-matching type 'Child'
extension Parent: IdentifiableChild { }

After some trial-and-error I understood that IdentifiableChild should be instead declared in one of the following ways:

protocol IdentifiableChild where ChildType: Identifiable {
    associated ChildType
    var child: ChildType { get }
}

…or…

protocol IdentifiableChild {
    associated ChildType: Identifiable
    var child: ChildType { get }
}

However, the compiler error didn't really give me any hints about what was wrong in the first example code, especially given that the original IdentifiableChild definition was accepted without errors or warnings.

The obvious improvement proposal is to rewrite the error message to give the programmer a clearer understanding of the situation and (hopefully) offer a “Fix” action. Moreover, I'd like to ask: Why doesn't the original definition of IdentifiableChild work, and (since it was accepted by the compiler) what is its usefulness?

@theblixguy
Copy link
Collaborator

The reason you get an error is because the property requirement in ChildIdentifiable requires its type to be exactly Identifiable, whereas you want something that conforms to Identifiable. This can be expressed by using a constrained associatedtype i.e. associatedtype ChildType: Identifiable.

I suppose we could change the diagnostic note to say candidate has type 'Child' (which conforms to 'Identifiable'), but protocol requires type to be exactly 'Identifiable'. Do you think that would be clearer in this scenario? Also, we could perhaps offer another fix-it to change the requirement's type to use an associated type.

cc @hborla theindigamer (JIRA User) What do you think?

@swift-ci
Copy link
Collaborator Author

swift-ci commented Aug 9, 2020

Comment by Vilar Fiuza da Camara Neto (JIRA)

@theblixguy The new diagnostic note you propose is much better and also hints about the difference between “being” vs. “conforming” when it comes to protocols – something that beginner-to-intermediate Swift programmers may not be aware of.

Moreover, thanks for the concise and enlightening answer.

@typesanitizer
Copy link

Isn't this very much like the type_cannot_conform diagnostic we already have today? It also has an educational note protocol-type-non-conformance.md. Maybe we should reuse that somehow?

@theblixguy
Copy link
Collaborator

Yeah, I think we show it when you have T: SomeProtocol requirement somewhere and you pass SomeProtocol however it’s the reverse here (i.e. the requirement is SomeProtocol and you’re passing T where T: SomeProtocol). Also, the diagnostic you mentioned is an error whereas I think we want to use a tailored version of the protocol_witness_type_conflict note.

@typesanitizer
Copy link

@swift-ci create

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler The Swift compiler in itself diagnostics QoI Bug: Diagnostics Quality of Implementation improvement type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

3 participants