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

[Proposal] Support different attribute "retention" levels #4896

Closed
gafter opened this issue Aug 31, 2015 · 13 comments
Closed

[Proposal] Support different attribute "retention" levels #4896

gafter opened this issue Aug 31, 2015 · 13 comments
Labels
Area-Language Design Resolution-Answered The question has been answered

Comments

@gafter
Copy link
Member

gafter commented Aug 31, 2015

Attributes are currently available at runtime through reflection. However, we propose a meta-attribute (an attribute on attribute definitions) that the compiler and runtime would respect to control how long a use of the attribute is retained for.

  • source only - Such an attribute would be visible to the compiler and analyzers on the source, but not retained in the generated assembly (and therefore not visible to dependent compilations). An example would be SuppressMessageAttribute.
  • assembly only - Such an attribute would be visible to compilers and analyzers, including those that reference the code with the attribute, but the attribute is not retained or visible at runtime through reflection. An example would be DecimalConstantAttribute
  • runtime - This is the current behavior for all attributes - the attribute is available at compile-time and runtime.

The retention levels lower than runtime may be useful for some meta-programming techniques.

/cc @mattwar @joeduffy @jaredpar @srivatsn @stephentoub @MadsTorgersen @JohnHamby @cston

@gafter gafter changed the title Support different attribute "retention" levels [Proposal] Support different attribute "retention" levels Aug 31, 2015
@tmat
Copy link
Member

tmat commented Aug 31, 2015

I'm not sure I understand the purpose of "assembly only" attributes. DecimalConstantAttribute is needed at runtime for late bound code compilation and debugging.

@tmat
Copy link
Member

tmat commented Aug 31, 2015

What exactly do you mean by "runtime reflection" here? Is reading metadata of the assembly a runtime reflection?

@gafter
Copy link
Member Author

gafter commented Aug 31, 2015

@tmat If you're reading the metadata bits out of an assembly's file on disk, that is not reflection but file I/O. If you're using reflection APIs to access attributes of currently loaded program elements, that is reflection.

@ilmax
Copy link

ilmax commented Aug 31, 2015

Love the idea! Source only attributes + Roslyn can unleash some metaprogramming magic!

@tmat
Copy link
Member

tmat commented Aug 31, 2015

@gafter I don't think we should make Reflection produce different results than metadata reader.

@MrJul
Copy link
Contributor

MrJul commented Sep 1, 2015

Source-only attributes already exist today with the help of ConditionalAttribute. Can't this be reused? It's sufficient to never define the associated symbol. And if you ever do, it means that you really want those attributes to be available at runtime.

@HaloFour
Copy link

HaloFour commented Sep 1, 2015

@gafter

Would "assembly only" attributes be readable through reflection-only assemblies or would you need to be reading through the assembly manually? I assume that such attributes would require CLR changes to support so that the CLR doesn't bother trying to read them at runtime.

As for "source only" attributes, would that potentially include lifting some of the restrictions on what kind of parameters can be used since you wouldn't be limited to what the CLR can read/load at runtime? I could see some very interesting meta-programming scenarios enabled by supporting richer parameter types, like expression trees.

@MrJul

The ConditionalAttribute only applies to methods (and the attributes on those methods of course) and doesn't apply to anywhere else that you might want to apply an attribute. It also requires that the consumer specify whether or not the attribute is retained in the metadata. This feature would put that power into the hands of whoever is writing the attribute. It also provides feature parity with Java 5 which included retention in annotations since their inception.

@MrJul
Copy link
Contributor

MrJul commented Sep 1, 2015

@HaloFour No, it doesn't apply to methods only. ConditionalAttribute applied on an attribute completely removes the usages of this attribute today from the compilation if the matching conditional compilation symbol isn't defined, effectively making it "source-only". It's chosen by whoever is writing the attribute, but can be overridden by the consumer if needed (by defining the correct symbol).

For source-only, this proposal is adding a new attribute that works like ConditionalAttribute with a never-defined symbol.

@HaloFour
Copy link

HaloFour commented Sep 1, 2015

@MrJul Ah, must've been looking at an older definition of the attribute which used to only target methods.

Either way, this doesn't accomplish the same task. By marking an attribute (or any class) with ConditionalAttribute when the symbol isn't defined that class is stripped from the assembly entirely. It's not possible to write a helper assembly containing attributes and analyzers which can then be used by another project. A "source-only" attribute can exist in a separate assembly and used to decorate your project so that an analyzer can read those attributes but they would be stripped from the final assembly.

@MrJul
Copy link
Contributor

MrJul commented Sep 1, 2015

@HaloFour I think you're mistaken, the scenario you're talking about is specifically the one enabled by ConditionalAttribute. It doesn't remove the attribute class itself, only its usages.

The JetBrains.Annotations NuGet package is a perfect example: all attributes are used for source analysis by JetBrains' ReSharper, but all usages are stripped from your source code thanks to ConditionalAttribute (it's applied on every attribute), so it doesn't depend on JetBrains.Annotations at runtime.

Note: I'm not advocating against this proposal (who am I to criticize @gafter?). I'm simply pointing out the fact that this can already be done today, at least for source only attributes.

Regarding the assembly only attribute, I agree with @tmat here: reflection should also be able to see them. If the aim is to hide some "compiler only" attributes from reflection, we might as well hide all those compiler-generated classes for closures or iterators from reflection.

@HaloFour
Copy link

HaloFour commented Sep 1, 2015

@MrJul Clearly I've not used that feature before. So yeah, you can sorta emulate "source only" attributes today as long as the program doesn't define whatever symbol decorates the attribute. I wonder if those attributes are visible to analyzers in Roslyn today. It's not a part of this spec as written but I would like to see some of the limitations regarding what kind of types can be used for attribute parameters is lifted some since the CLR isn't expected to be instantiating the attribute instances at run-time.

@dsaf
Copy link

dsaf commented Sep 1, 2015

It can get confusing quite quickly unless IDE starts actually supporting custom attributes #711.

An example would be SuppressMessageAttribute.
An example would be DecimalConstantAttribute.

Does this mean the new feature will potentially be applied to existing .NET Framework attributes?

@gafter
Copy link
Member Author

gafter commented Sep 9, 2015

Given the existence of ConditionalAttribute pointed out by @MrJul, and other issues with assembly-only retention mentioned by @tmat, I believe this proposal is already satisfied.

@gafter gafter closed this as completed Sep 9, 2015
@gafter gafter added the Resolution-Answered The question has been answered label Sep 9, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Language Design Resolution-Answered The question has been answered
Projects
None yet
Development

No branches or pull requests

6 participants