- Notifications
You must be signed in to change notification settings - Fork 263
Add a clang-specific impl->projection conversion operator#1274
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
Uh oh!
There was an error while loading. Please reload this page.
Conversation
DHowett commented Feb 14, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
The conversion from `producer_convert` to `const producer_ref` does not improve const-correctness, and in compliant compilers¹ prevents the conversion of `producer_convert` (ala `winrt::implements<D, I>`) to `producer_ref<T>`'s base type `T`. In brief², this is because conversion acts as rvalue reference construction via `T(T&&)`; a `const`-qualified rvalue cannot bind an rvalue reference. The `const`ness here doesn't impart any additional safety, either: - It contains only an untyped pointer, the constness of which does not restrict its holder from any additional access to either the implementation or projected types. - It exists to convert to its base type T, and it will do so by copy. That copy will contain (hidden) the same pointer, but will often not be `const`-qualified; any code that holds it will likely have unfettered access to that In short, it's a `const`-qualified temporary that exists to convert a `winrt::implements<D, I>` from non-`const` `D` to non-`const` `I`. Given that holding on to a `producer_ref` is in violation of the C++/WinRT `impl` namespace contract _anyway_, be it `const`-qualified or not, this should be a safe change to make. Closesmicrosoft#1273 ¹ http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2077 ² https://stackoverflow.com/a/70654432
DHowett commented Feb 14, 2023
/cc @DefaultRyan@oldnewthing as mentioned in #1273. |
DHowett commented Feb 14, 2023
(I'll dig in on the ASAN failures, which didn't reproduce when I ran the test suite locally.) |
lhecker commented Feb 14, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
Edit: With the included |
DHowett commented Feb 14, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
Well, it looks like that is a load-bearing In short, here's what happens during conversion from With |
kennykerr commented Feb 14, 2023
Yes, the |
DHowett commented Feb 14, 2023
My next couple avenues of exploration are...
I know that the last one would be a dealbreaker, but would you be amenable to it if it didn't impact the golden path MSVC scenario? |
kennykerr commented Feb 14, 2023
Presumably we don't want to inject spurious ref count bumps into Clang builds either but if it only impacts cases where a ref count is needed anyway, such as |
DHowett commented Feb 22, 2023
Okay, so, here's my contention. I've dug and dug and I can't find a way to eliminate the I'd like to propose two things:
See, at the end of the day... all I need is for my code to appear to be well-formed and compile. I'm not shipping a product based on this, but right now we would need to fix up ~151 sites across our codebase (and annotate them with a comment explaining why the normal C++/WinRT way doesn't work so they don't get reverted) and in every one of those cases introduce our own extra If you'd be amenable to a gated "make the code work, sub-optimally, if the user opts in" experience... I'd be happy to write it up. |
kennykerr commented Feb 22, 2023
Hey, thanks for looking into it. Obviously, compiling sub-optimally is better than not compiling at all. Can we just hide it behind an |
DHowett commented Feb 22, 2023
I'm totally cool with that. Thanks @kennykerr. I'll update this PR inplace. |
DHowett commented Feb 23, 2023
Alright, updated the PR title, body and contents. |
kennykerr left a comment
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.
Looks good - thanks!
alvinhochun commented Feb 23, 2023
Can you add some tests for this? |
kennykerr commented Feb 23, 2023
A little surprised this isn't already covered, unless a test is disabled for clang? |
(cherry picked from commit 675f8b7)
DHowett commented Feb 23, 2023
Good call. I added a test, unconditional for all compilers. 😄 I could not find one that had been disabled for clang that would have exercised this. |
| // uniform initialization relies on IStringable(IStringable&&), | ||
| // which requires non-const rvalue semantics. | ||
| com_ptr<Foo> foo = make_self<Foo>(); | ||
| IStringable stringable{foo.as<IStringable>() }; |
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.
| IStringable stringable{foo.as<IStringable>() }; | |
| IStringable stringable{*foo }; |
Isn't something like this required to actually invoke the implicit conversion operator? Otherwise you're just calling the explicit as method provided by com_ptr which in turn calls QI.
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.
facepalm
In Clang, the conversion from
producer_converttoconst producer_ref<I>does not allow for the move-initialization of
IviaI(I&&)(implicitor explicit) due to a language misspecification¹.
In brief², we cannot offer zero-cost initialization of projected types
from implementation types in all meaningful cases in projects compiled
with clang.
Until it improves (which is tracked in llvm/llvm-project#17056), this
conversion operator will allow for C++/WinRT code to compile with Clang.
Closes#1273
¹ http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2077 documents
the language standard bug that results in this.
² In non-brief, https://stackoverflow.com/a/70654432