[swift-evolution] Renaming for Protocol Conformance

David Waite david at alkaline-solutions.com
Tue Aug 23 12:47:48 CDT 2016


C# does something similar to this - you can implement an interface without having the implementation methods published on the object. You must cast/box to the interface in order to access those methods.

This is used for instance to support both the generic and non-generic interfaces for dictionaries in the same class.

I don’t know if an object should expose either method with the same name as the parent protocols if they conflict - I would imagine someone being burned by getting incorrect behavior, and I’m trying to think if there would be interesting semantics with generic code.

-DW

> On Aug 22, 2016, at 11:39 PM, Karl via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
>> On 23 Aug 2016, at 06:59, Jonathan Hull via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>> Hi everyone,
>> 
>> We talked about this before when we were discussing mixins, and there seemed to be generally positive feelings towards it as a feature for the future.  I am fairly certain this affects the ABI though, so I thought I would bring it up now.
>> 
>> If two protocols have methods/properties with the same name, but different signatures, we need a way to distinguish between them when attempting to conform to both.
>> 
>> 	protocol A {
>> 		var x:Int {get set}
>> 	}
>> 
>> 	protocol B {
>> 		var x:Double {get set}
>> 	}
>> 
>> One possibility is to allow a struct/class/enum to conform to the protocol while renaming one (or both) of the clashing methods:
>> 
>> 	struct C: A,B {
>> 		var x:Int
>> 		var y:Double implements B.x
>> 	}
>> 
>> The conforming method/property would still have to have the same signature, but could have a different name (and parameter labels).  It would also allow protocol methods which have identical signatures and semantics, but different names to be implemented using the same method (i.e ‘implements D.z & E.w’).
>> 
>> When something is cast to the protocol (say ‘as B’), then calling the property (e.g. ‘x’) would end up calling the implementation of the renamed property ( ‘y’ in this example) on the conforming type.
>> 
>> I think we would also want a way to retroactively conform using existing properties/methods in an extension declaring conformance.  Not sure what the best syntax for that would be.  Off the top of my head (though I would love to have something with less cruft):
>> 
>> 	extension D:B {
>> 		@conform(to: B.x, with: D.y)
>> 	}
>> 
>> or maybe just:
>> 	
>> 	extension D:B {
>> 		D.y implements B.x
>> 	}
>> 	
>> 
>> All of this is merely to start the discussion, so feel free to propose better syntax or a more elegant solution...
>> 
>> Thoughts?
>> 
>> Thanks,
>> Jon
>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> What about if we synthesised members on the conforming type? So I’m thinking
> 
>  protocol MyProtoOne {
>  	func doSomething()
>  }
> 
>  protocol MyProtoTwo {
>  	func doSomething()
>  }
> 
>  struct ImplementsOne : MyProtoOne {
>  	func doSomething() {
>  		// Unambiguous. Satisfies MyProtoOne.
>  	}
>  }
> 
>  struct ImplementsBoth : MyProtoOne, MyProtoTwo {
>  	
>  	func MyProtoOne.doSomething() {
>  		// Or some other declaration modifier to say this for MyProtoOne
>  	}
> 
>  	func MyProtoTwo.doSomething() {
>  		// ...
>  	}
>  }
> 
> ImplementsOne().doSomething() // unambiguous intention at call-site
> ImplementsBoth().MyProtoOne.doSomething() // intention at call-site must be explicit. What kind of thing do you want to look at ImplementsBoth() as?
> ImplementsBoth().MyProtoTwo.doSomething()
> 
> I think this would be relatively simple to implement. We just disambiguate at declaration site, and the synthesised members ImplementsBoth().MyProto{One/Two} are the protocol-witness tables to disambiguate at the call-site.
> 
> The thing is that we would need to mangle those names differently, and for ABI resilience (the ability to add a protocol with a conflicting name later) that would mean also mangling the protocol name in to the non-conflicting cases (ImplementsOne.MyProtoOne.doSomething). That means if you had ImplementsOne.doSomething in v1 and added the MyProtoOne protocol in v1.1, you would need to add a plain doSomething() method which doesn’t belong to a protocol.
> 
> That’s the thing — members would kind of “belong” to the protocol conformance on the type, rather than being plain top-level members on the type itself (although as long as there are no conflicts, you could use them as such and the compiler would know which members you mean). That may be beneficial for mixins.
> 
> Karl
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



More information about the swift-evolution mailing list