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-7336] Protocol with same-type constraint on associated type "can only be used as generic constraint" #49884

Closed
AnthonyLatsis opened this issue Apr 2, 2018 · 7 comments
Labels
compiler The Swift compiler in itself duplicate Resolution: Duplicates another issue existentials Feature: values of types like `any Collection`, `Any` and `AnyObject`; type-erased values feature A feature request or implementation improvement swift evolution implemented Flag → feature: A feature that was approved through the Swift evolution process and implemented type checker Area → compiler: Semantic analysis

Comments

@AnthonyLatsis
Copy link
Collaborator

AnthonyLatsis commented Apr 2, 2018

Previous ID SR-7336
Radar None
Original Reporter @AnthonyLatsis
Type Bug
Status Resolved
Resolution Duplicate
Environment

Xcode Version 9.2 (9C40b)

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: 0e0706f8b1ded96651a61cd786f858cb

duplicates:

  • SR-4758 SE-0142: derived protocol that restricts associatedtype should be allowed as a variable type

Issue Description:

Frustrating to meet this bug...Since Action is defined (in a mathematical sense), I should be able to use P1 as any other protocol without associated types.

protocol P {
    associatedtype Action

    func handle(_ action: Action)
}

protocol P1: P where Action == Int {}

class Foo: P1 {
    func handle(_ action: Int) {}
}

let foo: P1 = Foo() // Protocol 'P1' can only be used as a generic constraint ...

I understand same-type constraints as semantic refinements rather that defaulting acts. The difference is that the former are irreversible.

protocol P1: P {
    asssociatedtype Action = String
}

is not the same as

protocol P1: P where Action == String

In the first example I specify a default type for Action. This means I can have a different default in an inheriting protocol. Conversely, in the second example I constrain Action to String. In other words, Action becomes a typealias that can't be overridden or changed further in the protocol hierarchy.

However, it is possible to "override" Action even after same-type constraining it, which is very strange to me.

protocol P1: P where Action == Int {}

protocol P2: P1 {     
   associatedtype Action = String 
}

class Foo: P2 {
    func handle(_ action: String) {} // protocol stubs
}

This might be the reason I can't use a protocol with a same-type constraint on it's associated type anywhere other that a generic constraint, or just another bug.

@belkadan
Copy link
Contributor

belkadan commented Apr 3, 2018

@huonw, @DougGregor?

@DougGregor
Copy link
Member

DougGregor commented Apr 3, 2018

It's a little silly that we don't complain about P2 as written:

protocol P2: P1 {     
   associatedtype Action = String 
}

because that associated type default will never get used; Action is always going to be Int. The compiler correctly complains about the attempt to conform to P2 with a String Action:

t2a.swift:15:7: error: 'P1' requires the types 'String' and 'Int' be equivalent
class Foo: P2 {
      ^
t2a.swift:15:7: note: requirement specified as 'Self.Action' == 'Int' [with Self = Foo]
class Foo: P2 {
      ^

@AnthonyLatsis
Copy link
Collaborator Author

AnthonyLatsis commented Apr 4, 2018

Yes, I missed the fact that the compiler complains upon conformance – the Xcode 9.2 playground only prints errors to the console.

@DougGregor (Action is always going to be Int) – then this should be a little silly as well 🙂

protocol P1: P where Action == Int {}

class Foo: P1 {
    func handle(_ action: Int) {}
}

let foo: P1 = Foo() //  Protocol 'P1' can only be used as a generic constraint

@AnthonyLatsis
Copy link
Collaborator Author

@slavapestov shouldn't SR-4758 be a duplicate of this one instead, since it was reported later?

@belkadan
Copy link
Contributor

Dups are always collected on the oldest bug. Otherwise you'd end up with a chain to ever-newer issues.

@AnthonyLatsis
Copy link
Collaborator Author

Ah, my bad, I didn't notice that one was older.

@AnthonyLatsis
Copy link
Collaborator Author

AnthonyLatsis commented May 17, 2018

@slavapestov I forgot I mentioned 2 issues in one report. Is the ability to do this (from the snippet above):

protocol P1: P where Action == Int {}

protocol P2: P1 {     
   associatedtype Action = String 
}

class Foo: P2 {

    func handle(_ action: String) {} // protocol stubs
}

directly related to the dup?

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@AnthonyLatsis AnthonyLatsis added duplicate Resolution: Duplicates another issue improvement feature A feature request or implementation type checker Area → compiler: Semantic analysis swift evolution implemented Flag → feature: A feature that was approved through the Swift evolution process and implemented existentials Feature: values of types like `any Collection`, `Any` and `AnyObject`; type-erased values and removed bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. labels Jan 28, 2023
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 duplicate Resolution: Duplicates another issue existentials Feature: values of types like `any Collection`, `Any` and `AnyObject`; type-erased values feature A feature request or implementation improvement swift evolution implemented Flag → feature: A feature that was approved through the Swift evolution process and implemented type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

3 participants