-
Notifications
You must be signed in to change notification settings - Fork 263
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
Key union converted to a proper class #720
Conversation
This being a breaking change that touches user sketches without any deprecation period, warning, or back compat makes me fairly nervous. Is it -possible- to turn the previous union into a class and still use the undefined-but-supported-by-gcc behavior inside to expose the old raw, flags, and keyCode properties for some period of time? |
I definitely expected that. Very understandable.
This is something that gave me headaches for a long time. Still I haven't found a good solution. This is not about giving the I am agonizing over a solution that gives us both, the backward compatible behavior and still the ability to do fancy compile time things, yet without success. |
b5c77c0
to
b60b3b5
Compare
There's definitely no way to replace a union by a class without breaking anything. But at a closer look on the use cases of class This suggests that we could make the effects of the union->class transition for Code that uses the i force-pushed a change to this PR that replaces As in contrast to my first approach this solution requires storing @obra, I am sorry that I cannot reduce your level of nervousity to 0%. But maybe the proposed solution is acceptable, nonetheless. The perspective of obtaining the ability to do all sorts of fancy things with |
b60b3b5
to
547f17e
Compare
Factored out an unrelated change and moved it over to #721. Force pushed changes. |
0a18051
to
c231589
Compare
Heureka! Last night I had an epiphany. There is a way to support The trick is to make To be on the safe side, no instance for Access to Now we have a solution where users are properly warned and we still finally have a class |
That sounds acceptable to me.
ᐧ
…On Tue, Nov 19, 2019 at 12:54 AM noseglasses ***@***.***> wrote:
Heureka! Last night I had an epiphany.
There *is* a way to support Key::keyCode, Key::flags *and* Key::raw event
when moving away from a union to a class.
The trick is to make Key::raw a static member and emit a deprecation
message that informs the user about all access to Key::raw having to be
replaced by Key::getRaw() and Key::setRaw().
To be on the safe side, no instance for Key::raw will be provided and the
code will fail to link until all access to Key::raw has been properly
replaced.
Access to Key::keyCode and Key::raw will trigger a normal deprecation
warning.
Now we have a solution where users are properly warned and we still
finally have a class Key.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#720?email_source=notifications&email_token=AAALC2EUOAOX4OW2IHUGI23QUOSWBA5CNFSM4JMGRZ6KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEENLVYY#issuecomment-555399907>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAALC2HFOEAE2Z3WXXIEGULQUOSWBANCNFSM4JMGRZ6A>
.
|
(I'm reviewing the code now) |
I'd love to get @algernon's take on this before merge. |
I'll go over this first thing tomorrow. Already started, but won't be able to finish before I fall asleep. |
Right... I promised a review, but today didn't quite go as originally planned, so all I can offer is a first impression. I definitely like the direction this is taking, but it is a breaking change, even with the What I love about this PR, is All in all, my first impression is to stamp my approval. We'll need to update |
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.
stamp of approval
I did leave two small comments about the text of the deprecation, but those should not hold up merging this PR, we can quickly fix the texts after, and add an example or two to UPGRADING.md
.
#define _DEPRECATED_MESSAGE_DIRECT_KEY_MEMBER_ACCESS \ | ||
"Direct access to `Key` class' data members is deprecated.\n" \ | ||
"Please use `Key::setKeyCode()`/`Key::getKeyCode()` or\n" \ | ||
"`Key::setFlags()`/`Key::getFlags()` 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.
I think this should be reworded a bit. It's clear to anyone who knows C++, but for someone who's just copy & pasting code, this might as well be Klingon. I think a better way would be to point them to UPGRADING.md
, where we can provide a few examples of how to get from the old style to the new one.
To be honest, just slap For further information and examples on how to do that, please see UPGRADING.md
.
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.
Modified deprecations.h
, now pointing to UPGRADING.md
.
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.
Now, as even Duolingo supports Klingon, one can expect more and more Klingon speaking users around 😏
"use `Key::setRaw()`/`Key::getRaw()` to set and get raw data.\n" \ | ||
"\n" \ | ||
"Important: This is not a deprecation. Your code will compile but fail\n" \ | ||
" to link until all access to `Key::raw` has been replaced." |
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.
Same as above, slapping the same text at the end of this should do the trick, and point people to the right direction even better.
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.
Modified deprecations.h
, now pointing to UPGRADING.md
.
Unions are a C-reminiscense that are better avoided in modern C++. They cause specific problems due to their nature of representing independent types. The way they are used in Kaleidoscope, they can easily be replaced by a class. This enables it to properly work with Key objects in constexpr context where with the old union-based implementation the compiler reported errors when one Key was constructed based on a key_code/flags pair and another one through raw-data. In such a case, the compiler assumes that both Key instances represent something entirely different. This is because unions were never meant for type conversions and the C++ standard considers their use for that purpose as undefined behavior. The new class provides accessor methods for raw-data access and for key_code/flags-data access. This is a breaking change as it is is not possible to replace direct member access patterns like key.raw = 0xFFFF; based on the raw-accessors. For the .keyCode and .flags members, proxy objects are used to enable the generation of suitable deprecations warnings. All direct access via .raw, .keyCode and .flags have been replaced throughout Kaleidoscope. Information on how to upgrade is provided in UPGRADING.md Signed-off-by: Florian Fleissner <florian.fleissner@inpartik.de>
c231589
to
ba79eef
Compare
Thanks @algernon for the review and the positive comments. I totally forgot about |
I'm +1 to merge once @algernon signs off. |
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 job on the docs!
Important: This PR introduces a breaking change. All code that accesses the
Key::raw
member directory will break.Travis fails because there are two more PRs that need to be merged along with this to
allow the entire firmware to build.
keyboardio/Kaleidoscope-HIDAdaptor-KeyboardioHID#21
keyboardio/Model01-Firmware#92
Unions are a C-reminiscense that are better avoided in modern C++.
They cause specific problems due to their nature of representing
independent types. The way they are used in Kaleidoscope, they
can easily be replaced by a class.
This enables it to properly work with Key objects in constexpr context
where with the old union-based implementation the compiler reported
errors when one Key was constructed based on a key_code/flags pair and
another one through raw-data. In such a case, the compiler assumes that
both Key instances represent something entirely different. This is
because unions were never meant for type conversions and the C++
standard considers their use for that purpose as undefined behavior.
The new class provides accessor methods for raw-data access and for
key_code/flags-data access.
This is a breaking change as it is is not possible to replace direct
member access patterns like
key.raw = 0xFFFF;
based on the raw-accessors.
All direct access via .raw, .keyCode and .flags have been replaced
throughout Kaleidoscope.
Signed-off-by: Florian Fleissner florian.fleissner@inpartik.de