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

Refactoring of synthesized types tracking across EnC generations #69782

Merged
merged 5 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,36 +26,30 @@ internal sealed class CSharpSymbolMatcher : SymbolMatcher
private readonly MatchSymbols _symbols;

public CSharpSymbolMatcher(
IReadOnlyDictionary<AnonymousTypeKey, AnonymousTypeValue> anonymousTypeMap,
IReadOnlyDictionary<SynthesizedDelegateKey, SynthesizedDelegateValue> anonymousDelegates,
IReadOnlyDictionary<string, AnonymousTypeValue> anonymousDelegatesWithIndexedNames,
SourceAssemblySymbol sourceAssembly,
EmitContext sourceContext,
SourceAssemblySymbol otherAssembly,
EmitContext otherContext,
SynthesizedTypeMaps synthesizedTypes,
ImmutableDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>>? otherSynthesizedMembers,
ImmutableDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>>? otherDeletedMembers)
{
_defs = new MatchDefsToSource(sourceContext, otherContext);
_symbols = new MatchSymbols(anonymousTypeMap, anonymousDelegates, anonymousDelegatesWithIndexedNames, sourceAssembly, otherAssembly, otherSynthesizedMembers, otherDeletedMembers, new DeepTranslator(otherAssembly.GetSpecialType(SpecialType.System_Object)));
_symbols = new MatchSymbols(sourceAssembly, otherAssembly, synthesizedTypes, otherSynthesizedMembers, otherDeletedMembers, new DeepTranslator(otherAssembly.GetSpecialType(SpecialType.System_Object)));
}

