-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Move PEPropertySymbol to use the same UncommonFields pattern that PEMethodSymbol uses #74132
Conversation
@@ -814,24 +884,28 @@ internal override bool MustCallMethodsDirectly | |||
|
|||
public override string GetDocumentationCommentXml(CultureInfo preferredCulture = null, bool expandIncludes = false, CancellationToken cancellationToken = default(CancellationToken)) | |||
{ | |||
return PEDocumentationCommentUtils.GetDocumentationComment(this, _containingType.ContainingPEModule, preferredCulture, cancellationToken, ref _lazyDocComment); | |||
return PEDocumentationCommentUtils.GetDocumentationComment(this, _containingType.ContainingPEModule, preferredCulture, cancellationToken, ref AccessUncommonFields()._lazyDocComment); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This unconditional access is the same pattern used by PEMethodSymbol
, so I kept it here.
…ethodSymbol uses This will be useful for OverloadResolutionPriority as well, as most properties won't have this attribute.
@@ -867,8 +938,31 @@ internal override ObsoleteAttributeData ObsoleteAttributeData | |||
{ | |||
get | |||
{ | |||
ObsoleteAttributeHelpers.InitializeObsoleteDataFromMetadata(ref _lazyObsoleteAttributeData, _handle, (PEModuleSymbol)(this.ContainingModule), ignoreByRefLikeMarker: false, ignoreRequiredMemberMarker: false); | |||
return _lazyObsoleteAttributeData; | |||
if (!_flags.IsObsoleteAttributePopulated) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementation basically copied wholesale from PEMethodSymbol
, with adjustments to GetObsoleteDataFromMetadata
as appropriate.
/// Atomically initializes the cache with the given value if it is currently fully default. | ||
/// This <i>will not</i> initialize <see cref="CachedUseSiteInfo{TAssemblySymbol}.Uninitialized"/>. | ||
/// </summary> | ||
public UseSiteInfo<TAssemblySymbol> InterlockedInitializeFromDefault(TAssemblySymbol? primaryDependency, UseSiteInfo<TAssemblySymbol> value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: the calling pattern in PEMethodSymbol
is pretty complicated, and explicitly calls out not using the Sentinel
for race safety. It seemed like it could be simplified to me, but I didn't want to touch it here, so I just renamed these methods to make it clear what they actually do: they both initialize a CachedUseSiteInfo
, one assuming that _info
is null
, and one assuming that _info
is Sentinel
. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the rename and this context. It is surprising indeed that we couldn't always use a sentinel for the uninitialized value.
@@ -146,7 +179,8 @@ public bool TryGetHasUnscopedRefAttribute(out bool hasUnscopedRefAttribute) | |||
|
|||
if (propEx != null || isBad) | |||
{ | |||
result._lazyCachedUseSiteInfo.Initialize(new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, result)); | |||
result.AccessUncommonFields()._lazyCachedUseSiteInfo.Initialize(new CSDiagnosticInfo(ErrorCode.ERR_BindToBogus, result)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
result.AccessUncommonFields()._lazyCachedUseSiteInfo.Initialize
PEMethodSymbol
has a dedicated InitializeUseSiteDiagnostic()
method that is used for all (?) cases where use-site diagnostics are calculated, and that also calls SetUseSiteDiagnosticPopulated()
. Is there a reason to set the fields directly here rather than using that approach?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm frankly not entirely certain why PEMethodSymbol has as complicated an initialization strategy as it does, but it does also initialize the diagnostic from more properties than we do in PEPropertySymbol. Here, we only initialize from:
- The creation steps, where the created symbol has not yet been exposed to anything else, so we don't have to worry about races.
GetUseSiteDiagnostic
, which does have to worry about races.
The pattern used here is the pattern used by all the rest of the UncommonFields
members, which correctly handles the occasional race of calculating that there is no use-site diagnostic/setting _flags.IsUseSiteDiagnostic
and creating _uncommonFields
.
@jcouv @dotnet/roslyn-compiler for a second review |
@@ -277,6 +312,33 @@ static bool anyUnexpectedRequiredModifiers(ParamInfo<TypeSymbol>[] propertyParam | |||
} | |||
} | |||
|
|||
private UncommonFields CreateUncommonFields() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this could be a local function in AccessUncommonFields
private UncommonFields CreateUncommonFields() | ||
{ | ||
var retVal = new UncommonFields(); | ||
if (!_flags.IsObsoleteAttributePopulated) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't understand this pattern of checking _flags
when initializing _uncommonFields
(here or in PEMethodSymbol
).
What is the scenario where _flags.IsObsoleteAttributePopulated
is set before _uncommonFields
is initialized by AccessUncommonFields
?
The pattern of initialization that we use (1. AccessUncommonFields()
, 2. initialize ._lazyObsoleteAttributeData
on it, then 3. mark the flag with SetObsoleteAttributePopulated
) seems to preclude that. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind, figured it out. We only conditionally do steps 1 and 2 (when there is non-trivial data to store). May be worth a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The scenario where there is no obsolete attribute. That will not call AccessUncommonData()
, since it doesn't need to put anything in it.
{ | ||
var result = uncommonFields._lazyCustomAttributes; | ||
if (result.IsDefault) | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider leaving a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM Thanks (iteration 3)
This will be useful for OverloadResolutionPriority as well, as most properties won't have this attribute.