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

Move PEPropertySymbol to use the same UncommonFields pattern that PEMethodSymbol uses #74132

Merged
merged 3 commits into from
Jun 27, 2024

Conversation

333fred
Copy link
Member

@333fred 333fred commented Jun 24, 2024

This will be useful for OverloadResolutionPriority as well, as most properties won't have this attribute.

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Jun 24, 2024
@@ -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);
Copy link
Member Author

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)
Copy link
Member Author

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.

@333fred
Copy link
Member Author

333fred commented Jun 25, 2024

@dotnet/roslyn-compiler @jcouv @cston for review. This will contribute to overload resolution priority, but is an effectively unrelated refactoring so I separated it out.

/// 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)
Copy link
Member Author

@333fred 333fred Jun 26, 2024

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

Copy link
Member

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.

@333fred
Copy link
Member Author

333fred commented Jun 26, 2024

@jcouv @cston @dotnet/roslyn-compiler for review.

@@ -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));
Copy link
Member

@cston cston Jun 26, 2024

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?

Copy link
Member Author

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:

  1. The creation steps, where the created symbol has not yet been exposed to anything else, so we don't have to worry about races.
  2. 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.

@333fred
Copy link
Member Author

333fred commented Jun 26, 2024

@jcouv @dotnet/roslyn-compiler for a second review

@@ -277,6 +312,33 @@ static bool anyUnexpectedRequiredModifiers(ParamInfo<TypeSymbol>[] propertyParam
}
}

private UncommonFields CreateUncommonFields()
Copy link
Member

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)
Copy link
Member

@jcouv jcouv Jun 27, 2024

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

Copy link
Member

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

Copy link
Member Author

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)
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider leaving a comment

@jcouv jcouv self-assigned this Jun 27, 2024
Copy link
Member

@jcouv jcouv left a 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)

@333fred 333fred merged commit 5475105 into dotnet:main Jun 27, 2024
24 checks passed
@333fred 333fred deleted the pe-uncomon branch June 27, 2024 20:33
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Jun 27, 2024
333fred added a commit to 333fred/roslyn that referenced this pull request Jun 27, 2024
333fred added a commit that referenced this pull request Jul 18, 2024
* Address PR feedback on #74132

* Spelling
@RikkiGibson RikkiGibson modified the milestones: Next, 17.12 P1 Jul 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants