-
Notifications
You must be signed in to change notification settings - Fork 534
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
Simplify and refactor the implement
macro
#3507
Simplify and refactor the implement
macro
#3507
Conversation
At an initial reading this PR seems to be doing too much - it would be easier to reason about if this were broken up a bit more into more discrete changes that focused on individual things. Philosophical changes to |
This sounds like a good meaty PR on its own. I like the sound of this.
Macros seem like they have so much potential in Rust but lack so much in terms of debuggability and testability and contextual ignorance. It would be nice, for consistency to move this into the
There might be an issue here if an implementation needs to implement both
Neat, we did this in C++/WinRT and it made big difference.
We may not be super consistent here but it helps to preserve the original API names to avoid confusion and make it easier to search the code base for related code.
👍
I'm not sure I agree with this - the
👍 |
Fortunately, that won't cause a collision. Both interface chains will have a different index, and the generated ident contains the index as well as the name suffix. So this case would generate something like Speaking of tuples, we've been relying on a behavior that is not guaranteed. The compiler is allowed to reorder the fields within a tuple; tuples are How about this:
|
Even when the field is part of a |
I believe so, because the layout of types is determined by their definition, but not their context. In this case, we're getting lucky because these definitions are always "a sequence of non-nullable pointer-sized fields". But if we had a tuple like We're just getting lucky right now. ;) |
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 my comments are on existing code which has been moved...
47095b2
to
61e9b32
Compare
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.
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
Comments suppressed due to low confidence (1)
crates/tests/libs/implement_core/src/com_object.rs:437
- The removal of raw pointer assertions in the iunknown_identity test has reduced explicit verification of the canonical IUnknown pointer behavior. Consider reintroducing these assertions or alternative checks to ensure interface pointer integrity.
let app = MyApp::new(0);
c002135
to
cc8115c
Compare
//! These tests are just a way to quickly run the `#[implement]` macro and see its output. | ||
//! They don't check the output in any way. | ||
//! | ||
//! This exists because of some difficulties of running `cargo expand` against the `#[implement]` |
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.
Maybe just a comment about how to run a test and see the output - for example I run this:
cargo test -p windows-implement --tests simple_type
But cargo test does not automatically display the stdout
for println
.
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.
e.g.
cargo test -p windows-implement --tests simple_type -- --nocapture
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.
Much more manageable thanks!
implement
macro
This improves COM object support.
The main focus is on improving the internal structure of the
implement
proc macro. I've broken theimplement
function into a bunch of small, focused functions. Theimplement
proc macro first parses its input, creates anImplementInputs
struct which contains all of the information need to generate output. Then, it callsgen_all
to generate the output, which callsgen_*
to generate each specific output item. This makes the code much easier to understand, debug, and edit.The codegen functions (the
gen_*
functions) now generate strongly-typedsyn
values, such assyn::Item
. Eachgen_*
generates the tokens and then parses them into the strongly-typed value. This allows us to catch syntax errors far more quickly, and theparse_quote
macro will panic at the site of any syntax error. This makes development on theincrement
macro a lot more productive.Speaking of debugging, I've added some unit tests within the
implement
crate. They don't actually test anything, but that's not the point. The point of these unit tests is that you can very easily see the output ofimplement
, without needingcargo-expand
(which has its own problems). You can also step through the code in a debugger.This PR contains some modest improvements to the code that is generated by
implements
:interface2_ifoo
. This makes it a lot easier to debug COM objects at runtime.IUnknownImpl
trait is now anunsafe
trait. There's no way to implement this trait without writing unsafe code.IUnknown::Release
implementation now puts the "slow" path (refcount reaches zero) into a separate function. This keeps the fast path (refcount is not zero) as small and fast as possible. For objects with significant destructors, this helps.GetTrustLevel
and such to use snake casing, where applicable.from_inner_ref
onIUnknown
. There is no need for this any more, since all COM interface method implementations are onFoo_Impl
types now.WeakRefCount
that can change the refcount to haveunsafe
signatures. Any change to a refcount could affect memory lifetime, so these operations need to beunsafe
. This allows us to expose&WeakRefCount
forComObject<T>
, which simplifies other things. The motivation here is to make it difficult to accidentally leave a memory safety hole (in safe code).quote_spanned
orparse_quote_spanned
macros, with a span that points to the interface name. This improves the error messages when the user forgets to provide an implementation of a COM interface, because the error message will point to the interface name.