Limitation of implicitly opening existentials?

It was nice to see that Combine's Scheduler protocol has a new primary associated type in the betas, but unfortunately it doesn't seem to be usable given Combine's APIs:

let scheduler: any Scheduler<DispatchQueue.SchedulerTimeType>
scheduler = DispatchQueue.main
Just(2).delay(for: 1, scheduler: scheduler)

:stop_sign: Type 'any Scheduler<DispatchQueue.SchedulerTimeType>' cannot conform to 'Scheduler'

This seems to be because the for interval parameter references the scheduler generic, and/or because the Publishers.Delay returned from the operator references the scheduler generic.

Is this just a known limitation that will be fixed some day? Or is it a bug that should be reported?


I believe both issues prevent the implicit opening under the rules of SE-0352.

The limitation from the interval parameter seems like it could eventually be lifted in certain circumstances (e.g., here, the SchedulerTimeType.Stride is statically known via the primary associated type constraint), but the issue with the return type is more fundamental. There's no generic argument that we could instantiate the Publishers.Delay type with for the S parameter (because the opened type isn’t permitted to propagate ‘out’ from the call). Maybe there’s some additional generics features that could make this sound, though.


Alternatively, if Combine had provided the following return type it would have been fine?

-> some Publisher<Output, Failure>

Or even:

-> Publishers.Delay<Self, S.SchedulerTimeType>

Right, I think those should be okay since they hide the identity of the opened existential.

1 Like