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-5753] Remove "redundant same-type constraints" warnings #48323

Closed
NachoSoto opened this issue Aug 23, 2017 · 15 comments
Closed

[SR-5753] Remove "redundant same-type constraints" warnings #48323

NachoSoto opened this issue Aug 23, 2017 · 15 comments
Assignees
Labels
compiler The Swift compiler in itself diagnostics QoI Bug: Diagnostics Quality of Implementation improvement type checker Area → compiler: Semantic analysis

Comments

@NachoSoto
Copy link
Contributor

Previous ID SR-5753
Radar None
Original Reporter @NachoSoto
Type Improvement
Status Resolved
Resolution Done
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Improvement, DiagnosticsQoI, TypeChecker
Assignee @DougGregor
Priority Medium

md5: 929f231d867d72f61e86204ff4e16b03

is duplicated by:

  • SR-5766 Remove the warning Redundant conformance constraint ...

relates to:

  • SR-6265 Remove "redundant layout constraint" warning
  • SR-13898 "redundant conformance constraint" warning shows up (again?)
  • SR-5766 Remove the warning Redundant conformance constraint ...

Issue Description:

See Twitter thread

I think these warnings are more annoying than helpful, especially without the ability to disable them (either globally or on a per-instance basis).
Just like Swift doesn't warn when adding explicit types (example: let a: Int = [1, 2].count), I believe it shouldn't either when specifying type constraints that may already be known.

This redundancy allows being explicit instead of implicitly relying on some other constraint, that could change or go away in the future, or that might not be obvious to the reader in some context.

A simple example could be:

struct S<T: Hashable> {}

fun f<T: Equatable>(s: S<T>) {}

Maybe I want to specify the Equatable constraint to provide clarity, to avoid the implicit assumption that S has Hashable (or hell, that Hashable implies Equatable! Maybe obvious in this particular example, but might not be in other protocol hierarchies), or in case the constraint on S ever changes.

@belkadan
Copy link
Contributor

cc @DougGregor

@DougGregor
Copy link
Member

One issue with this warning is that there is no natural in-source way to silence it, and a warning option to the compiler seems like a very heavy hammer.

We could invent some grammatical trick—allowing parentheses around individual requirements and using those as a cue to silence the warning—but that also feels like a hack.

@NachoSoto
Copy link
Contributor Author

To me this seems like something that's only useful sometimes. I can imagine wanting to do a one-off pass through my code to find these (using a linter for example), not something the compiler should warn all the time by default. It's not like the rest of warnings where if you have that (ignored returned values, unused variables, etc) it probably means you did something wrong. There's nothing inherently wrong with redundant types.

@DougGregor
Copy link
Member

The warning indicates that you've written a constraint explicitly that has no effect, which might mean that you meant to write a different constraint or might mean that you're confused about the actual constraints of your generic. It's not that different from an unused value, where you did something intentionally but it's effect has been lost. But with an unused-value warning, there's an easy fix in the grammar.

@DougGregor
Copy link
Member

One possible path forward would be to stop warning about causes where we've inferred the constraint from the types in the signature. For example, we could stop warning about the first example in the description (where we inferred a constraint from the signature), but continue warning about cases where you've explicitly written out both constraints, e.g.,

struct S<T: Hashable> {}

fun f<T: Equatable>(s: S<T>) where T: Hashable {}   // warn that "T: Equatable" is redundant

@NachoSoto
Copy link
Contributor Author

That makes a lot of sense.

@DougGregor
Copy link
Member

Debating #12007

@swift-ci
Copy link
Collaborator

Comment by Josh Wiechman (JIRA)

Continuing the discussion from SR-5766

I really like the GitHub diff and the option to opt-in to these type of warnings.

I would disagree with the previous description of "The warning indicates that you've written a constraint explicitly that has no effect" The constraint has effect, but not necessarily double effect.
Others have called out that the implementing class/struct that can explicitly establish the conformance to a protocol provides value from the clarity of code.

I ask two questions:

  1. How does the Swift group define a compilation warning? (Criteria to call something a compilation warning vs. style.)
  1. What is the value statement of providing warnings on redundant protocols? Or what issue does this warning address?
    (I don't see the harm, even if redundant. Languages such as Java also do not cause compilation warnings with this style of redundancy with inheriting interfaces used along-side the inherited interface.)

@belkadan
Copy link
Contributor

For the most part, a warning in Swift is something that's almost certainly a mistake on the programmer's part, but where you don't have to fix it now just to get the project to build. (For an error, there's no valid interpretation of what they've done at all.) Obviously this gets a little fuzzy in practice, but in general I think we don't like to diagnose things that we would just consider "style".

@DougGregor
Copy link
Member

I'm going to turn off all redundancy warnings based on inferred constraints, per #12135.

@DougGregor
Copy link
Member

Fixed by 98e88bc

@swift-ci
Copy link
Collaborator

swift-ci commented Mar 7, 2018

Comment by Shawn Morel (JIRA)

Unless I'm missing something obvious, the fix seems to only apply to generic constraints but the same rationale applies to structs / enums conforming to protocols.

Using the same 2 protocols as above for consistency:

struct MyStruct : Equatable, Hashable {...}

You can substitute Equatable and Hashable for any 2 other protocols that might come from different 3rd party libraries that you can't control.

$ swift --version
Apple Swift version 4.2-dev (LLVM c4ec2ab808, Clang af436f313e, Swift abbaa47)
Target: x86_64-apple-darwin17.4.0

@swift-ci
Copy link
Collaborator

swift-ci commented Mar 8, 2018

Comment by Josh Wiechman (JIRA)

Hi Shawn,

The issue is the assumption that a class implementing a protocol and a sub class explicitly implementing the same protocol should be a warning.

This does not make sense with respect to protocol oriented programming in the situations where protocol extensions exist.

Both the parent class and the child class may have an explicitly dependency on the protocol + extension.

Explicitly stating both classes implement the protocol should not be a warning. Nothing is technically wrong and there is a valid use case for this approach.

If only the parent class implemented the the protocol, and later, within the scope of the parent class, the protocol is no longer needed, the protocol would be removed.

Any child class that depends on that protocol for covariance and contravariance leveraging that protocol would be broken. Additionally, that functionality from the extension would no longer be associated with the sub class.

If we assign the protocol to the parent and want to explicitly call out the dependency of the protocol, we should be able to without warnings to ensure the explicit requirement are always applied to the sub class (no matter the parent including the protocol).

This is important with local development and when building on top of 3rd party dependencies.

Hope this helps!

@swift-ci
Copy link
Collaborator

swift-ci commented Mar 9, 2018

Comment by Shawn Morel (JIRA)

Hi Josh,

Unless I’m misunderstanding your explanation, I think we’re in agreement.

`struct MyStruct: Equatable, Hashable {...} ` currently gives a warning when I’d expect it not to for the reasons (I think) you’ve stated.

As you’ve mentioned, Protocol conformance checking operates more like a subsumsion relation and less like a subtyping relation.

@swift-ci
Copy link
Collaborator

Comment by Josh Wiechman (JIRA)

strangemonad (JIRA User) Yep!

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
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

4 participants