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

Introduce pseudo-attributes page #42850

Open
jnm2 opened this issue Oct 4, 2024 · 2 comments
Open

Introduce pseudo-attributes page #42850

jnm2 opened this issue Oct 4, 2024 · 2 comments
Labels
doc-idea Indicates issues that are suggestions for new topics [org][type][category] dotnet-csharp/svc lang-reference/subsvc Pri2

Comments

@jnm2
Copy link
Contributor

jnm2 commented Oct 4, 2024

Type of issue

Missing information

Description

There is a class of attributes interpreted by the compiler which could have its own page. I've seen them described as pseudo-custom attributes, or, as https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.getcustomattributes describes them in the table it contains, simply pseudo-attributes. A pseudo-attribute is something that appears in C# syntax as an ordinary attribute, but upon compilation, it is not emitted into the IL custom attributes table as an ordinary attribute would be. Instead, IL flags or options are created. By making these IL options look like attributes, these options can be controlled using the C# language.

All of these may be used in C# source.

ComImportAttribute: maps to the IL import modifier
DefaultParameterValueAttribute: maps to the default value for the parameter
DllImportAttribute: maps to the IL pinvokeimpl modifier, with various options
FieldOffsetAttribute: maps to the offset for the IL .field
InAttribute: maps to the IL [in] modifier
MarshalAsAttribute: maps to the IL marshal modifier, with various options
MethodImplAttribute: maps to the IL flag modifier, with specific named flags such as aggressiveinlining or forwardref, as well as native, managed, or optil modifiers for the MethodCodeType field.
NonSerializedAttribute: maps to the IL notserialized modifier
OptionalAttribute: maps to the IL [opt] modifier
OutAttribute: maps to the IL [out] modifier
PreserveSigAttribute: maps to the IL preservesig modifier
SerializableAttribute: maps to the IL serializable modifier
SkipLocalsInitAttribute: maps to the absence of the IL init modifier for .locals (This might belong here rather than in https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/general#skiplocalsinit-attribute. It's also the odd one out, where a custom attribute is also added to the compilation, but this may be considered an oversight and possibly corrected in the future.)
SpecialNameAttribute maps the IL specialname modifier
StructLayoutAttribute: maps to the IL auto, sequential, or explicit modifiers, and some other options

Page URL

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/general

Content source URL

https://github.com/dotnet/docs/blob/main/docs/csharp/language-reference/attributes/general.md

Document Version Independent Id

6a60a627-c59c-74de-ce5b-6f52e15e7668

Article author

@BillWagner

Metadata

  • ID: d415a929-c112-ab86-cf2e-13bf2ef64e1a
  • Service: dotnet-csharp
  • Sub-service: lang-reference
@BillWagner BillWagner added the doc-idea Indicates issues that are suggestions for new topics [org][type][category] label Oct 7, 2024
@jnm2
Copy link
Contributor Author

jnm2 commented Oct 7, 2024

After considering more, it might be worth discussing where to draw the lines to determine whether SkipLocalsInitAttribute is a pseudo-attribute.

  • SkipLocalsInitAttribute can be set at a high level and set a whole bunch of IL flags on many objects at once; it doesn't appear in the source as always 1:1 per flag being set.
  • The existing pseudo-attributes are actually IL modifiers on the Type/MemberInfo/ParameterInfo, whereas SkipLocalsInit affects the .locals of a method body which can't be directly attributed in C#.
  • SkipLocalsInit doesn't represent an IL flag, but rather means "don't emit the flag."

On the other hand, the feature fully works without the presence of the custom attribute table entry, which is thus redundant. A similar attribute is ModuleInitializerAttribute, where the compiler could (should?) omit the custom attribute table entry since it it has no effect on the feature.

@jnm2
Copy link
Contributor Author

jnm2 commented Oct 7, 2024

ECMA-335 refers to these as pseudo custom attributes (without a hyphen, which makes me happy), and defines them as follows:

II.21.2 Attributes used by the CLI

There are two kinds of custom attributes, called genuine custom attributes, and pseudo custom attributes). Custom attributes and pseudo custom attributes are treated differently, at the time they are defined, as follows:

  • A custom attribute is stored directly into the metadata; the‘blob’ which holds its defining data is stored as-is. That ‘blob’ can be retrieved later.
  • A pseudo custom attribute is recognized because its name is one of a short list. Rather than store its ‘blob’ directly in metadata, that ‘blob’ is parsed, and the information it contains is used to set bits and/or fields within metadata tables. The ‘blob’ is then discarded; it cannot be retrieved later.

Then §II.12.2.1 lists them, saying it's not an exhaustive list, but that the names that are given are reserved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
doc-idea Indicates issues that are suggestions for new topics [org][type][category] dotnet-csharp/svc lang-reference/subsvc Pri2
Projects
None yet
Development

No branches or pull requests

2 participants