> 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
