on Thu Aug 11 2016, Douglas Gregor <swift-evolution@swift.org> wrote:
> Sent from my iPhone > >> On Aug 4, 2016, at 2:36 AM, Haravikk via swift-evolution >> <swift-evolution@swift.org> wrote: >> >> >>>> On 4 Aug 2016, at 03:19, Brent Royal-Gordon via swift-evolution >>>> <swift-evolution@swift.org> wrote: >>>> >>>> On Aug 3, 2016, at 10:17 AM, Manav Gabhawala via swift-evolution >>>> <swift-evolution@swift.org> 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 doesn't really have any features that stop working across > modules. We're okay with the programmer having to think more and be > more explicit across module boundaries (since it is API design at that > point), but it'd take a very strong argument to have different runtime > semantics across module boundaries. > > FWIW, I'm planning to write a complete proposal for conditional > conformances and will start posting drafts once it is far enough along > to be useful. It won't have support for protocols conforming to other > protocols, though. So “a Collection is Equatable if its elements are?” == not supported? -- -Dave _______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution