[Pitch] Add namespacing to associatedTypes


(Noah Blake) #1

Types associated with a protocol are not namespaced by the protocol, but
rather by the protocol's adopters. As such, when two protocols declare a
common associatedType, adoption of those protocols introduces undesirable
ambiguity.

Given the understandable propensity of developers to arrive at similarly
named types (T, for example), it is likely that this problem will reduce
the compatibility of packages for reasons that may not be entirely clear to
the package consumer.

Here is a demonstration of the issue. Apologies, I'm a longtime reader of
the list, but this is my first time posting, and I'm not sure how best to
format this. You may also find this example on Jira (
https://bugs.swift.org/browse/SR-1065).

protocol A {
    associatedtype T
    var aT: T { get }
}

protocol B {
    associatedtype T
    var bT: T { get }
}

T is ambiguous: "Type C does not conform to protocol 'B'."

class C: A, B {
    var aT = String()
    var bT = Int()
}

T is inferred unambiguously, compiles without error.

class C: A, B {
    var aT = String()
    var bT = String()
}

T is explicit, but problematic: "Type C does not conform to protocol 'A'."

class C: A, B {
    typealias T = Int
    var aT = String()
    var bT = Int()
}

I would greatly appreciate any advice or direction as to next steps. I have
a proposal for resolving this in mind, but it seemed premature to offer it
before finding some agreement that this was worth carrying forward.

Best regards,
Noah Blake


(Milos Rankovic) #2

I agree that this is counterintuitive behaviour and should ideally be changed to match things like:

    func f <T> (_: T.Type) {}
    func f2 <T> (_: T.Type) {}

    f(Int)
    f2(String)

milos

···

On 5 Apr 2016, at 17:16, Noah Blake via swift-evolution <swift-evolution@swift.org> wrote:

Types associated with a protocol are not namespaced by the protocol, but rather by the protocol's adopters. As such, when two protocols declare a common associatedType, adoption of those protocols introduces undesirable ambiguity.

Given the understandable propensity of developers to arrive at similarly named types (T, for example), it is likely that this problem will reduce the compatibility of packages for reasons that may not be entirely clear to the package consumer.

Here is a demonstration of the issue. Apologies, I'm a longtime reader of the list, but this is my first time posting, and I'm not sure how best to format this. You may also find this example on Jira (https://bugs.swift.org/browse/SR-1065).

protocol A {
    associatedtype T
    var aT: T { get }
}

protocol B {
    associatedtype T
    var bT: T { get }
}

T is ambiguous: "Type C does not conform to protocol 'B'."

class C: A, B {
    var aT = String()
    var bT = Int()
}

T is inferred unambiguously, compiles without error.

class C: A, B {
    var aT = String()
    var bT = String()
}

T is explicit, but problematic: "Type C does not conform to protocol 'A'."

class C: A, B {
    typealias T = Int
    var aT = String()
    var bT = Int()
}

I would greatly appreciate any advice or direction as to next steps. I have a proposal for resolving this in mind, but it seemed premature to offer it before finding some agreement that this was worth carrying forward.

Best regards,
Noah Blake
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Brent Royal-Gordon) #3

Types associated with a protocol are not namespaced by the protocol, but rather by the protocol's adopters. As such, when two protocols declare a common associatedType, adoption of those protocols introduces undesirable ambiguity.

I don't think there's much of a point solving this just for associated types. The same issue exists for all protocol requirements.

Given the understandable propensity of developers to arrive at similarly named types (T, for example), it is likely that this problem will reduce the compatibility of packages for reasons that may not be entirely clear to the package consumer.

Then don't do that. Absurdly short associated/generic type names are like absurdly short variable or function names—they're okay in a very small context like a short function or a single loop, but a bad idea in a wider context. That's why the Swift 2 standard library moved away from using short names like `T` in generic types like Array and Optional.

···

--
Brent Royal-Gordon
Architechies


(Noah Blake) #4

I don't think there's much of a point solving this just for associated
types. The same issue exists for all protocol requirements.

True enough. The one difference worth noting, however, is that there's no
way to address the ambiguity of identical protocol requirements without
adding syntactical overhead. In the case of associatedtype inferencing,
however, it should be possible.

Then don't do that. Absurdly short associated/generic type names are like

absurdly short variable or function names—they're okay in a very small
context like a short function or a single loop, but a bad idea in a wider
context. That's why the Swift 2 standard library moved away from using
short names like `T` in generic types like Array and Optional.

While this may be a bit orthogonal, it's worth noting that the standard
library has increased its usage of T over the past month. Right now, it
contains 3932 occurrences of <T>. Plenty of these usages are type-scoped.
To your point, there are only 46 occurrences of "associatedtype T".

Regardless, there are plenty of longer, arguably better associatedtype
names that writers of different packages may commonly reach for. "Element"
may be known to be somewhat off limits, but it is representative of this
category.

···

On Wed, Apr 6, 2016 at 1:45 AM, Brent Royal-Gordon <brent@architechies.com> wrote:

> Types associated with a protocol are not namespaced by the protocol, but
rather by the protocol's adopters. As such, when two protocols declare a
common associatedType, adoption of those protocols introduces undesirable
ambiguity.

I don't think there's much of a point solving this just for associated
types. The same issue exists for all protocol requirements.

> Given the understandable propensity of developers to arrive at similarly
named types (T, for example), it is likely that this problem will reduce
the compatibility of packages for reasons that may not be entirely clear to
the package consumer.

Then don't do that. Absurdly short associated/generic type names are like
absurdly short variable or function names—they're okay in a very small
context like a short function or a single loop, but a bad idea in a wider
context. That's why the Swift 2 standard library moved away from using
short names like `T` in generic types like Array and Optional.

--
Brent Royal-Gordon
Architechies


(Noah Blake) #5

Apologies - in /stdlib proper, there are only 207 usages of "<T>", and no
occurrences of "associatedtype T." My previous figures come from a grep of
the entire repo.

···

On Wed, Apr 6, 2016 at 6:19 AM, Noah Blake <nononoah@gmail.com> wrote:

I don't think there's much of a point solving this just for associated

types. The same issue exists for all protocol requirements.

True enough. The one difference worth noting, however, is that there's no
way to address the ambiguity of identical protocol requirements without
adding syntactical overhead. In the case of associatedtype inferencing,
however, it should be possible.

Then don't do that. Absurdly short associated/generic type names are like

absurdly short variable or function names—they're okay in a very small
context like a short function or a single loop, but a bad idea in a wider
context. That's why the Swift 2 standard library moved away from using
short names like `T` in generic types like Array and Optional.

While this may be a bit orthogonal, it's worth noting that the standard
library has increased its usage of T over the past month. Right now, it
contains 3932 occurrences of <T>. Plenty of these usages are type-scoped.
To your point, there are only 46 occurrences of "associatedtype T".

Regardless, there are plenty of longer, arguably better associatedtype
names that writers of different packages may commonly reach for. "Element"
may be known to be somewhat off limits, but it is representative of this
category.

On Wed, Apr 6, 2016 at 1:45 AM, Brent Royal-Gordon <brent@architechies.com > > wrote:

> Types associated with a protocol are not namespaced by the protocol,
but rather by the protocol's adopters. As such, when two protocols declare
a common associatedType, adoption of those protocols introduces undesirable
ambiguity.

I don't think there's much of a point solving this just for associated
types. The same issue exists for all protocol requirements.

> Given the understandable propensity of developers to arrive at
similarly named types (T, for example), it is likely that this problem will
reduce the compatibility of packages for reasons that may not be entirely
clear to the package consumer.

Then don't do that. Absurdly short associated/generic type names are like
absurdly short variable or function names—they're okay in a very small
context like a short function or a single loop, but a bad idea in a wider
context. That's why the Swift 2 standard library moved away from using
short names like `T` in generic types like Array and Optional.

--
Brent Royal-Gordon
Architechies