Diagnose LibraryImport/[GeneratedComInterface] with restricted CCW/RCW options - #130097
Diagnose LibraryImport/[GeneratedComInterface] with restricted CCW/RCW options#130097AaronRobinsonMSFT with Copilot wants to merge 6 commits into
Conversation
…W options When a method marshals a `[GeneratedComInterface]`-attributed type in a direction its `ComInterfaceOptions` cannot support, the generated marshalling code silently uses `ComInterfaceMarshaller<T>.ConvertToUnmanaged` (needs CCW = ManagedObjectWrapper) or `ConvertToManaged` (needs RCW = ComObjectWrapper), and fails at runtime. Emit `SYSLIB1051` (Parameter/ReturnTypeNotSupportedWithDetails) with a message naming the missing wrapper option, so users see the problem at build time. - `NativeMarshallingAttributeInfo` grows two boolean init properties (`SupportsManagedToUnmanagedMarshalling`, `SupportsUnmanagedToManagedMarshalling`) defaulting to `true` — no behavior change for other marshallers. - `ComInterfaceMarshallingInfoProvider` reads `[GeneratedComInterface(Options = ...)]` off the interface symbol and sets the flags accordingly. Options are read as `int` to avoid a shared-project dependency on the `ComInterfaceOptions` enum type owned by ComInterfaceGenerator. - `AttributedMarshallingModelGeneratorResolver.CreateCustomNativeTypeMarshaller` validates the resolved `MarshalDirection` against the flags and returns `ResolvedGenerator.NotSupported` when a required direction isn't supported. - Tests exercise `in`/`out`/`ref`/return positions on `LibraryImport` and on `[GeneratedComInterface]` VtableIndex members. Closes #92222. Co-authored-by: AaronRobinsonMSFT <30635565+AaronRobinsonMSFT@users.noreply.github.com>
|
@copilot Please address the feedback. |
…efault Co-authored-by: AaronRobinsonMSFT <30635565+AaronRobinsonMSFT@users.noreply.github.com>
| Marshallers: marshallers.Value) | ||
| { | ||
| SupportsManagedToUnmanagedMarshalling = supportsManagedObjectWrapper, | ||
| SupportsUnmanagedToManagedMarshalling = supportsComObjectWrapper, | ||
| }; |
There was a problem hiding this comment.
@copilot Instead of introducing new SupportsManagedToUnmanagedMarshalling and SupportsUnmanagedToManagedMarshalling properties, can we instead generate a new CustomTypeMarshallers value that only contains the supported modes?
Ie, instead of setting SupportsManagedToUnmanagedMarshalling = true and SupportsUnmanagedToManagedMarshalling = false, we create a new CustomTypeMarshallers instance that only has marshallers for ManagedToUnmanagedIn and UnmanagedToManagedOut and the correct element marshallers.
There was a problem hiding this comment.
Done in f8878fb. ComInterfaceMarshallingInfoProvider now filters the CustomTypeMarshallers dictionary based on the interface's ComInterfaceOptions — CCW-only interfaces retain only {ManagedToUnmanagedIn, UnmanagedToManagedOut, ElementIn} and RCW-only interfaces retain only {ManagedToUnmanagedOut, UnmanagedToManagedIn, ElementOut} (the Default fallback is dropped when either wrapper is missing). The existing ValidateCustomNativeTypeMarshallingSupported in AttributedMarshallingModelGeneratorResolver then emits ManagedToUnmanagedMissingRequiredMarshaller / UnmanagedToManagedMissingRequiredMarshaller / BidirectionalMissingRequiredMarshaller for unsupported directions. The SupportsManagedToUnmanagedMarshalling/SupportsUnmanagedToManagedMarshalling properties and the two custom SR strings have been removed. Tests updated accordingly.
Note
AI/Copilot-generated reply.
…using new flag properties Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
| // Filter the available marshallers based on the ComInterfaceOptions declared on the interface. | ||
| // A [GeneratedComInterface] that only specifies ManagedObjectWrapper (CCW) supports data flow | ||
| // in the managed-to-unmanaged direction, and one that only specifies ComObjectWrapper (RCW) | ||
| // supports the unmanaged-to-managed direction. Restricting the CustomTypeMarshallers dictionary | ||
| // to only the modes that match the supported direction lets the shared resolver machinery | ||
| // (AttributedMarshallingModelGeneratorResolver) surface a build-time diagnostic when a caller | ||
| // marshals in an unsupported direction. | ||
| CustomTypeMarshallers filteredMarshallers = FilterMarshallersByComInterfaceOptions(marshallers.Value, interfaceType); |
There was a problem hiding this comment.
@copilot, please enhance the CustomTypeMarshallers type to allow usages to specify a specific error string for when marshalling is not supported in a particular direction for a particular scenario.
Then, update the following string IDs to allow a more specific reason to be appended at the end by adding {1} at the end of the strings: UnmanagedToManagedMissingRequiredMarshaller, BidirectionalMissingRequiredMarshaller, ManagedToUnmanagedMissingRequiredMarshaller.
Finally, update ValidateCustomNativeTypeMarshallingSupported to pass any custom reason (or an empty string if no custom reason exists) to the SR.Format calls.
There was a problem hiding this comment.
Done in the latest commit. Here's a summary of what was changed:
-
CustomTypeMarshallers— addedstring? UnsupportedReason = nullas a second primary constructor parameter; updatedEqualsandGetHashCodeto include it. -
Resource strings — updated
BidirectionalMissingRequiredMarshaller,ManagedToUnmanagedMissingRequiredMarshaller, andUnmanagedToManagedMissingRequiredMarshallerto end with{1}. Added two new stringsComObjectWrapperNotSpecifiedReasonandManagedObjectWrapperNotSpecifiedReason(each starting with a space for natural sentence concatenation). -
ValidateCustomNativeTypeMarshallingSupported— extractsmarshalInfo.Marshallers.UnsupportedReason ?? ""and passes it as{1}to all threeSR.Formatcalls. -
ComInterfaceMarshallingInfoProvider—FilterMarshallersByComInterfaceOptionsnow passes the COM-specific reason string when constructing the filteredCustomTypeMarshallers. -
Tests — all
SR.Formatcall sites updated to pass a second argument (""for generic cases, interface-specific reason for COM restriction tests).
Note
AI/Copilot-generated reply.
…ostic strings with {1}
Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
When a
[LibraryImport](or a virtual member of a[GeneratedComInterface]) marshals a[GeneratedComInterface]-attributed type in a direction itsComInterfaceOptionscannot support, the generated code compiles but silently usesComInterfaceMarshaller<T>.ConvertToUnmanaged(needs CCW =ManagedObjectWrapper) orConvertToManaged(needs RCW =ComObjectWrapper), and fails at runtime. This surfaces the problem at build time asSYSLIB1051.Given the repro from the issue:
the generator now reports on
ppFactory:Changes
NativeMarshallingAttributeInfo— added twoinitbool properties,SupportsManagedToUnmanagedMarshallingandSupportsUnmanagedToManagedMarshalling, both defaulting totrue(no behavior change for other marshallers). Inherited byIidParameterIndexNativeMarshallingInfoandNativeLinearCollectionMarshallingInfo.ComInterfaceMarshallingInfoProvider— reads[GeneratedComInterface(Options = …)]off the interface symbol and sets the two flags.Optionsis read as a rawint(0x1=ManagedObjectWrapper/CCW,0x2=ComObjectWrapper/RCW) to avoid a shared-project dependency on theComInterfaceOptionsenum type owned byComInterfaceGenerator.AttributedMarshallingModelGeneratorResolver.CreateCustomNativeTypeMarshaller— validates the resolvedMarshalDirectionagainst the flags and returnsResolvedGenerator.NotSupportedwith a targeted message when a required direction isn't supported. Fast-paths the common "both supported" case.Common/Resources/Strings.resx(auto-propagated to xlf files) naming the missing wrapper option.Diagnostic behavior
inparam onLibraryImport; return on a virtual COM method;ref)ManagedObjectWrapper(CCW)SYSLIB1051"…does not specify 'ComInterfaceOptions.ManagedObjectWrapper'…"outonLibraryImport; by-value /inparam on a virtual COM method;ref)ComObjectWrapper(RCW)SYSLIB1051"…does not specify 'ComInterfaceOptions.ComObjectWrapper'…"Tests
LibraryImportGenerator.UnitTests/CompileFails.cs— two new[Fact]tests coveringin/out/ref/return positions with the two restricted-option interfaces, plus aCodeSnippets.GeneratedComInterfaceWithOptionshelper.ComInterfaceGenerator.Unit.Tests/CompileFails.cs— two new[Fact]tests covering the corresponding cases for virtual COM methods (return-value and parameter positions).Note
This PR description is AI/Copilot-generated.