Fix windows-rdl complex attribute refs - #3942
Conversation
…ter WFM emit) Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
| interface IStatics {} | ||
| #[First(1)] | ||
| #[Second(2)] | ||
| #[Windows :: Foundation :: Metadata :: Activatable(3)] |
There was a problem hiding this comment.
Copilot The extra spaces around :: should be removed during formatting.
There was a problem hiding this comment.
Copilot The extra spaces around :: should be removed during formatting.
There was a problem hiding this comment.
Fixed in 8e4cfa8. push_attribute in the formatter now uses a peekable iterator to detect ::, trims the space before it, emits :: directly, and suppresses the space after it via an after_colon_colon flag — so Windows::Foundation::Metadata::Activatable(3) is now emitted without extra spaces.
| #[First(1)] | ||
| #[Second(2)] | ||
| #[Windows :: Foundation :: Metadata :: Activatable(3)] | ||
| #[Windows :: Foundation :: Metadata :: Static("Test.IStatics", 4)] |
There was a problem hiding this comment.
Copilot The Static("Test.IStatics", 4) should be written as Static(IStatics, 4) or Static(Test::IStatics, 4)` since it is a type rather than a string.
There was a problem hiding this comment.
Fixed in 8e4cfa8. The root cause was that Value::Utf8.ty() returns Type::String, so the MemberRef was written with a String signature parameter instead of System.Type. When reading back, the writer's type-path check never matched. The fix adds a types field to AttributeRef that captures the matched constructor's parameter types, which are then used directly in encode_named_attribute to build the MemberRef signature. Now Static(IStatics, 4) roundtrips cleanly.
There was a problem hiding this comment.
Copilot this seems a bit contrived - would it not be simpler to add a Name(TypeName) variant to the windows-metadata crate's Value enum so that we can be explicit about the fact that the "value" represents a type name rather than just a string?
There was a problem hiding this comment.
Done in 75dc740. Added Value::TypeName(TypeName) to the windows-metadata Value enum. ty() returns Type::Name(TypeName::named("System", "Type")) so the MemberRef signature is derived automatically. read_value now produces Value::TypeName for System.Type blobs, write_value (helpers.rs) serializes it back as a dotted UTF-8 string, and the RDL writer emits it as a type path via write_type. The AttributeRef.types workaround field is gone — everything flows through the type system cleanly.
| @@ -186,7 +186,15 @@ fn encode_attr_value( | |||
| lit: syn::Lit::Str(s), | |||
| .. | |||
| }) => Ok(metadata::Value::Utf8(s.value())), | |||
There was a problem hiding this comment.
Copilot Type parameters should not accept strings, just paths.
There was a problem hiding this comment.
Fixed in 2dac884. The string literal arm for System.Type has been removed — only path expressions are accepted now, with the error message updated to "expected type path".
…ture Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
… only Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
…e attribute values Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
|
Copilot fix multiple build breaks pls |
Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
Fixed in 259ce16. Two failures:
|
| Value::Utf8(s) => { | ||
| if let Some(dot) = s.rfind('.') { | ||
| (&s[..dot], &s[dot + 1..]) | ||
| } else { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Copilot this should always be a TypeName so perhaps don't bother with checking for a Utf8
There was a problem hiding this comment.
Done in 6643f3f. Both loops now only match Value::TypeName, dropping the Value::Utf8 fallback entirely.
…Composable type params Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
Fixes several bugs that prevented
Windows.Foundation.Metadataattribute refs from working correctly on non-class types and with path-typed constructor arguments.Reader (
attribute_ref.rs):encode_attr_valuenow only accepts Rust path expressions (IStatics,Test::IStatics, etc.) forSystem.Typeconstructor params — string literals are rejected. Paths are resolved viaencode_pathand stored as the newValue::TypeNamevariant. TheAttributeRef.typesworkaround field has been removed; the MemberRef signature is now derived directly fromValue::ty(), which returnsType::Name(TypeName::named("System", "Type"))forValue::TypeName.windows-metadataValueenum: Added aTypeName(TypeName)variant to explicitly represent type-name values rather than encoding them as ambiguous UTF-8 strings.read_valuenow producesValue::TypeNamewhen readingSystem.Typeblobs (splitting the stored dotted string into namespace + name). The binary writer serialisesValue::TypeNameback to the same dotted UTF-8 wire format, so existing.winmdfiles are unaffected.windows-bindgen(class.rs):StaticAttribute,ActivatableAttribute, andComposableAttributehandling now matchesValue::TypeNameexclusively when looking up interface type names — the oldValue::Utf8dotted-string path is no longer needed sinceSystem.Typeattribute params are always represented asValue::TypeName.Writer (
writer/mod.rs):write_custom_attributesblanket-skipped allWindows.Foundation.Metadataattributes, silently dropping them on roundtrip for structs and other non-class types. Now onlySystem.*(CLR-internal) attributes are unconditionally skipped;Windows.Foundation.Metadataattributes respect the caller's explicitskiplist (class behaviour unchanged). External-namespace attributes are emitted with a fully-qualified path (e.g.#[Windows::Foundation::Metadata::Activatable(3)]).Value::TypeNameargs are emitted as type paths viawrite_type, making roundtrips lossless.write_valuenow takes anamespaceparameter used to produce relative type paths.Formatter (
formatter/mod.rs):push_attributenow uses a peekable iterator to detect::, trims the space before it, and suppresses the space after via anafter_colon_colonflag, so qualified attribute paths are formatted correctly (e.g.Windows::Foundation::Metadata::Activatable(3)with no extra spaces).Path casing (
attribute-from-reference.rs,nested.rs,path.rs): Tests referencedwindows.winmd(lowercase) while the actual file isWindows.winmd, silently failing on case-sensitive Linux filesystems.Example that now works end-to-end:
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.