Sent from my iPad
> On Jun 25, 2016, at 12:41 PM, Austin Zheng <austinzh...@gmail.com> wrote: > > >> On Jun 25, 2016, at 6:23 AM, Matthew Johnson <matt...@anandabits.com> wrote: >> >> Hi Austin, >> >> I’m sorry to say, but this proposal makes me really sad. I consider >> associated type inference one of the more elegant aspects of Swift. It >> would be very unfortunate to lose it. > > There are lots of "elegant" things that Swift could do, but has chosen not to > do for pragmatic reasons (e.g. generalized implicit conversions, type > inference that crosses statement boundaries). Given how terrible the > development experience can be right now in the worst case, I would happily > trade off some measure of convenience for better tooling. I understand the technical issues underlying the proposal. I wasn't sure how I would respond to this until Dmitri posted an alternative. IMO if we can solve the technical issues without giving up inference that is a huge win. It looks viable to me (as a non-expert - I hope a compiler engineer can confirm this). If this is indeed a viable alternative then there is no tradeoff necessary and the discussion becomes one of style / preference. In that discussion I fall strongly on the side of protocol requirement guided inference. > >> >> I am really pleased to see that Dmitri has offered an alternative that looks >> very reasonable. I’m hoping the Doug or Chris (or someone else from the >> core team) can chime in on the feasibility of this alternative. If it is >> considered viable and Dmitri isn’t able to write the proposal I would be >> happy to do so. >> >> If the alternative isn’t viable and we must proceed with a proposal to >> remove inference I think there is one crucial thing to consider that isn’t >> discussed in this proposal: retroactive modeling. As far as I can tell, >> this proposal will *prohibit* some types from conforming to some protocols. >> Specifically, if a type defines a typealias with a name that matches the >> name of an associatedtype in a protocol it would not be possible to >> retroactively model that protocol. Because of the name conflict an >> associatedtype declaration would not be allowed and the existing typealias >> would not meet the requirement. Consider this example: > > I actually think that the delineation between `associatedtype` and > `typealias` should make this legal, and will change the proposal as such. It > should be legal to bind an associated type to a type alias, and it should be > possible to define a type alias that shadows (but does not conflict with) an > associated type definition. This would fix the issue with retroactive > modeling. IIUC you're saying a type is allowed to have an `associatedtype` and `typealias` (or nested type) both bound to the same name as long as they resolve to the same type. Is that correct? That would at least preserve current expressiveness. > >> >> // Module A >> public struct S { >> public typealias Foo = Int >> } >> >> // Module B >> public protocol P { >> associatedtype Foo >> } >> >> // Module C >> import A >> import B >> >> // compiler error: `S` does not meet the `Foo` associatedtype requirement >> extension S : P { >> // compiler error: cannot define associatedtype `Foo` for `S` which >> already declares typealias `Foo` >> associatedtype Foo = String >> } >> >> I cannot support any proposal that breaks retroactive modeling in this way. > > Addendum aside, retroactive modeling is already suboptimal or broken in > multiple ways today - try conforming a protocol with associated type > 'Element' to a different protocol whose 'Element' means something completely > different. Did you mean conforming a type to two protocols with an 'Element' associatedtype? I consider that issue to be in the realm of multiple conformances rather than retroactive modeling. I can still > >> >> Another item that is not mentioned in this proposal is that typealias is not >> the only way to meet an associatedtype requirement in the language today. >> For example, this code is legal: >> >> protocol Foo { >> associatedtype Bar >> } >> struct S : Foo { >> struct Bar {} >> } > > I don't see how this is relevant. > > struct S : Foo { > associatedtype S = Bar > struct Bar { } > } Do you mean this? struct S : Foo { associatedtype Bar = Bar struct Bar { } } That would preserve current expressiveness. > >> >> If we *must* drop inference I prefer the alternative of just doing that: >> dropping inference, but otherwise leaving things alone. All associated type >> requirements would need to be explicitly satisfied using one of the >> mechanisms that is currently valid for satisfying a non-inferred associated >> type requirement. The ability to satisfy these requirements in a variety of >> ways is a *benefit* that provides valuable flexibility. > > I disagree that it's a benefit. It certainly saves a couple of keystrokes, > but you gain or lose no expressive power from this proposal, addendum > included. I'm happy to expand the alternatives section to discuss the other > ways to satisfy associated type requirements, though. Thank you for adding the clarifications. I feel a little better knowing we wouldn't lose expressive power, but still prefer the directed inference suggested by Dmitri. > >> >> I agree that something should look for a good solution to the subclass >> typealias issue, but I don’t think this is it. Ideally we would find a >> solution that works well in the presence of retroactive modeling making code >> such as the following valid: >> >> // module A >> protocol P1 { >> associatedtype Foo >> >> @infers(Foo) >> var foo: Foo { get } >> } >> // module B >> protocol P2 { >> associatedtype Foo >> >> @infers(Foo) >> func bar() -> Foo >> } >> >> // module C >> class Base { >> let foo: String = "foo" >> } >> class Derived : Base { >> func bar() -> Int { return 42 } >> } >> >> // module D >> import A >> import B >> import C >> import D >> extension Base : P1 {} >> extension Derived : P2 {} >> >> We don’t always control the protocol or type definitions we want to make >> work together. The ability to make code that “should work together” >> actually do so with minimal fuss is one of the great things about Swift. >> Any time we interfere with retroactive modeling we increase the need for >> boilerplate adapter types, etc. >> >> One detail appears to be implied by the proposal but isn’t explicitly >> stated. Specifically, it looks like the intent is that other than only >> being valid when used to meet a protocol requirement, associatedtype >> otherwise works like a typealias. It would be good to have this behavior >> clarified if the proposal moves forward. >> >> -Matthew >> >> >> >>> On Jun 25, 2016, at 12:50 AM, Austin Zheng via swift-evolution >>> <swift-evolution@swift.org> wrote: >>> >>> Hello all, >>> >>> Per Chris Lattner's list of open Swift 3 design topics >>> (http://article.gmane.org/gmane.comp.lang.swift.evolution/21369), I've put >>> together a proposal for removing type inference for associated types. >>> >>> It can be found here: >>> https://github.com/austinzheng/swift-evolution/blob/az-assoctypeinf/proposals/XXXX-remove-assoctype-inference.md >>> >>> Thoughts, criticism, and feedback welcome. There are at least two slightly >>> different designs in the proposal, and I'm sure people will have ideas for >>> even more. >>> >>> Best, >>> Austin >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org >>> https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution