Add Generic<'a, T> type alias for generic parameters in _Impl traits#4327
Add Generic<'a, T> type alias for generic parameters in _Impl traits#4327
Generic<'a, T> type alias for generic parameters in _Impl traits#4327Conversation
…mplParam Agent-Logs-Url: https://github.com/microsoft/windows-rs/sessions/2a163a9d-e89f-4c9a-a6af-ee3d0a55b6eb Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
Agent-Logs-Url: https://github.com/microsoft/windows-rs/sessions/2a163a9d-e89f-4c9a-a6af-ee3d0a55b6eb Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
| /// since these are cheap to copy and `Ref` adds no value. For `CloneType` (HSTRING, etc.) | ||
| /// and `InterfaceType` (COM interfaces) this is `Ref<'a, T>` — a borrowed wrapper that | ||
| /// matches the ABI representation. | ||
| type Param<'a>: 'a |
There was a problem hiding this comment.
@copilot might be clearer if this were just called Generic as well otherwise it can be confused with the Param trait.
There was a problem hiding this comment.
Done in 2a23e69. Renamed the GAT from type Param<'a> to type Generic<'a> on the Type trait so it matches the public alias and can't be confused with the Param trait. The pub type Generic<'a, T> alias now resolves to <T as Type<T>>::Generic<'a>.
…rait Agent-Logs-Url: https://github.com/microsoft/windows-rs/sessions/f23af9c0-6dc8-4fe9-b018-b4a6e6b866e5 Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
| /// # Safety | ||
| /// | ||
| /// The ABI value must be valid for the lifetime `'a`. | ||
| unsafe fn abi_to_param(abi: &Self::Abi) -> Self::Generic<'_>; |
There was a problem hiding this comment.
Rename abi_to_param to abi_to_generic.
There was a problem hiding this comment.
Done in f0adad2. Renamed abi_to_param → abi_to_generic throughout.
| /// This is used in generic collection implementations (e.g. `IMap_Impl`, `IVector_Impl`) | ||
| /// to obtain a `&K::Default` from a `Generic<'_, K>` in order to perform map/vector | ||
| /// operations that operate on the default type. | ||
| fn param_as_default<'a, 'b>(param: &'a Self::Generic<'b>) -> &'a Self::Default; |
There was a problem hiding this comment.
Rename param_as_default to generic_as_default.
There was a problem hiding this comment.
Done in f0adad2. Renamed param_as_default → generic_as_default throughout.
|
@copilot deal with review comments |
…_as_default Agent-Logs-Url: https://github.com/microsoft/windows-rs/sessions/9af89a3c-ff53-4be5-9dd8-d76539f480c3 Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
| unsafe { core::mem::transmute_copy(abi) } | ||
| } | ||
|
|
||
| fn generic_as_default<'a, 'b>(param: &'a Ref<'b, Self>) -> &'a Option<Self> { |
There was a problem hiding this comment.
All the generic_as_default implementations appear to be passthroughs - do we really need it?
There was a problem hiding this comment.
Removed from the Type trait in f036bc1. The reason the implementations are all passthroughs is that Generic<'_, T> and T::Default always share the same memory layout (identity for CopyType; Ref<T> is #[repr(transparent)] over T::Abi which is layout-compatible with T::Default for Ref types). The logic is still needed in generic collection code to uniformly convert Generic<'_, K> → &K::Default, so it's now a standalone #[doc(hidden)] free function generic_as_default::<T>(&key) exported from windows_core rather than a trait method.
| /// # Safety | ||
| /// | ||
| /// The ABI value must be valid for the lifetime `'a`. | ||
| unsafe fn abi_to_generic(abi: &Self::Abi) -> Self::Generic<'_>; |
There was a problem hiding this comment.
The abi_to_generic doesn't appear to provide any more value over transmute_copy - can we do without?
There was a problem hiding this comment.
Removed in f036bc1. All call sites now use core::mem::transmute_copy directly, and the method is gone from the trait.
|
@copilot deal with review comments |
…neric_as_default to free function; use transmute_copy for abi conversion Agent-Logs-Url: https://github.com/microsoft/windows-rs/sessions/274af45a-45d3-4cc5-91eb-4470139b56d6 Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
Done in f036bc1. Both |
What's this all about?
This PR implements an improved version of the generics binding improvement from #4155, with the cleaner name
Genericinstead ofImplParam.Problem
When implementing generic WinRT interfaces like
IMap_Impl<K, V>orIVector_Impl<T>, users had to writeRef<K>for all generic type parameters — even primitives whereRefadds no semantic value:The same issue affected event handler closures:
TypedEventHandler::new(move |_, args: Ref<i32>| { assert_eq!(*args, 2); }).Solution
Added a
Generic<'a>generic associated type (GAT) to theTypetrait inwindows-core:CopyType(primitives, GUID, enums, etc.):Generic<'a> = T— the type itself, noRefwrapperCloneType(HSTRING, etc.):Generic<'a> = Ref<'a, T>— same as beforeInterfaceType(COM interfaces):Generic<'a> = Ref<'a, T>— same as beforeThe GAT is named
Generic<'a>to avoid confusion with the existingParamtrait.A public type alias is exported:
A
#[doc(hidden)]free functiongeneric_as_defaultis exported fromwindows_coreto convert aGeneric<'_, T>reference to a&T::Defaultreference. This is needed by generic collection implementations (IMap_Impl,IVector_Impl, etc.) becauseGeneric<'_, T>is eitherTitself (forCopyType) orRef<'_, T>(for other types), and there is no built-in Rust construct that dereferences uniformly across both forms. The function is a zero-cost reinterpretation sinceGeneric<'_, T>andT::Defaultalways share the same memory layout. Generated vtable code usescore::mem::transmute_copydirectly instead of a trait helper method.Result
Users can now write generic type parameters directly for primitives:
For non-primitive types like
HSTRINGand COM interfaces,Generic<'_, T>resolves toRef<'_, T>as before.Changes
crates/libs/core/src/type.rs— AddedGeneric<'a>GAT,pub type Generic<'a, T>, and a standalonegeneric_as_defaultfree function; removedabi_to_genericandgeneric_as_defaulttrait methods fromTypecrates/libs/bindgen/src/types/method.rs— Updated code generator to emitGeneric<'_, T>in_Implsignatures and usecore::mem::transmute_copyin vtable upcall codecollections/bindings.rs,future/bindings.rs,Foundation/mod.rs,class_dep.rs,interface_iterable.rs,delegate_generic.rs,reference_custom/bindings.rs,reference_no_deps/bindings.rsmap.rs,vector.rs, etc.) to useGeneric<'_, T>and thegeneric_as_defaultfree function