Skip to content
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

Cannot read MarshalAsAttribute in source generator #54754

Open
kant2002 opened this issue Jul 11, 2021 · 5 comments
Open

Cannot read MarshalAsAttribute in source generator #54754

kant2002 opened this issue Jul 11, 2021 · 5 comments
Labels
Area-Compilers Concept-API This issue involves adding, removing, clarification, or modification of an API.

Comments

@kant2002
Copy link

Version Used:
3.10.0

Steps to Reproduce:

  1. Create analyzer
  2. Find desired method which has [MarshalAs] attribute assigned to parameter. Save to IParameterSymbol parameterSymbol variable.
  3. Try read parameterSymbol.GetAttributes()
  4. This array return 0 elements, even if [MarshalAs] present.

Important that method should be in the separate assembly, If method is in same assembly in which source generator produce code, then MarshalAsAttribute appears in the list of attributes.

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Jul 11, 2021
@PathogenDavid
Copy link
Contributor

PathogenDavid commented Jul 12, 2021

TL;DR: This is happening because MarshalAs isn't an attribute anymore once the code has been compiled.


I don't have a great workaround for you, but I can at least explain why it's happening (and why you might not hold your breath on this feature getting added any time soon.)

MarshalAs (along with DllImport and a few others) are not actually emitted from the compiler as attributes but as metadata directly associated with their associated method/parameter. (You can see this for yourself by looking at the IL. I included an ObsoleteAttribute to show what a normal attribute looks like.)

Unfortunately since Roslyn doesn't have a need for marshaling info, it doesn't parse it when it comes from an external source.

The reason this issue doesn't come up with reflection is the runtime synthesizes fake attributes. In theory Roslyn could do this too, but I'm not sure how the devs would feel about it.


As for workarounds potential workarounds...

If all you need is the UnmanagedType of the parameter, that is stored and you should be able to get at it by reflecting PEParameterSymbol.MarshallingType.

If you need anything beyond that, I believe the rest is hiding in its encoded form in PEParameterSymbol.MarshallingDescriptor. I believe ParseNativeTypeInfo is the runtime code responsible for decoding this data so I'd use it as reference. (The format is also documented in ECMA-335 §II.23.4, but unless I'm missing something it doesn't include everything anyway. You might also find it useful to refer to MetaDataImport::GetMarshalAs, which is the connecting glue between GetMarshalAsCustomAttribute and ParseNativeTypeInfo.)

@kant2002
Copy link
Author

Thanks for detailed answer. I was aware that MarshalAs is pseudo-custom attributes. And rationale why it is not included make sense. What I thinking right now, is that time changed with source generators. One use-case for source generators is implementing efficient marshalling for .NET and for generation of COM RCW/CCW using ComWrappers. For that you may need declaration of structures and interfaces from other assemblies.

For now, I'm probably would be happy with proposed workarounds. But isn't this should be handled properly in Roslyn nowadays?

@jaredpar jaredpar added Concept-API This issue involves adding, removing, clarification, or modification of an API. Need More Info The issue needs more information to proceed. and removed untriaged Issues and PRs which have not yet been triaged by a lead labels Jul 12, 2021
@jaredpar
Copy link
Member

I think the best path forward here is to get an API proposal together for how we expose pseudo attributes in Roslyn.

@333fred as I believe this has come up before. Not sure if we have an existing proposal that we can add onto here.

@333fred
Copy link
Member

333fred commented Jul 12, 2021

This is similar to others, but we don't have anything specifically related to MarshalAs requested yet. We decode this information (https://sourceroslyn.io/#Microsoft.CodeAnalysis.CSharp/Symbols/FieldSymbol.cs,291), but it is not exposed in any public form today. We'd need an API proposal for how to expose marshalling information.

@kant2002
Copy link
Author

Initially I was thinking that somehow when calling GetAttributes() values from metadata would recreate AttributeData for appropriate IParameterSymbol/IFieldSymbol implementations. That's most intuitive way to work with these information. I do not see a value to have special API for consuming this data. If you insist that due performance implications, or maybe potential breakages it is not an option, I think API can be like that

public interface IParameterSymbol
{
+    MarshallingInformation GetMarshallingInformation();
}

public interface IFieldSymbol
{
+    MarshallingInformation GetMarshallingInformation();
}

+public struct MarshallingInformation
+{
+    public System.Runtime.InteropServices.UnmanagedType MarshalType { get; internal set; }
+    public System.Runtime.InteropServices.UnmanagedType ArrayElementType { get; internal set; }
+    public int ArraySizeConst { get; internal set; }
+    public int ArraySizeParameterIndex { get; internal set; }
+    public ISymbol CustomMarshallerType { get; internal set; }
+    public string CustomMarshallerCookie { get; internal set; }
+    public int ComInterfaceIIDParameterIndex { get; internal set; }
+}

Depending on the implementation of MarshallingInformation would be populated either from AttributeData or from CIL metadata.

@ghost ghost added the fabric-bot-test Testing the impact of changes to the fabric bot label Aug 10, 2021
@jaredpar jaredpar removed Need More Info The issue needs more information to proceed. fabric-bot-test Testing the impact of changes to the fabric bot labels Aug 10, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers Concept-API This issue involves adding, removing, clarification, or modification of an API.
Projects
None yet
Development

No branches or pull requests

4 participants