-
Notifications
You must be signed in to change notification settings - Fork 543
CXX-2109 Deprecate all references to utf8 #744
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
Conversation
src/bsoncxx/document/element.cpp
Outdated
|
||
types::b_utf8 element::get_string() const { | ||
types::b_utf8 element::get_utf8() const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the utf8
in BSONCXX_ENUM(utf8, 0x02)
was replaced with string
, this method is no longer created by the macro above. Now, get_string
is created instead. I needed to add this manually for backward compatibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch!
src/bsoncxx/types.hpp
Outdated
@@ -122,10 +158,14 @@ struct BSONCXX_API b_utf8 { | |||
template <typename T, | |||
typename std::enable_if<!std::is_same<b_utf8, typename std::decay<T>::type>::value, | |||
int>::type = 0> | |||
BSONCXX_INLINE explicit b_utf8(T&& t) : value(std::forward<T>(t)) {} | |||
BSONCXX_INLINE BSONCXX_DEPRECATED explicit b_utf8(T&& t) : value(std::forward<T>(t)) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Originally, I tried to deprecate the entire struct. That was a disaster. Deprecating the struct will, predictably, throw a deprecation warning anywhere b_utf8
appears. This includes public headers. So our code won't compile. Using BSONCXX_SUPPRESS_DEPRECATION_WARNINGS...
in public headers would be bad since it's in a private header and using it would defeat the purpose of deprecating the struct in the first place. This was the alternative I came up with but I'm open to other ideas.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've been able to deprecate a class before gracefully, and I think that the same flow would work for a struct. Here's what we did for the ssl -> tls rename:
- Implement new/newly-named NewThing
- Remove old class Thing
- Add a deprecated typedef alias for Thing
///
/// This class has been renamed to NewThing.
///
/// @deprecated use the NewThing class instead.
///
MONGOCXX_DEPRECATED typedef NewThing Thing;
- Change all instances of Thing -> NewThing in parameters and return values in header files. Since the alias is there, this shouldn't break user code.
Are there any places that b_utf8
appears in public headers that you don't think we can get rid of with this strategy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That worked! b_utf8
is now removed.
src/bsoncxx/types.hpp
Outdated
operator b_string() { | ||
return b_string{value}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll notice this can't be round-tripped, i.e., operator b_utf8
isn't defined in b_string
. This is because we would have to create a b_utf8
in the definition and the constructor for the b_utf8
is deprecated. Again, this is a public header so including the private header containing BSONCXX_SUPPRESS_DEPRECATION_WARNINGS...
would be a bad idea. I could create a public version of the suppression warnings but that would just allow users to bypass the deprecation warning, assuming that even works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that we should not create a public version of the suppression warnings.
With the typedef strategy I mentioned in a different comment, I think this issue would go away.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/bsoncxx/document/element.cpp
Outdated
|
||
types::b_utf8 element::get_string() const { | ||
types::b_utf8 element::get_utf8() const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch!
src/bsoncxx/document/element.cpp
Outdated
types::bson_value::view v{_raw, _length, _offset, _keylen}; | ||
return v.get_string(); | ||
BSONCXX_SUPPRESS_DEPRECATION_WARNINGS_BEGIN | ||
return v.get_utf8(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this call the new v.get_string()
instead ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/bsoncxx/types.hpp
Outdated
@@ -122,10 +158,14 @@ struct BSONCXX_API b_utf8 { | |||
template <typename T, | |||
typename std::enable_if<!std::is_same<b_utf8, typename std::decay<T>::type>::value, | |||
int>::type = 0> | |||
BSONCXX_INLINE explicit b_utf8(T&& t) : value(std::forward<T>(t)) {} | |||
BSONCXX_INLINE BSONCXX_DEPRECATED explicit b_utf8(T&& t) : value(std::forward<T>(t)) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've been able to deprecate a class before gracefully, and I think that the same flow would work for a struct. Here's what we did for the ssl -> tls rename:
- Implement new/newly-named NewThing
- Remove old class Thing
- Add a deprecated typedef alias for Thing
///
/// This class has been renamed to NewThing.
///
/// @deprecated use the NewThing class instead.
///
MONGOCXX_DEPRECATED typedef NewThing Thing;
- Change all instances of Thing -> NewThing in parameters and return values in header files. Since the alias is there, this shouldn't break user code.
Are there any places that b_utf8
appears in public headers that you don't think we can get rid of with this strategy?
src/bsoncxx/types.hpp
Outdated
operator b_string() { | ||
return b_string{value}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that we should not create a public version of the suppression warnings.
With the typedef strategy I mentioned in a different comment, I think this issue would go away.
src/bsoncxx/types.hpp
Outdated
@@ -668,6 +708,10 @@ BSONCXX_INLINE bool operator==(const b_maxkey&, const b_maxkey&) { | |||
#include <bsoncxx/enums/type.hpp> | |||
#undef BSONCXX_ENUM | |||
|
|||
BSONCXX_INLINE bool operator!=(const b_utf8& lhs, const b_utf8& rhs) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also should be covered by the new b_string methods if there is a typedef alias
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good!
@@ -17,7 +17,7 @@ | |||
#endif | |||
|
|||
BSONCXX_ENUM(double, 0x01) | |||
BSONCXX_ENUM(utf8, 0x02) | |||
BSONCXX_ENUM(string, 0x02) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this renaming causes some API removal.
grepping through all .hpp files for #include <bsoncxx/enums/type.hpp>
, I think these would be removed.
type::k_utf8
is defined insrc/bsoncxx/types.hpp
.error_code::k_need_element_type_k_utf8
anderror_code::k_cannot_append_utf8
are defined. These are integer error codes which I don't believe we can change.
Both cases are enum values.
For those cases, we may need to redefine each at the same integer value.
Ideally we can deprecate the old utf8 value. There may not be a completely portable way of doing so, but #pragma deprecated
would at least deprecate for compilers that recognize the pragma. Ideally, users are informed by a compiler warning. But at the very least, we can give them notice via release notes.
Here's what I'm thinking.
///
/// An enumeration of each BSON type.
/// These x-macros will expand to be of the form:
/// k_double = 0x01,
/// k_string = 0x02,
/// k_document = 0x03,
/// k_array = 0x04 ...
///
enum class type : std::uint8_t {
#define BSONCXX_ENUM(name, val) k_##name = val,
#include <bsoncxx/enums/type.hpp>
#undef BSONCXX_ENUM
k_utf8 = 0x02
};
#pragma deprecated(k_utf8)
I think this could be a motivation for doing CXX-641 before the next release as well. That way we can double check ABI changes before we release. I moved that to "Needs Triage".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. I added k_utf8
and deprecated it using BSONCXX_DEPRECATED
. For the error codes, I added them back to error_code.hpp
. They're at the end of the enum to avoid changing other error code values. I set them to the _string
variants since they share the same values. I did not add them to the switch statements in error_code.cpp
. You can't add a new case for the same values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it appears that the ability deprecated enum values didn't appear until GCC-6 (source):
The C and C++ compilers now support attributes on enumerators. For instance, it is now possible to mark enumerators as deprecated:
enum { newval, oldval __attribute__ ((deprecated ("too old"))) };
The code snippet above (#pragma deprecated(k_utf8)
) doesn't even compile locally so I'm not sure if it's possible to deprecate this.
Local compilers:
➜ g++ --version
g++ (Ubuntu 10.2.0-13ubuntu1) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
➜ clang --version
Ubuntu clang version 11.0.0-2
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might just have to leave this and error code as is until the next major release. @samantharitter any ideas?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for looking into it. If there's isn't a straightforward way to deprecate it, then I agree we'll have to leave it for now. We can note the deprecation in release notes.
I verified #pragma deprecated
will warn on compilers that don't recognize it: https://godbolt.org/z/xPhvoe so I agree that's not a viable solution unless we #ifdef
it with compilers we know support the pragma.
7ba5c50
to
a9c728c
Compare
@kevinAlbs and @samantharitter unfortunately, to fix merge conflicts, I ended up squash all of the commits into one. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM as well!
No description provided.