Proposal: Custom attributes on local variables #8460
Unanswered
IS4Code
asked this question in
Language Ideas
Replies: 1 comment 9 replies
-
See: #1452 |
Beta Was this translation helpful? Give feedback.
9 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Note: This is similar to #1452 and #2478 in allowing attributes in additional contexts, but this is specifically about locals, and these attributes are not meant to be (just) source-only.
Motivation
Some code analyzers may require a way to be able to annotate declarations of local variables to specify further contracts, guards, or other requirements that apply when using them, for example:
Moreover, being able to use custom attributes in this location could also be helpful for the compiler itself, potential IL rewriting, optimizations during JIT/AOT, and similar (for example a more fine-grained
[SkipLocalsInit]
). Unless prevented via other mechanisms, these attributes need to be preserved in the generated CIL.Design
Syntax
The syntax is modified to allow attributes in a
local_variable_declaration
:Additionally, "
var
" becomes a standardattribute_target
, to be used only in alocal_variable_declaration
.Usage
There are two options as to what attributes are made to be permitted on a local variable:
Add
AttributeTargets.Variable
(or recognize(AttributeTargets)32768
) to specifically designate attributes meant to be used only on local variables. This has potential issues however with compilations targeting older versions of the runtime, and the meaning ofAttributeTargets.All
.Recognize some existing attributes as implicitly applying to local variables as well. Specifically, I suggest to allow any attribute matching all of these conditions:
AttributeTargets.Parameter
‒ a parameter is a variable, hence what makes sense on local variables should usually make sense on parameters too.AttributeTargets.Field
,AttributeTargets.Property
, orAttributeTargets.ReturnValue
. This is to show that it applies to other storage locations as well.I have checked all types in the runtime that match this condition (but do not specify too many other targets), arriving at this list. Click below to show.
Both options are possible to adopt, which would increase compatibility with existing attributes, and allow the creation of new ones specifically restricted to local variables.
Interpretation
Each individually specified attribute applies to all variables declared in the
local_variable_declaration
, as long as its target isvar
or unspecified. Moreover:field
, and the attribute supportsAttributeTargets.Field
, the attribute applies to all compiler-generated fields corresponding to the variable, for example in a closure object or iterator/asynchronous state.param
, and the attribute supportsAttributeTargets.Parameter
, the attribute applies to all compiler-generated parameters corresponding to the variable. I am not sure if this currently happens anywhere, but it might.This serves to ensure that the attribute survives even if the local variable is not necessarily encoded as a variable in CIL. If that is not the case (a non-existent target is specified, or the attribute's
AttributeTargets
flags are not compatible with the implied target), an error is produced.In a context where the declaration of a local variable might be omitted entirely by the compiler (as an optimization) when generating CIL (or it may be merged with an unrelated local variable of the same type), this optimization should be skipped if there was an attribute on it. This means the identity of a variable should be preserved when it has custom attributes (as long as they should be encoded alongside it).
Encoding
As seen above, an attribute on a local variable might eventually turn into one on a field or a parameter ‒ if that is the case, it is encoded the usual way.
An attribute on an actual (CIL) local variable is currently possible to realize in one of two ways:
LocalVariableInfo.GetModifiedLocalType()
.localIndex
corresponds toLocalVariableIndex.LocalIndex
. Unlike in "real" attributes, the constructor must be specified separately, using its declaringType
and the signature, as aType
array of its parameters (including their optional/required modifiers, if any). This should uniquely specify the constructor of the attribute.blob
is the same as in metadata, encoding the arguments and assigned properties.Examples
The same happens in case of multiple declared variables:
Conversely,
Beta Was this translation helpful? Give feedback.
All reactions