Welcome to the community @lordzsolt. You raise a valid concern. I concur with @Rod_Brown that while reporting a bug is important, it is not very helpful. That must be really frustrating to always see the one warning.
You forgot the fourth and fifth options
- Move the code into a simple module that is compiled with deprecation warning turned off and imported by your main module.
- Move this code into an objc file.
This is a concern for us with Swift 5.5 / async. We will effectively be deprecating large numbers of completion-blocks APIs, because we want to discourage new uses of them in favor of new async versions. However, doing so will create a bajillion "use of deprecated API" warning in every file immediately.
Ideally we want to grandfather in existing uses and warn on new ones. A callside mechanism to suppress the deprecation warning would be sufficient for this purpose.
I think this pitch is trying to handle this case: only warn about use of the āoldā completion handler API if itās being called from an async context, where the async alternative would be preferred.
The problem with this is that it loses the opportunity to give us hints about contexts that should be async but arenāt. Doing this would either require an opt-in to always show the warnings, or a separate tool that does all the analysis redundantly.
(See also: Auditing potentially async code)
This, like deprecation warnings, seems like a case where judicious use of optional warnings (and selective -Werror) would be to everyoneās benefit.
+1 for any solution that gives me a command line switch to disable all suppressions so I can quickly get a list of all potential code problems regardless of wether the associated warning has been suppressed.
This hit me again today: due to some implementation and specification changes, it has become awkward to support an existing API and the best thing to do is deprecate it. I've managed to back-port it (at a significant performance cost) to support anybody who might be using it, but I intend to remove it in the near future.
The problem is: I can't test the back-porting code without adding a bunch of warnings all over my tests.
It's fine, I can take that, but I'd rather not. It's messy and obscures actual warnings that might be alerting me to issues with my test code.
If you're using XCTest, you can test deprecated APIs by marking the test method or class as deprecated itself. Deprecated code is allowed to call other deprecated code, so this will suppress the diagnostics on the calls you're making, but XCTest invokes your test cases without physically writing those names in source code, so it won't raise any new deprecations.
I love coming back to the same thing I wrote every year when I deprecate the oldest iOS version we support because I google 'swift suppress deprecation warnings' and this is still the top result.
In case anyone is wondering if this is improved, there is one change since I wrote the original post; SE-0443 allows for selectively 'upgrading' warnings to errors.
However the language still lacks the ability to selectively allow existing cases in source, as Objective-C could do with pragma clang diagnostics. SE-0443 only helps if you want to declare bankruptcy on deprecation warnings, for example, and still block any other warnings from landing (by converting them to errors). It would not help you if you maintain a 'clean' codebase with no warnings.
There may have been some other swiftlang proposal to allow for suppressing warnings at a source level that someone sent me at some point, but I cannot find it right now.
In short, the solutions presented in the original post are still valid, and in case anyone is wondering what we're doing with our millions of lines of Swift every year when we deprecate; we tend to just wrap those Apple SDKs in a Objective-C target that suppresses the deprecation warnings via new APIs prefixed with '_deprecated' and call that Objective-C target from Swift.
I'm confused, doesn't SE-0443 specifically bring -Wwarning, which keeps specified warnings as warnings even with -warnings-as-errors?
One of Swift's goal is to ensure safety, and the compiler has a reason for any warning it emits. I think a meaningful goal is to prevent compilation failure due to some warnings, rather than to "clean" those warnings visually.
It's best to have 0 warnings, so you immediately notice any new warnings. It's also best to avoid using deprecated APIs but sometimes there is no replacement or it doesn't do what you want, so you have to use the deprecated API. In this case, you want to silence the warning only on that specific line.
I know some people even bloat their warning count to 100s or even 1000s with SwiftLint and they think having that many warnings is normal but it really shouldn't be normal.
Sure, you can keep deprecated warnings as warnings and still upgrade all other warnings to errors. But if you do that, you can't block a PR that someone writes where they add a new deprecation warning to the codebase. If you're a team of one, who cares? But if you're a team of hundreds, you probably want to block (i.e., fail the compilation step) when some random engineer wants to commit new code to the codebase using deprecated APIs.
But even if "One of Swift's goal(s) is to ensure safety", the Swift team doesn't decide which deprecations ship with the SDKs on Apple's platforms. There are dozens, likely even hundreds, of teams that write those SDKs and decide when/how to deprecate their APIs. As a wrapper around those SDKs, they simply have to surface those deprecation warnings to the end user. Deprecations on Apple platforms are not uniformly as 'important' as each other, and individual SDK authors in Apple manage deprecations differently. Sometimes they deprecate an entire type, which causes havoc for anyone using that type (from within a Swift codebase). Sometimes they ship a deprecation where the new API is only added in the same SDK version the old API was deprecated in, meaning you cannot easily write a feature flag that switches between both, you have to wholesale replace the old API with the new one, and hope that you can test every corner case before shipping your unflagged code.
But the difference was that Objective-C had a great sourceālevel solution to balancing a 'no warnings codebase' with the needs of an organization that wants to change their Deployment Target on a timely cadence (say, yearly). With Objective-C you can bump your Deployment Target for iOS to a new version and still 'allow list' existing deprecation warnings with a pragma clang suppression on individual cases in source code. Bumping your Deployment Target can be done in a few days, instead of several weeks or months.
The reason today why Apple doesn't do anything here is that members of the Swift core team don't agree with the general idea of keeping a 'no warnings codebase', and they are disconnected from this issue because most binaries/frameworks inside Apple simply use the latest SDKs and never have to care about supporting more than one iOS version because their binary/framework ships with the OS (it only ever supports the current version of the OS). There are few cheerleaders inside Apple advocating for solving this problem.
The rare teams inside Apple who would even be close to having the problem an external developer has, are teams with apps that ship to the App Store (e.g., the 'Sports' app, or the 'Keynote' app), and I'm guessing they manage a codebase littered with thousands of warnings.
At the time this thread originally started, I think it was probably true that there was more resistance in general to adding diagnostic control features to Swift. However, the acceptance SE-0443 and the discussion of that proposal indicate to me that there is appetite for more capabilities in this vein. In addition to establishing precedent for diagnostic control features in Swift, that proposal also introduced named diagnostic groups which are an important building block that would be needed for this feature.
I think that what is needed most to make progress on this topic is concrete discussion of what the syntax and semantics of this feature would be, taking the foundation established by SE-0443 into account.
When you work on software that always has the latest available deployment target, you see more deprecation warnings than in projects that deploy to older versions of the OS. Deprecation warnings only get emitted by the compiler when the deployment target is at least as high as the version that the given declaration was deprecated in, so projects with older deployment targets don't get warnings about newly APIs without also raising their deployment targets. Projects with the latest deployment target get warnings about new deprecations immediately.
I know for a fact that many, many people are interested in seeing this problem solved. I don't think lack of understanding of the motivation is the primary blocker. Philosophy (discussed earlier) and prioritization versus all the other things that also ought to be added to Swift are the more significant hurdles.