Skip to content

Commit 4619ed7

Browse files
authored
Partial properties: duplicate membersByName before merging accessors (#74969)
1 parent c6a0795 commit 4619ed7

File tree

1 file changed

+18
-31
lines changed

1 file changed

+18
-31
lines changed

src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs

+18-31
Original file line numberDiff line numberDiff line change
@@ -3668,12 +3668,7 @@ void mergePartialMethods(ref Dictionary<ReadOnlyMemory<char>, ImmutableArray<Sym
36683668
}
36693669
else
36703670
{
3671-
if ((object)membersByName == _lazyEarlyAttributeDecodingMembersDictionary)
3672-
{
3673-
// Avoid mutating the cached dictionary and especially avoid doing this possibly on multiple threads in parallel.
3674-
membersByName = new Dictionary<ReadOnlyMemory<char>, ImmutableArray<Symbol>>(membersByName, ReadOnlyMemoryOfCharComparer.Instance);
3675-
}
3676-
3671+
DuplicateMembersByNameIfCached(ref membersByName);
36773672
membersByName[name] = FixPartialMember(membersByName[name], prevMethod, currentMethod);
36783673
}
36793674
}
@@ -3692,40 +3687,23 @@ void mergePartialProperties(ref Dictionary<ReadOnlyMemory<char>, ImmutableArray<
36923687
}
36933688
else
36943689
{
3695-
var (currentGet, prevGet) = ((SourcePropertyAccessorSymbol?)currentProperty.GetMethod, (SourcePropertyAccessorSymbol?)prevProperty.GetMethod);
3696-
if (currentGet != null || prevGet != null)
3697-
{
3698-
var accessorName = (currentGet ?? prevGet)!.Name.AsMemory();
3699-
mergeAccessors(ref membersByName, accessorName, currentGet, prevGet);
3700-
}
3701-
3702-
var (currentSet, prevSet) = ((SourcePropertyAccessorSymbol?)currentProperty.SetMethod, (SourcePropertyAccessorSymbol?)prevProperty.SetMethod);
3703-
if (currentSet != null || prevSet != null)
3704-
{
3705-
var accessorName = (currentSet ?? prevSet)!.Name.AsMemory();
3706-
mergeAccessors(ref membersByName, accessorName, currentSet, prevSet);
3707-
}
3708-
3709-
if ((object)membersByName == _lazyEarlyAttributeDecodingMembersDictionary)
3710-
{
3711-
// Avoid mutating the cached dictionary and especially avoid doing this possibly on multiple threads in parallel.
3712-
membersByName = new Dictionary<ReadOnlyMemory<char>, ImmutableArray<Symbol>>(membersByName, ReadOnlyMemoryOfCharComparer.Instance);
3713-
}
3714-
3690+
DuplicateMembersByNameIfCached(ref membersByName);
3691+
mergeAccessors(ref membersByName, (SourcePropertyAccessorSymbol?)currentProperty.GetMethod, (SourcePropertyAccessorSymbol?)prevProperty.GetMethod);
3692+
mergeAccessors(ref membersByName, (SourcePropertyAccessorSymbol?)currentProperty.SetMethod, (SourcePropertyAccessorSymbol?)prevProperty.SetMethod);
37153693
membersByName[name] = FixPartialMember(membersByName[name], prevProperty, currentProperty);
37163694
}
37173695

3718-
void mergeAccessors(ref Dictionary<ReadOnlyMemory<char>, ImmutableArray<Symbol>> membersByName, ReadOnlyMemory<char> name, SourcePropertyAccessorSymbol? currentAccessor, SourcePropertyAccessorSymbol? prevAccessor)
3696+
void mergeAccessors(ref Dictionary<ReadOnlyMemory<char>, ImmutableArray<Symbol>> membersByName, SourcePropertyAccessorSymbol? currentAccessor, SourcePropertyAccessorSymbol? prevAccessor)
37193697
{
3720-
Debug.Assert(currentAccessor != null || prevAccessor != null);
3721-
if (currentAccessor != null && prevAccessor != null)
3698+
if (currentAccessor is { } && prevAccessor is { })
37223699
{
3700+
var name = currentAccessor.Name.AsMemory();
37233701
var implementationAccessor = currentProperty.IsPartialDefinition ? prevAccessor : currentAccessor;
37243702
membersByName[name] = Remove(membersByName[name], implementationAccessor);
37253703
}
3726-
else
3704+
else if (currentAccessor is { } || prevAccessor is { })
37273705
{
3728-
var (foundAccessor, containingProperty, otherProperty) = prevAccessor != null ? (prevAccessor, prevProperty, currentProperty) : (currentAccessor!, currentProperty, prevProperty);
3706+
var (foundAccessor, containingProperty, otherProperty) = prevAccessor is { } ? (prevAccessor, prevProperty, currentProperty) : (currentAccessor!, currentProperty, prevProperty);
37293707
// When an accessor is present on definition but not on implementation, the accessor is said to be missing on the implementation.
37303708
// When an accessor is present on implementation but not on definition, the accessor is said to be unexpected on the implementation.
37313709
var (errorCode, propertyToBlame) = foundAccessor.IsPartialDefinition
@@ -3737,6 +3715,15 @@ void mergeAccessors(ref Dictionary<ReadOnlyMemory<char>, ImmutableArray<Symbol>>
37373715
}
37383716
}
37393717

3718+
private void DuplicateMembersByNameIfCached(ref Dictionary<ReadOnlyMemory<char>, ImmutableArray<Symbol>> membersByName)
3719+
{
3720+
if ((object)membersByName == _lazyEarlyAttributeDecodingMembersDictionary)
3721+
{
3722+
// Avoid mutating the cached dictionary and especially avoid doing this possibly on multiple threads in parallel.
3723+
membersByName = new Dictionary<ReadOnlyMemory<char>, ImmutableArray<Symbol>>(membersByName, ReadOnlyMemoryOfCharComparer.Instance);
3724+
}
3725+
}
3726+
37403727
/// <summary>Links together the definition and implementation parts of a partial method. Returns a member list which has the implementation part removed.</summary>
37413728
private static ImmutableArray<Symbol> FixPartialMember(ImmutableArray<Symbol> symbols, SourceOrdinaryMethodSymbol part1, SourceOrdinaryMethodSymbol part2)
37423729
{

0 commit comments

Comments
 (0)