public CSharpSymbolMatcher(
IReadOnlyDictionary<AnonymousTypeKey, AnonymousTypeValue> anonymousTypeMap,
IReadOnlyDictionary<SynthesizedDelegateKey, SynthesizedDelegateValue> anonymousDelegates,
IReadOnlyDictionary<string, AnonymousTypeValue> anonymousDelegatesWithIndexedNames,
SynthesizedTypeMaps synthesizedTypes,
SourceAssemblySymbol sourceAssembly,
EmitContext sourceContext,
PEAssemblySymbol otherAssembly)
{
_defs = new MatchDefsToMetadata(sourceContext, otherAssembly);

_symbols = new MatchSymbols(
anonymousTypeMap,
anonymousDelegates,
anonymousDelegatesWithIndexedNames,
sourceAssembly,
otherAssembly,
synthesizedTypes,
otherSynthesizedMembers: null,
deepTranslator: null,
otherDeletedMembers: null);
Expand Down Expand Up @@ -281,9 +275,7 @@ public MatchDefsToSource(

private sealed class MatchSymbols : CSharpSymbolVisitor<Symbol?>
{
private readonly IReadOnlyDictionary<AnonymousTypeKey, AnonymousTypeValue> _anonymousTypeMap;
private readonly IReadOnlyDictionary<SynthesizedDelegateKey, SynthesizedDelegateValue> _anonymousDelegates;
private readonly IReadOnlyDictionary<string, AnonymousTypeValue> _anonymousDelegatesWithIndexedNames;
private readonly SynthesizedTypeMaps _synthesizedTypes;
private readonly SourceAssemblySymbol _sourceAssembly;

// metadata or source assembly:
Expand All @@ -309,18 +301,14 @@ private sealed class MatchSymbols : CSharpSymbolVisitor<Symbol?>
private readonly ConcurrentDictionary<ISymbolInternal, IReadOnlyDictionary<string, ImmutableArray<ISymbolInternal>>> _otherMembers = new(ReferenceEqualityComparer.Instance);

public MatchSymbols(
IReadOnlyDictionary<AnonymousTypeKey, AnonymousTypeValue> anonymousTypeMap,
IReadOnlyDictionary<SynthesizedDelegateKey, SynthesizedDelegateValue> anonymousDelegates,
IReadOnlyDictionary<string, AnonymousTypeValue> anonymousDelegatesWithIndexedNames,
SourceAssemblySymbol sourceAssembly,
AssemblySymbol otherAssembly,
SynthesizedTypeMaps synthesizedTypes,
ImmutableDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>>? otherSynthesizedMembers,
ImmutableDictionary<ISymbolInternal, ImmutableArray<ISymbolInternal>>? otherDeletedMembers,
DeepTranslator? deepTranslator)
{
_anonymousTypeMap = anonymousTypeMap;
_anonymousDelegates = anonymousDelegates;
_anonymousDelegatesWithIndexedNames = anonymousDelegatesWithIndexedNames;
_synthesizedTypes = synthesizedTypes;
_sourceAssembly = sourceAssembly;
_otherAssembly = otherAssembly;
_otherSynthesizedMembers = otherSynthesizedMembers;
Expand Down Expand Up @@ -680,15 +668,15 @@ internal bool TryFindAnonymousType(AnonymousTypeManager.AnonymousTypeTemplateSym
{
Debug.Assert((object)type.ContainingSymbol == (object)_sourceAssembly.GlobalNamespace);

return _anonymousTypeMap.TryGetValue(type.GetAnonymousTypeKey(), out otherType);
return _synthesizedTypes.AnonymousTypes.TryGetValue(type.GetAnonymousTypeKey(), out otherType);
}

internal bool TryFindAnonymousDelegate(AnonymousTypeManager.AnonymousDelegateTemplateSymbol delegateSymbol, out SynthesizedDelegateValue otherDelegateSymbol)
{
Debug.Assert((object)delegateSymbol.ContainingSymbol == (object)_sourceAssembly.GlobalNamespace);

var key = new SynthesizedDelegateKey(delegateSymbol.MetadataName);
return _anonymousDelegates.TryGetValue(key, out otherDelegateSymbol);
return _synthesizedTypes.AnonymousDelegates.TryGetValue(key, out otherDelegateSymbol);
}

internal bool TryFindAnonymousDelegateWithIndexedName(AnonymousTypeManager.AnonymousDelegateTemplateSymbol type, out AnonymousTypeValue otherType)
Expand All @@ -701,7 +689,7 @@ internal bool TryFindAnonymousDelegateWithIndexedName(AnonymousTypeManager.Anony
// expression may have been changed explicitly, or another lambda expression may have been inserted
// ahead of this one in source order. Therefore, we need to verify the signatures of the delegate types
// are equivalent - by comparing the Invoke() method signatures.
if (_anonymousDelegatesWithIndexedNames.TryGetValue(type.Name, out otherType) &&
if (_synthesizedTypes.AnonymousDelegatesWithIndexedNames.TryGetValue(type.Name, out otherType) &&
otherType.Type.GetInternalSymbol() is NamedTypeSymbol otherDelegateType &&
isCorrespondingAnonymousDelegate(type, otherDelegateType))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Reflection.Metadata;
using System.Threading;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
Expand Down Expand Up @@ -82,7 +83,7 @@ internal static EmitDifferenceResult EmitDifference(
filterOpt: s => changes.RequiresCompilation(s.GetISymbol()),
cancellationToken: cancellationToken))
{
if (!ContainsPreviousAnonymousDelegates(definitionMap, baseline.AnonymousDelegatesWithIndexedNames, moduleBeingBuilt.GetAnonymousDelegatesWithIndexedNames()))
if (!ContainsPreviousAnonymousDelegates(definitionMap, baseline.SynthesizedTypes.AnonymousDelegatesWithIndexedNames, compilation.AnonymousTypeManager.GetCreatedAnonymousDelegateTypesWithIndexedNames()))
{
diagnostics.Add(ErrorCode.ERR_EncUpdateFailedDelegateTypeChanged, Location.None);
}
Expand Down Expand Up @@ -120,32 +121,31 @@ internal static EmitDifferenceResult EmitDifference(

private static bool ContainsPreviousAnonymousDelegates(
CSharpDefinitionMap definitionMap,
IReadOnlyDictionary<string, AnonymousTypeValue> previousDictionary,
IReadOnlyDictionary<string, AnonymousTypeValue> currentDictionary)
ImmutableDictionary<string, AnonymousTypeValue> previousDictionary,
IEnumerable<Cci.ITypeDefinition> currentTypes)
{
if (previousDictionary.Count == 0)
{
return true;
}

if (previousDictionary.Count > currentDictionary.Count)
var currentTypesByName = currentTypes.ToImmutableDictionary(getName);
if (previousDictionary.Count > currentTypesByName.Count)
{
return false;
}

Dictionary<string, Cci.ITypeDefinition> currentTypes = getTypes(currentDictionary).ToDictionary(t => getName(t));
IEnumerable<Cci.ITypeDefinition> previousTypes = getTypes(previousDictionary);
foreach (var previousType in previousTypes)
foreach (var previousType in previousDictionary)
{
if (!currentTypes.TryGetValue(getName(previousType), out var currentType) ||
if (!currentTypesByName.TryGetValue(getName(previousType.Value.Type), out var currentType) ||
definitionMap.MapDefinition(currentType) is null)
{
return false;
}
}

return true;

static IEnumerable<Cci.ITypeDefinition> getTypes(IReadOnlyDictionary<string, AnonymousTypeValue> dictionary) => dictionary.Values.Select(v => v.Type);
static string getName(Cci.ITypeDefinition type) => ((Cci.INamedEntity)type).Name!;
}

Expand Down Expand Up @@ -175,25 +175,21 @@ private static EmitBaseline MapToCompilation(
RoslynDebug.AssertNotNull(previousGeneration.PEModuleBuilder);
RoslynDebug.AssertNotNull(moduleBeingBuilt.EncSymbolChanges);

var synthesizedTypes = moduleBeingBuilt.GetSynthesizedTypes();
var currentSynthesizedMembers = moduleBeingBuilt.GetAllSynthesizedMembers();
var currentDeletedMembers = moduleBeingBuilt.EncSymbolChanges.GetAllDeletedMembers();

// Mapping from previous compilation to the current.
var anonymousTypeMap = moduleBeingBuilt.GetAnonymousTypeMap();
var anonymousDelegates = moduleBeingBuilt.GetAnonymousDelegates();
var anonymousDelegatesWithIndexedNames = moduleBeingBuilt.GetAnonymousDelegatesWithIndexedNames();
var sourceAssembly = ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly;
var sourceContext = new EmitContext((PEModuleBuilder)previousGeneration.PEModuleBuilder, null, new DiagnosticBag(), metadataOnly: false, includePrivateMembers: true);
var otherContext = new EmitContext(moduleBeingBuilt, null, new DiagnosticBag(), metadataOnly: false, includePrivateMembers: true);

var matcher = new CSharpSymbolMatcher(
anonymousTypeMap,
anonymousDelegates,
anonymousDelegatesWithIndexedNames,
sourceAssembly,
sourceContext,
compilation.SourceAssembly,
otherContext,
synthesizedTypes,
currentSynthesizedMembers,
currentDeletedMembers);

Expand All @@ -204,13 +200,11 @@ private static EmitBaseline MapToCompilation(

// TODO: can we reuse some data from the previous matcher?
var matcherWithAllSynthesizedMembers = new CSharpSymbolMatcher(
anonymousTypeMap,
anonymousDelegates,
anonymousDelegatesWithIndexedNames,
sourceAssembly,
sourceContext,
compilation.SourceAssembly,
otherContext,
synthesizedTypes,
mappedSynthesizedMembers,
mappedDeletedMembers);

Expand Down
Loading