> On 4 Aug 2016, at 03:19, Brent Royal-Gordon via swift-evolution 
> <[email protected]> wrote:
> 
>> On Aug 3, 2016, at 10:17 AM, Manav Gabhawala via swift-evolution 
>> <[email protected]> wrote:
>> 
>> I was wondering why this would put any more of a burden on the runtime
>> than simple inheritance of protocols. The way this could be
>> implemented is to augment the ConformanceTable for nominal types by
>> looking up its protocol extension’s inheritance clauses. I can
>> definitely see this impacting compile time but I don’t see why runtime
>> performance will be any different than simple inheritance. Further,
>> cyclic chains can be detected and broken (compiler error) during the
>> second pass of semantic analysis.
> 
> My understanding—which may be incorrect, by the way—is that the issue is 
> mainly with protocol extensions adding conformances, not specifically with 
> those conformances being conditional, and that it specifically has to do with 
> `is` and `as?` checks across module boundaries.
> 
> Suppose you have these declarations in module M:
> 
>       public protocol AProtocol {…}
>       public protocol BProtocol: AProtocol {…}
>       public protocol CProtocol {…}
>       
>       // Public or otherwise doesn't matter here.
>       public struct Foo: BProtocol {…}
> 
> Foo essentially has a flat list of the protocols it conforms to attached to 
> it. Notionally, you can think of that list as looking like:
> 
>       Foo.self.conformsTo = [BProtocol.self, AProtocol.self]
> 
> And when you write `foo is CProtocol`, that eventually translates into:
> 
>       foo.dynamicType.conformsTo.contains(CProtocol.self)
> 
> For a `Foo`, since the `conformsTo` list doesn't include `CProtocol.self`, it 
> returns `false`.
> 
> Now imagine that you write a new module, N, and in it you say:
> 
>       extension Foo: CProtocol {…}
> 
> You have now retroactively conformed `Foo` to `CProtocol`. Swift needs to 
> reach into module M and add `CProtocol.self` to the `Foo.self.conformsTo` 
> list. This is perfectly doable for a concrete type—it's one flat list, after 
> all.
> 
> Instead, though, imagine that module N extended `AProtocol` to add a 
> conformance:
> 
>       extension AProtocol: CProtocol {…}
> 
> There are two ways to handle this. One is to find all types conforming to 
> `AProtocol`, recursively, and add `CProtocol.self` to their conformance list. 
> The other is to scrap the flat list of conformances and instead make `is` and 
> `as?` recursively search each protocol. Either way, you have replaced a fast, 
> flat operation with a slow, recursive one.
> 
> Conditional conformance adds another wrinkle to this, of course—you must not 
> only recursively search the list, but also evaluate the condition to see if 
> it applies in this case. But the general problem of having to replace a fast 
> search with a slow search applies either way.

Great explanation! This switch from flat to recursively searched though seems 
like it would only occur when the extension is in an external module though; 
for internal modules would it not still be possible to determine the flat list 
for each type? In that case extending a type from another module could be 
either disallowed, or produce a warning to indicate the performance implication?

The feature would still be very useful even just for internal use after all. 
Also it seems useful on a relatively small number of types, and the number of 
external modules that need/want to do this must narrow that even further, so 
external extensions may be quite niche, i.e- not worth losing the feature for 
internal use if that is indeed easier?
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to