Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pitch: Deprecate ActionProtocol #248

Merged
merged 2 commits into from Feb 27, 2017
Merged

Conversation

sharplet
Copy link
Contributor

@sharplet sharplet commented Feb 5, 2017

...instead of removing it completely. See the discussion on #245 for context. I'm proposing this change as an alternative for discussion: there are some issues with this approach, so I thought it would be good to have something concrete to discuss.

Benefits:

  • Mergeable into master now, suitable for inclusion in the next minor release.
  • ActionProtocol is an implementation detail, but isn't clearly documented as such. There are possibly users making use of it in ways we didn't intend (I was once one of them).

Update: See #248 (comment).

Downsides:
  • Because conditionally compiled code has to be syntactically valid, we essentially have to duplicate the extension. I experimented with using an internal typealias to work around this limitation, but it was unfortunately a dead-end.

I don't have much of a problem with the amount of duplication in this case. But it's pretty clear to me that this approach won't scale all that well to SignalProtocol and SignalProducerProtocol, whose extensions currently house all of the operator definitions. There would be a lot of duplication. There are certainly techniques we could use to avoid duplicating the implementations (reducing the duplication to declarations only), but they might not be pretty.

@sharplet sharplet mentioned this pull request Feb 5, 2017
@sharplet
Copy link
Contributor Author

sharplet commented Feb 5, 2017

Although I just realised something: given that 3.1 is supposed to be source-compatible with 3.0, I think we should be able to just slap the deprecation warning on and not duplicate anything?? I'll take a look at how to get Swift 3.1 to compile in 3.0 mode...

@sharplet
Copy link
Contributor Author

sharplet commented Feb 5, 2017

I've just pushed a change which removes the duplication.

@sharplet
Copy link
Contributor Author

sharplet commented Feb 5, 2017

I now believe this should work just fine for our other *Protocols, too. I'll do some more experimenting tomorrow.

@sharplet
Copy link
Contributor Author

sharplet commented Feb 5, 2017

... suitable for inclusion in the next minor release

Because the deprecation warning only shows for Swift >= 3.1, this could now go into a patch release.

@mdiep
Copy link
Contributor

mdiep commented Feb 5, 2017

Not sure what to do about the podspec error. I guess we should --allow-warnings?

@sharplet
Copy link
Contributor Author

sharplet commented Feb 5, 2017

Interesting, I didn't see that warning in my tests. I'll try with a different Xcode version and see if it comes up (I was using the 8.3 beta).

@sharplet
Copy link
Contributor Author

sharplet commented Feb 5, 2017

@available(swift, ...) is only, ahem, available, in Swift 3.1: https://github.com/apple/swift-evolution/blob/master/proposals/0141-available-by-swift-version.md. I'll have to nut out how to handle this properly under semver. Though if this is just going to emit a warning when compiling ReactiveSwift and not in user code, it might be fine to ignore it.

@andersio
Copy link
Member

andersio commented Feb 5, 2017

This is not source compatible since the definition has changed. Even if it is kept intact, the real problem is that we cannot do this with SignalProtocol and SignalProducerProtocol, while ideally we might want to do all these in one batch. Once we transfer the default implementations to the concrete type, existing external extensions to these two protocols would lose accesses to all those operators, unless we make trampolines.

Another issue would be the deprecation warnings in our codebases that cannot be suppressed, should we still have any extensions to these deprecated entities.

@sharplet
Copy link
Contributor Author

sharplet commented Feb 5, 2017

Yeah, we don't have to keep the incompatible changes, this should probably just be the deprecation. As the implementations have no longer moved, I'm not sure I see why we can't do this with the other protocols?

@andersio
Copy link
Member

andersio commented Feb 5, 2017

If it is just marking it unavailable deprecated, it should be okay for a point release. Just that for other protocols, specifically SignalProtocol and SignalProducerProtocol, AFAIU our codebase would get tons of deprecation warnings on the protocol extensions that cannot be suppressed.

@sharplet
Copy link
Contributor Author

sharplet commented Feb 5, 2017

I also just realised that it's not going to be possible to remove SignalProtocol and SignalProducerProtocol until we get recursive constraints in extensions (used for the flatten operator), which won't land until at least the Swift 4 timeframe. I don't think it would make sense to add a deprecation warning for these protocols until we have a version of that feature we can test with.

So, the current state of this PR:

  • On Swift 3.1, this change emits deprecation warnings for all uses of ActionProtocol
  • On Swift 3.0.x, this change emits an "invalid platform" warning in ReactiveSwift, but doesn't emit any warnings in calling code.

It's a shame that there's no way to suppress the deprecation warnings for uses internal to ReactiveSwift, and they're a little annoying. But I don't think I mind that for the sake of users. @ReactiveCocoa/reactiveswift I'd love to hear your thoughts on the matter of warnings internal to this codebase. It doesn't bother me, but I totally understand if others feel differently.

@mdiep
Copy link
Contributor

mdiep commented Feb 6, 2017

I don't mind internal deprecation warnings—so long as the next major release isn't far off.

If we really feel this is a pain, we could do it right before the last 1.x release.

@andersio
Copy link
Member

andersio commented Feb 6, 2017

I think recursive constraint is not relevant here, but parameterized extensions. Sadly, it seems the 2.0 plan has to be scrapped then. An alternative plan is to move everything except those that cannot (flattening, optionalize, etc), while keeping the protocols. Then we leave the remaining work to RAS 3.0. This way, we still have all operators hosted in the concrete type. That's said there is no guarantee that we would have parameterized extensions in Swift 4.0.

@sharplet
Copy link
Contributor Author

sharplet commented Feb 6, 2017

Maybe both? This definitely fails under Swift 3.1 with a recursive constraint error:

// Flatten.swift
extension Signal where Value == Signal ...

@andersio
Copy link
Member

andersio commented Feb 6, 2017

Hmm, perhaps.

By the way, I have a branch with producer operators converted, e.g.

extension SignalProducer where Value: _SignalProducerProtocol, Error == Value.Error {

But it got hit by an issue in overloading somehow specific to concrete type extensions, and it so far affects attempt and then.

Bug Report: https://bugs.swift.org/browse/SR-3873

Swift 3.1 now raises an error when using a private variable from an
inlined function.
@@ -207,6 +207,7 @@ private struct ActionState {
}

/// A protocol used to constraint `Action` initializers.
@available(swift, deprecated: 3.1, message: "This protocol is no longer necessary and will be removed in a future version of ReactiveSwift. Use Action directly instead.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it cannot be suppressed anyway, we may deprecate it for 3.0.x too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not so sure: currently it only generates a warning inside ReactiveSwift, so I like the idea that it won't generate any warnings for consumers.

Copy link
Member

@andersio andersio Feb 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would happen when building through Carthage in Swift 3.1 anyway... https://travis-ci.org/ReactiveCocoa/ReactiveSwift/jobs/201869272#L821

@sharplet
Copy link
Contributor Author

sharplet commented Feb 15, 2017 via email

@andersio
Copy link
Member

andersio commented Feb 15, 2017

@sharplet Oops, it still appears in the build log.
https://travis-ci.org/ReactiveCocoa/ReactiveSwift/jobs/199639595#L826

@andersio
Copy link
Member

Tried -suppress-warnings in 6eb9671 and it works.

@andersio
Copy link
Member

@sharplet With #272 merged, could you please rebase it on master and strip the swift(>=3.1) constraint of the deprecation?

@andersio andersio merged commit cdc3d25 into master Feb 27, 2017
@andersio andersio deleted the as-deprecate-action-protocol branch February 27, 2017 08:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants