[Development] Removal of Non-deprecated API Elements in v6.6.0
Volker Hilsheimer
volker.hilsheimer at qt.io
Thu Oct 19 16:03:18 CEST 2023
> On 19 Oct 2023, at 13:07, Giuseppe D'Angelo via Development <development at qt-project.org> wrote:
>
> On 19/10/2023 12:07, Phil Thompson via Development wrote:
>> Up until v6.6 upgrading to a new version was relatively low risk but this will just encourage people to stay on older versions. Is this a mistake or a change in policy?
>
> There is actually a policy document that says that certain source breaks are acceptable, especially the ones that prevent mistakes from users:
>
> https://contribute.qt-project.org/quips/6
>
> I'm not really sure about the real-world impact of the change in question, but there's an argument that this fits the QUIP-6 bill:
>
> * if you have a non-const QSqlRecord object, you can keep calling boundValues(). You would still get a mutable reference to the bound arguments -- that is, that is 100% API compatible.
>
> * If you have a const QSqlRecord, and you're trying to mutate the bound values, then your code rightfully stops compiling, as you're not supposed to do that. You can fix this in a way that works with Qt before and after 6.6. So, you should do that.
>
> Granted, each source-incompatible change disrupts _someone_ _somehow_. I'm not sure where to draw the line: "this has to wait 10 years for Qt 7" vs. "we should be changing this now, as we're making users a disservice with a suboptimal/dangerous/misleading API" are both valid arguments, but it's not a binary choice, it's much more of a gradient. For this specific change, it's also interesting that it landed after 6.5, giving people plenty of time to adapt.
Removing APIs (via the REMOVED_SINCE mechanism, which leaves the symbol in the ABI by still compiling it when building Qt, but removes it from the API from the specified version on) is usually only done when there is a source compatible replacement. The removal might then be done to enable the replacement without introducing ambiguities.
E.g. we removed
QReadWriteLock::tryLockForRead()
because we wanted to add
bool tryLockForRead(QDeadlineTimer timeout = {})
This is source compatible, but we don’t need both. And various QXmlStreamAttributes::value overloads were removed and replaced by a single version using QAnyStringView, which should also be source compatible; but without removing the old, the new API would have resulted in ambiguities.
In the specific case of the QSqlRecord APIs, we decided to remove them; as Peppe points out, it’s source compatible, unless you were doing something that is potentially dangerous and possibly resulting in a corrupted internal state. And it then breaks the build rather than silently breaks your application. Looking through the REMOVE_SINCE(6, 6) usage in my source tree, there shouldn’t be any other API removals that result in source incompatibility, but we might have made a mistake somewhere.
The technical process by which we deprecate APIs is generally documented here:
https://wiki.qt.io/Deprecation
That page doesn’t give any guidance on how deprecations should be phased: how many releases after a replacement API was added should a warning be generated from the old API? Some people use “the release after an LTS”, which was a conclusion from Qt CS 2014 [1] when the concept of LTS was established.
[1] https://wiki.qt.io/Qt-contributors-summit-2014-Long_term_releases
Qt 6.6 is such a release.
But removing an API after deprecating would suggest that the removal would not be source compatible anyway (otherwise, why deprecate?), and there wouldn’t be any replacement API to port to and silence the warnings either.
Volker
More information about the Development
mailing list