未验证 提交 9e786147 编写于 作者: J Jared Parsons 提交者: GitHub

Merge pull request #42348 from jaredpar/nullable-ref

Annotate ReferenceManager
{
"tools": {
"dotnet": "3.1.101",
"dotnet": "3.1.200",
"vs": {
"version": "16.4"
},
......
......@@ -353,7 +353,7 @@ private bool CreateAndSetSourceAssemblyFullBind(CSharpCompilation compilation)
try
{
IDictionary<(string, string), MetadataReference> boundReferenceDirectiveMap;
IDictionary<(string, string), MetadataReference>? boundReferenceDirectiveMap;
ImmutableArray<MetadataReference> boundReferenceDirectives;
ImmutableArray<AssemblyData> referencedAssemblies;
ImmutableArray<PEModule> modules; // To make sure the modules are not collected ahead of time.
......@@ -382,7 +382,7 @@ private bool CreateAndSetSourceAssemblyFullBind(CSharpCompilation compilation)
// Avoid resolving previously resolved missing references. If we call to the resolver again we would create new assembly symbols for them,
// which would not match the previously created ones. As a result we would get duplicate PE types and conversion errors.
var implicitReferenceResolutions = compilation.ScriptCompilationInfo?.PreviousScriptCompilation?.GetBoundReferenceManager().ImplicitReferenceResolutions ??
ImmutableDictionary<AssemblyIdentity, PortableExecutableReference>.Empty;
ImmutableDictionary<AssemblyIdentity, PortableExecutableReference?>.Empty;
BoundInputAssembly[] bindingResult = Bind(
compilation,
......@@ -426,19 +426,20 @@ private bool CreateAndSetSourceAssemblyFullBind(CSharpCompilation compilation)
for (int i = 1; i < bindingResult.Length; i++)
{
if ((object)bindingResult[i].AssemblySymbol == null)
ref BoundInputAssembly bound = ref bindingResult[i];
if (bound.AssemblySymbol is null)
{
// symbol hasn't been found in the cache, create a new one
bindingResult[i].AssemblySymbol = ((AssemblyDataForMetadataOrCompilation)allAssemblyData[i]).CreateAssemblySymbol();
bound.AssemblySymbol = ((AssemblyDataForMetadataOrCompilation)allAssemblyData[i]).CreateAssemblySymbol();
newSymbols.Add(i);
}
Debug.Assert(allAssemblyData[i].IsLinked == bindingResult[i].AssemblySymbol.IsLinked);
Debug.Assert(allAssemblyData[i].IsLinked == bound.AssemblySymbol.IsLinked);
}
var assemblySymbol = new SourceAssemblySymbol(compilation, SimpleAssemblyName, compilation.MakeSourceModuleName(), netModules: modules);
AssemblySymbol corLibrary;
AssemblySymbol? corLibrary;
if (corLibraryIndex == 0)
{
......@@ -553,12 +554,12 @@ private bool CreateAndSetSourceAssemblyFullBind(CSharpCompilation compilation)
if (compilationData != null)
{
SetupReferencesForRetargetingAssembly(bindingResult, i, ref missingAssemblies, sourceAssemblyDebugOnly: sourceAssembly);
SetupReferencesForRetargetingAssembly(bindingResult, ref bindingResult[i], ref missingAssemblies, sourceAssemblyDebugOnly: sourceAssembly);
}
else
{
var fileData = (AssemblyDataForFile)assemblies[i];
SetupReferencesForFileAssembly(fileData, bindingResult, i, ref missingAssemblies, sourceAssemblyDebugOnly: sourceAssembly);
SetupReferencesForFileAssembly(fileData, bindingResult, ref bindingResult[i], ref missingAssemblies, sourceAssemblyDebugOnly: sourceAssembly);
}
}
......@@ -569,9 +570,13 @@ private bool CreateAndSetSourceAssemblyFullBind(CSharpCompilation compilation)
foreach (int i in newSymbols)
{
ref BoundInputAssembly currentBindingResult = ref bindingResult[i];
Debug.Assert(currentBindingResult.AssemblySymbol is object);
Debug.Assert(currentBindingResult.ReferenceBinding is object);
if (assemblies[i].ContainsNoPiaLocalTypes)
{
bindingResult[i].AssemblySymbol.SetNoPiaResolutionAssemblies(noPiaResolutionAssemblies);
currentBindingResult.AssemblySymbol.SetNoPiaResolutionAssemblies(noPiaResolutionAssemblies);
}
// Setup linked referenced assemblies.
......@@ -579,26 +584,27 @@ private bool CreateAndSetSourceAssemblyFullBind(CSharpCompilation compilation)
if (assemblies[i].IsLinked)
{
linkedReferencedAssembliesBuilder.Add(bindingResult[i].AssemblySymbol);
linkedReferencedAssembliesBuilder.Add(currentBindingResult.AssemblySymbol);
}
foreach (var referenceBinding in bindingResult[i].ReferenceBinding)
foreach (var referenceBinding in currentBindingResult.ReferenceBinding)
{
if (referenceBinding.IsBound &&
assemblies[referenceBinding.DefinitionIndex].IsLinked)
{
linkedReferencedAssembliesBuilder.Add(
bindingResult[referenceBinding.DefinitionIndex].AssemblySymbol);
var linkedAssemblySymbol = bindingResult[referenceBinding.DefinitionIndex].AssemblySymbol;
Debug.Assert(linkedAssemblySymbol is object);
linkedReferencedAssembliesBuilder.Add(linkedAssemblySymbol);
}
}
if (linkedReferencedAssembliesBuilder.Count > 0)
{
linkedReferencedAssembliesBuilder.RemoveDuplicates();
bindingResult[i].AssemblySymbol.SetLinkedReferencedAssemblies(linkedReferencedAssembliesBuilder.ToImmutable());
currentBindingResult.AssemblySymbol.SetLinkedReferencedAssemblies(linkedReferencedAssembliesBuilder.ToImmutable());
}
bindingResult[i].AssemblySymbol.SetCorLibrary(corLibrary);
currentBindingResult.AssemblySymbol.SetCorLibrary(corLibrary);
}
linkedReferencedAssembliesBuilder.Free();
......@@ -617,27 +623,31 @@ private static void UpdateSymbolCacheNoLock(List<int> newSymbols, ImmutableArray
// Add new assembly symbols into the cache
foreach (int i in newSymbols)
{
var compilationData = assemblies[i] as AssemblyDataForCompilation;
ref BoundInputAssembly current = ref bindingResult[i];
Debug.Assert(current.AssemblySymbol is object);
var compilationData = assemblies[i] as AssemblyDataForCompilation;
if (compilationData != null)
{
compilationData.Compilation.CacheRetargetingAssemblySymbolNoLock(bindingResult[i].AssemblySymbol);
compilationData.Compilation.CacheRetargetingAssemblySymbolNoLock(current.AssemblySymbol);
}
else
{
var fileData = (AssemblyDataForFile)assemblies[i];
fileData.CachedSymbols.Add((PEAssemblySymbol)bindingResult[i].AssemblySymbol);
fileData.CachedSymbols.Add((PEAssemblySymbol)current.AssemblySymbol);
}
}
}
private static void SetupReferencesForRetargetingAssembly(
BoundInputAssembly[] bindingResult,
int bindingIndex,
ref BoundInputAssembly currentBindingResult,
ref Dictionary<AssemblyIdentity, MissingAssemblySymbol>? missingAssemblies,
SourceAssemblySymbol sourceAssemblyDebugOnly)
{
var retargetingAssemblySymbol = (RetargetingAssemblySymbol)bindingResult[bindingIndex].AssemblySymbol;
Debug.Assert(currentBindingResult.AssemblySymbol is object);
Debug.Assert(currentBindingResult.ReferenceBinding is object);
var retargetingAssemblySymbol = (RetargetingAssemblySymbol)currentBindingResult.AssemblySymbol;
ImmutableArray<ModuleSymbol> modules = retargetingAssemblySymbol.Modules;
int moduleCount = modules.Length;
int refsUsed = 0;
......@@ -687,7 +697,7 @@ private static void UpdateSymbolCacheNoLock(List<int> newSymbols, ImmutableArray
for (int k = 0; k < refsCount; k++)
{
var referenceBinding = bindingResult[bindingIndex].ReferenceBinding[refsUsed + k];
var referenceBinding = currentBindingResult.ReferenceBinding[refsUsed + k];
if (referenceBinding.IsBound)
{
symbols[k] = GetAssemblyDefinitionSymbol(bindingResult, referenceBinding, ref unifiedAssemblies);
......@@ -708,11 +718,13 @@ private static void UpdateSymbolCacheNoLock(List<int> newSymbols, ImmutableArray
private static void SetupReferencesForFileAssembly(
AssemblyDataForFile fileData,
BoundInputAssembly[] bindingResult,
int bindingIndex,
ref BoundInputAssembly currentBindingResult,
ref Dictionary<AssemblyIdentity, MissingAssemblySymbol>? missingAssemblies,
SourceAssemblySymbol sourceAssemblyDebugOnly)
{
var portableExecutableAssemblySymbol = (PEAssemblySymbol)bindingResult[bindingIndex].AssemblySymbol;
Debug.Assert(currentBindingResult.AssemblySymbol is object);
Debug.Assert(currentBindingResult.ReferenceBinding is object);
var portableExecutableAssemblySymbol = (PEAssemblySymbol)currentBindingResult.AssemblySymbol;
ImmutableArray<ModuleSymbol> modules = portableExecutableAssemblySymbol.Modules;
int moduleCount = modules.Length;
......@@ -729,7 +741,7 @@ private static void UpdateSymbolCacheNoLock(List<int> newSymbols, ImmutableArray
ArrayBuilder<UnifiedAssembly<AssemblySymbol>>? unifiedAssemblies = null;
for (int k = 0; k < moduleReferenceCount; k++)
{
var boundReference = bindingResult[bindingIndex].ReferenceBinding[refsUsed + k];
var boundReference = currentBindingResult.ReferenceBinding[refsUsed + k];
if (boundReference.IsBound)
{
symbols[k] = GetAssemblyDefinitionSymbol(bindingResult, boundReference, ref unifiedAssemblies);
......@@ -772,7 +784,10 @@ private static void UpdateSymbolCacheNoLock(List<int> newSymbols, ImmutableArray
for (int k = 0; k < refsCount; k++)
{
var boundReference = bindingResult[0].ReferenceBinding[refsUsed + k];
Debug.Assert(bindingResult[0].ReferenceBinding is object);
var boundReference = bindingResult[0].ReferenceBinding![refsUsed + k];
Debug.Assert(boundReference.ReferenceIdentity is object);
if (boundReference.IsBound)
{
symbols[k] = GetAssemblyDefinitionSymbol(bindingResult, boundReference, ref unifiedAssemblies);
......@@ -809,9 +824,9 @@ private static void UpdateSymbolCacheNoLock(List<int> newSymbols, ImmutableArray
ref ArrayBuilder<UnifiedAssembly<AssemblySymbol>>? unifiedAssemblies)
{
Debug.Assert(referenceBinding.IsBound);
Debug.Assert(referenceBinding.ReferenceIdentity is object);
var assembly = bindingResult[referenceBinding.DefinitionIndex].AssemblySymbol;
RoslynDebug.Assert((object)assembly != null);
Debug.Assert(assembly is object);
if (referenceBinding.VersionDifference != 0)
{
......@@ -1013,7 +1028,7 @@ protected override void AddAvailableSymbols(List<AssemblySymbol> assemblies)
}
}
public override bool IsMatchingAssembly(AssemblySymbol candidateAssembly)
public override bool IsMatchingAssembly(AssemblySymbol? candidateAssembly)
{
return IsMatchingAssembly(candidateAssembly as PEAssemblySymbol);
}
......@@ -1121,7 +1136,7 @@ protected override void AddAvailableSymbols(List<AssemblySymbol> assemblies)
}
}
public override bool IsMatchingAssembly(AssemblySymbol candidateAssembly)
public override bool IsMatchingAssembly(AssemblySymbol? candidateAssembly)
{
var retargeting = candidateAssembly as RetargetingAssemblySymbol;
AssemblySymbol? asm;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using Microsoft.CodeAnalysis.Text;
using System.Diagnostics;
......@@ -10,10 +12,10 @@ namespace Microsoft.CodeAnalysis
/// <summary>
/// Represents the value of #r reference along with its source location.
/// </summary>
internal struct ReferenceDirective
internal readonly struct ReferenceDirective
{
public readonly string File;
public readonly Location Location;
public readonly string? File;
public readonly Location? Location;
public ReferenceDirective(string file, Location location)
{
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
......@@ -41,7 +43,7 @@ internal abstract class AssemblyData
/// The AssemblySymbol to check.
/// </param>
/// <returns>Boolean.</returns>
public abstract bool IsMatchingAssembly(TAssemblySymbol assembly);
public abstract bool IsMatchingAssembly(TAssemblySymbol? assembly);
/// <summary>
/// Resolve assembly references against assemblies described by provided AssemblyData objects.
......@@ -66,7 +68,7 @@ internal abstract class AssemblyData
/// Get the source compilation backing this assembly, if one exists.
/// Returns null otherwise.
/// </summary>
public abstract Compilation SourceCompilation { get; }
public abstract Compilation? SourceCompilation { get; }
private string GetDebuggerDisplay() => $"{GetType().Name}: [{Identity.GetDisplayName()}]";
}
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
......@@ -102,7 +104,7 @@ public override IEnumerable<TAssemblySymbol> AvailableSymbols
return boundReferences;
}
public override bool IsMatchingAssembly(TAssemblySymbol assembly)
public override bool IsMatchingAssembly(TAssemblySymbol? assembly)
{
throw ExceptionUtilities.Unreachable;
}
......@@ -131,7 +133,7 @@ public override bool DeclaresTheObjectClass
}
}
public override Compilation SourceCompilation => null;
public override Compilation? SourceCompilation => null;
}
}
}
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Diagnostics;
using Microsoft.CodeAnalysis.Text;
......@@ -13,9 +15,9 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
/// Result of binding an AssemblyRef to an AssemblyDef.
/// </summary>
[DebuggerDisplay("{GetDebuggerDisplay(), nq}")]
internal struct AssemblyReferenceBinding
internal readonly struct AssemblyReferenceBinding
{
private readonly AssemblyIdentity _referenceIdentity;
private readonly AssemblyIdentity? _referenceIdentity;
private readonly int _definitionIndex;
private readonly int _versionDifference;
......@@ -93,7 +95,7 @@ internal int DefinitionIndex
}
}
internal AssemblyIdentity ReferenceIdentity
internal AssemblyIdentity? ReferenceIdentity
{
get
{
......@@ -103,7 +105,8 @@ internal AssemblyIdentity ReferenceIdentity
private string GetDebuggerDisplay()
{
return IsBound ? ReferenceIdentity.GetDisplayName() + " -> #" + DefinitionIndex + (VersionDifference != 0 ? " VersionDiff=" + VersionDifference : "") : "unbound";
var displayName = ReferenceIdentity?.GetDisplayName() ?? "";
return IsBound ? displayName + " -> #" + DefinitionIndex + (VersionDifference != 0 ? " VersionDiff=" + VersionDifference : "") : "unbound";
}
}
}
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
namespace Microsoft.CodeAnalysis
{
internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
......@@ -10,7 +12,7 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
/// Private helper class to capture information about AssemblySymbol instance we
/// should check for suitability. Used by the Bind method.
/// </summary>
private struct AssemblyReferenceCandidate
private readonly struct AssemblyReferenceCandidate
{
/// <summary>
/// An index of the AssemblyData object in the input array. AssemblySymbol instance should
......@@ -22,7 +24,7 @@ private struct AssemblyReferenceCandidate
/// <summary>
/// AssemblySymbol instance to check for suitability.
/// </summary>
public readonly TAssemblySymbol AssemblySymbol;
public readonly TAssemblySymbol? AssemblySymbol;
/// <summary>
/// Convenience constructor to initialize fields of this structure.
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Diagnostics;
namespace Microsoft.CodeAnalysis
......@@ -18,7 +20,7 @@ internal struct BoundInputAssembly
/// Suitable AssemblySymbol instance for the corresponding assembly,
/// null reference if none is available/found.
/// </summary>
internal TAssemblySymbol AssemblySymbol;
internal TAssemblySymbol? AssemblySymbol;
/// <summary>
/// For each AssemblyRef of this AssemblyDef specifies which AssemblyDef matches the reference.
......@@ -31,9 +33,9 @@ internal struct BoundInputAssembly
/// Each element describes the assembly the corresponding reference of the input assembly
/// is bound to.
/// </remarks>
internal AssemblyReferenceBinding[] ReferenceBinding;
internal AssemblyReferenceBinding[]? ReferenceBinding;
private string GetDebuggerDisplay()
private string? GetDebuggerDisplay()
{
return AssemblySymbol == null ? "?" : AssemblySymbol.ToString();
}
......
......@@ -2,10 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis.PooledObjects;
using Roslyn.Utilities;
......@@ -93,14 +96,14 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
ImmutableArray<PEModule> explicitModules,
ImmutableArray<MetadataReference> explicitReferences,
ImmutableArray<ResolvedReference> explicitReferenceMap,
MetadataReferenceResolver resolverOpt,
MetadataReferenceResolver? resolverOpt,
MetadataImportOptions importOptions,
bool supersedeLowerVersions,
[In, Out] Dictionary<string, List<ReferencedAssemblyIdentity>> assemblyReferencesBySimpleName,
out ImmutableArray<AssemblyData> allAssemblies,
out ImmutableArray<MetadataReference> implicitlyResolvedReferences,
out ImmutableArray<ResolvedReference> implicitlyResolvedReferenceMap,
ref ImmutableDictionary<AssemblyIdentity, PortableExecutableReference> implicitReferenceResolutions,
ref ImmutableDictionary<AssemblyIdentity, PortableExecutableReference?> implicitReferenceResolutions,
[In, Out] DiagnosticBag resolutionDiagnostics,
out bool hasCircularReference,
out int corLibraryIndex)
......@@ -205,7 +208,7 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
out ImmutableArray<AssemblyData> allAssemblies,
out ImmutableArray<MetadataReference> metadataReferences,
out ImmutableArray<ResolvedReference> resolvedReferences,
ref ImmutableDictionary<AssemblyIdentity, PortableExecutableReference> implicitReferenceResolutions,
ref ImmutableDictionary<AssemblyIdentity, PortableExecutableReference?> implicitReferenceResolutions,
DiagnosticBag resolutionDiagnostics)
{
Debug.Assert(explicitAssemblies[0] is AssemblyDataForAssemblyBeingBuilt);
......@@ -222,7 +225,7 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
var metadataReferencesBuilder = ArrayBuilder<MetadataReference>.GetInstance();
Dictionary<MetadataReference, MergedAliases> lazyAliasMap = null;
Dictionary<MetadataReference, MergedAliases>? lazyAliasMap = null;
// metadata references and corresponding bindings of their references, used to calculate a fixed point:
var referenceBindingsToProcess = ArrayBuilder<(MetadataReference, ArraySegment<AssemblyReferenceBinding>)>.GetInstance();
......@@ -247,15 +250,16 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
continue;
}
Debug.Assert(binding.ReferenceIdentity is object);
if (!TryResolveMissingReference(
requestingReference,
binding.ReferenceIdentity,
ref implicitReferenceResolutions,
resolver,
resolutionDiagnostics,
out AssemblyIdentity resolvedAssemblyIdentity,
out AssemblyMetadata resolvedAssemblyMetadata,
out PortableExecutableReference resolvedReference))
out AssemblyIdentity? resolvedAssemblyIdentity,
out AssemblyMetadata? resolvedAssemblyMetadata,
out PortableExecutableReference? resolvedReference))
{
// Note the failure, but do not commit it to implicitReferenceResolutions until we are done with resolving all missing references.
resolutionFailures.Add(binding.ReferenceIdentity);
......@@ -331,6 +335,7 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol>
// We only need to resolve against implicitly resolved assemblies,
// since we already resolved against explicitly specified ones.
Debug.Assert(binding.ReferenceIdentity is object);
referenceBinding[i] = ResolveReferencedAssembly(
binding.ReferenceIdentity,
allAssemblies,
......@@ -426,7 +431,7 @@ private static ImmutableArray<int> CalculateModuleToReferenceMap(ImmutableArray<
private static ImmutableArray<ResolvedReference> ToResolvedAssemblyReferences(
ImmutableArray<MetadataReference> references,
Dictionary<MetadataReference, MergedAliases> propertyMapOpt,
Dictionary<MetadataReference, MergedAliases>? propertyMapOpt,
int explicitAssemblyCount)
{
var result = ArrayBuilder<ResolvedReference>.GetInstance(references.Length);
......@@ -491,12 +496,12 @@ private static void UpdateBindingsOfAssemblyBeingBuilt(ArrayBuilder<AssemblyRefe
private bool TryResolveMissingReference(
MetadataReference requestingReference,
AssemblyIdentity referenceIdentity,
ref ImmutableDictionary<AssemblyIdentity, PortableExecutableReference> implicitReferenceResolutions,
ref ImmutableDictionary<AssemblyIdentity, PortableExecutableReference?> implicitReferenceResolutions,
MetadataReferenceResolver resolver,
DiagnosticBag resolutionDiagnostics,
out AssemblyIdentity resolvedAssemblyIdentity,
out AssemblyMetadata resolvedAssemblyMetadata,
out PortableExecutableReference resolvedReference)
[NotNullWhen(true)] out AssemblyIdentity? resolvedAssemblyIdentity,
[NotNullWhen(true)] out AssemblyMetadata? resolvedAssemblyMetadata,
[NotNullWhen(true)] out PortableExecutableReference? resolvedReference)
{
resolvedAssemblyIdentity = null;
resolvedAssemblyMetadata = null;
......@@ -523,6 +528,7 @@ private static void UpdateBindingsOfAssemblyBeingBuilt(ArrayBuilder<AssemblyRefe
}
var resolvedAssembly = resolvedAssemblyMetadata.GetAssembly();
Debug.Assert(resolvedAssembly is object);
// Allow reference and definition identities to differ in version, but not other properties.
// Don't need to compare if we are reusing a previously resolved reference.
......@@ -542,8 +548,10 @@ private static void UpdateBindingsOfAssemblyBeingBuilt(ArrayBuilder<AssemblyRefe
PortableExecutableReference peReference,
MetadataImportOptions importOptions)
{
var assembly = assemblyMetadata.GetAssembly();
Debug.Assert(assembly is object);
return CreateAssemblyDataForFile(
assemblyMetadata.GetAssembly(),
assembly,
assemblyMetadata.CachedSymbols,
peReference.DocumentationProvider,
SimpleAssemblyName,
......@@ -724,6 +732,7 @@ private void ReuseAssemblySymbols(BoundInputAssembly[] boundInputs, TAssemblySym
AssemblyReferenceCandidate candidate = candidatesToExamine.Dequeue();
Debug.Assert(candidate.DefinitionIndex >= 0);
Debug.Assert(candidate.AssemblySymbol is object);
int candidateIndex = candidate.DefinitionIndex;
......@@ -731,7 +740,7 @@ private void ReuseAssemblySymbols(BoundInputAssembly[] boundInputs, TAssemblySym
Debug.Assert(boundInputs[candidateIndex].AssemblySymbol == null ||
candidateInputAssemblySymbols[candidateIndex] == null);
TAssemblySymbol inputAssembly = boundInputs[candidateIndex].AssemblySymbol;
TAssemblySymbol? inputAssembly = boundInputs[candidateIndex].AssemblySymbol;
if (inputAssembly == null)
{
inputAssembly = candidateInputAssemblySymbols[candidateIndex];
......@@ -770,8 +779,9 @@ private void ReuseAssemblySymbols(BoundInputAssembly[] boundInputs, TAssemblySym
var candidateReferenceBinding = boundInputs[candidateIndex].ReferenceBinding;
// the AssemblySymbols the candidate symbol refers to:
TAssemblySymbol[] candidateReferencedSymbols = GetActualBoundReferencesUsedBy(candidate.AssemblySymbol);
TAssemblySymbol?[] candidateReferencedSymbols = GetActualBoundReferencesUsedBy(candidate.AssemblySymbol);
Debug.Assert(candidateReferenceBinding is object);
Debug.Assert(candidateReferenceBinding.Length == candidateReferencedSymbols.Length);
int referencesCount = candidateReferencedSymbols.Length;
......@@ -801,7 +811,8 @@ private void ReuseAssemblySymbols(BoundInputAssembly[] boundInputs, TAssemblySym
}
// We resolved the reference, candidate must have that reference resolved too.
if (candidateReferencedSymbols[k] == null)
var currentCandidateReferencedSymbol = candidateReferencedSymbols[k];
if (currentCandidateReferencedSymbol == null)
{
// can't use symbols
match = false;
......@@ -817,7 +828,7 @@ private void ReuseAssemblySymbols(BoundInputAssembly[] boundInputs, TAssemblySym
}
// Make sure symbols represent the same assembly/binary
if (!assemblies[definitionIndex].IsMatchingAssembly(candidateReferencedSymbols[k]))
if (!assemblies[definitionIndex].IsMatchingAssembly(currentCandidateReferencedSymbol))
{
// Mismatch between versions?
match = false;
......@@ -832,7 +843,7 @@ private void ReuseAssemblySymbols(BoundInputAssembly[] boundInputs, TAssemblySym
break; // Stop processing references.
}
if (IsLinked(candidateReferencedSymbols[k]) != assemblies[definitionIndex].IsLinked)
if (IsLinked(currentCandidateReferencedSymbol) != assemblies[definitionIndex].IsLinked)
{
// Mismatch between reference kind.
match = false;
......@@ -840,13 +851,13 @@ private void ReuseAssemblySymbols(BoundInputAssembly[] boundInputs, TAssemblySym
}
// Add this reference to the queue so that we consider it as a candidate too
candidatesToExamine.Enqueue(new AssemblyReferenceCandidate(definitionIndex, candidateReferencedSymbols[k]));
candidatesToExamine.Enqueue(new AssemblyReferenceCandidate(definitionIndex, currentCandidateReferencedSymbol));
}
// Check that the COR library used by the candidate assembly symbol is the same as the one use by this compilation.
if (match)
{
TAssemblySymbol candidateCorLibrary = GetCorLibrary(candidate.AssemblySymbol);
TAssemblySymbol? candidateCorLibrary = GetCorLibrary(candidate.AssemblySymbol);
if (candidateCorLibrary == null)
{
......@@ -926,13 +937,15 @@ private static bool CheckCircularReference(IReadOnlyList<AssemblyReferenceBindin
private static bool IsSuperseded(AssemblyIdentity identity, IReadOnlyDictionary<string, List<ReferencedAssemblyIdentity>> assemblyReferencesBySimpleName)
{
return assemblyReferencesBySimpleName[identity.Name][0].Identity.Version != identity.Version;
var value = assemblyReferencesBySimpleName[identity.Name][0];
Debug.Assert(value.Identity is object);
return value.Identity.Version != identity.Version;
}
private static int IndexOfCorLibrary(ImmutableArray<AssemblyData> assemblies, IReadOnlyDictionary<string, List<ReferencedAssemblyIdentity>> assemblyReferencesBySimpleName, bool supersedeLowerVersions)
{
// Figure out COR library for this compilation.
ArrayBuilder<int> corLibraryCandidates = null;
ArrayBuilder<int>? corLibraryCandidates = null;
for (int i = 1; i < assemblies.Length; i++)
{
......@@ -1004,7 +1017,6 @@ static internal bool InternalsMayBeVisibleToAssemblyBeingCompiled(string compila
return !assembly.GetInternalsVisibleToPublicKeys(compilationName).IsEmpty();
}
#nullable enable
// https://github.com/dotnet/roslyn/issues/40751 It should not be necessary to annotate this method to annotate overrides
/// <summary>
/// Return AssemblySymbols referenced by the input AssemblySymbol. The AssemblySymbols must correspond
......@@ -1018,7 +1030,6 @@ static internal bool InternalsMayBeVisibleToAssemblyBeingCompiled(string compila
/// Implementers may return cached array, Binder does not mutate it.
/// </returns>
protected abstract TAssemblySymbol?[] GetActualBoundReferencesUsedBy(TAssemblySymbol assemblySymbol);
#nullable restore
/// <summary>
/// Return collection of assemblies involved in canonical type resolution of
......@@ -1032,11 +1043,9 @@ static internal bool InternalsMayBeVisibleToAssemblyBeingCompiled(string compila
/// </summary>
protected abstract bool IsLinked(TAssemblySymbol candidateAssembly);
#nullable enable
/// <summary>
/// Get Assembly used as COR library for the candidate.
/// </summary>
protected abstract TAssemblySymbol? GetCorLibrary(TAssemblySymbol candidateAssembly);
#nullable restore
}
}
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
......@@ -42,9 +44,9 @@ internal abstract class CommonReferenceManager
/// </summary>
internal abstract IEnumerable<(IAssemblySymbolInternal, ImmutableArray<string>)> GetReferencedAssemblyAliases();
internal abstract MetadataReference GetMetadataReference(IAssemblySymbolInternal assemblySymbol);
internal abstract MetadataReference? GetMetadataReference(IAssemblySymbolInternal? assemblySymbol);
internal abstract ImmutableArray<MetadataReference> ExplicitReferences { get; }
internal abstract ImmutableDictionary<AssemblyIdentity, PortableExecutableReference> ImplicitReferenceResolutions { get; }
internal abstract ImmutableDictionary<AssemblyIdentity, PortableExecutableReference?> ImplicitReferenceResolutions { get; }
}
internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol> : CommonReferenceManager
......@@ -87,7 +89,7 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol> : C
/// A map from a metadata reference to an index to <see cref="_lazyReferencedAssemblies"/> array. Do not access
/// directly, use <see cref="_lazyReferencedAssembliesMap"/> property instead.
/// </summary>
private Dictionary<MetadataReference, int> _lazyReferencedAssembliesMap;
private Dictionary<MetadataReference, int>? _lazyReferencedAssembliesMap;
/// <summary>
/// A map from a net-module metadata reference to the index of the corresponding module
......@@ -97,13 +99,13 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol> : C
/// Subtract one from the index (for the manifest module) to find the corresponding elements
/// of <see cref="_lazyReferencedModules"/> and <see cref="_lazyReferencedModulesReferences"/>.
/// </remarks>
private Dictionary<MetadataReference, int> _lazyReferencedModuleIndexMap;
private Dictionary<MetadataReference, int>? _lazyReferencedModuleIndexMap;
/// <summary>
/// Maps (containing syntax tree file name, reference string) of #r directive to a resolved metadata reference.
/// If multiple #r's in the same tree use the same value as a reference the resolved metadata reference is the same as well.
/// </summary>
private IDictionary<(string, string), MetadataReference> _lazyReferenceDirectiveMap;
private IDictionary<(string, string), MetadataReference>? _lazyReferenceDirectiveMap;
/// <summary>
/// Array of unique bound #r references.
......@@ -128,7 +130,7 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol> : C
/// This is important to maintain consistency, especially across multiple submissions (e.g. the reference is not found during compilation of the first submission
/// but then it is available when the second submission is compiled).
/// </summary>
private ImmutableDictionary<AssemblyIdentity, PortableExecutableReference> _lazyImplicitReferenceResolutions;
private ImmutableDictionary<AssemblyIdentity, PortableExecutableReference?>? _lazyImplicitReferenceResolutions;
/// <summary>
/// Diagnostics produced during reference resolution and binding.
......@@ -148,7 +150,7 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol> : C
/// here since we wouldn't be able to share the state among subsequent compilations that are derived from it
/// (each of them has its own source assembly symbol).
/// </remarks>
private TAssemblySymbol _lazyCorLibraryOpt;
private TAssemblySymbol? _lazyCorLibraryOpt;
/// <summary>
/// Standalone modules referenced by the compilation (doesn't include the manifest module of the compilation).
......@@ -184,7 +186,7 @@ internal partial class CommonReferenceManager<TCompilation, TAssemblySymbol> : C
/// </summary>
private ImmutableArray<UnifiedAssembly<TAssemblySymbol>> _lazyUnifiedAssemblies;
public CommonReferenceManager(string simpleAssemblyName, AssemblyIdentityComparer identityComparer, Dictionary<MetadataReference, MetadataOrDiagnostic> observedMetadata)
public CommonReferenceManager(string simpleAssemblyName, AssemblyIdentityComparer identityComparer, Dictionary<MetadataReference, MetadataOrDiagnostic>? observedMetadata)
{
Debug.Assert(simpleAssemblyName != null);
Debug.Assert(identityComparer != null);
......@@ -216,8 +218,9 @@ internal bool HasCircularReference
{
get
{
// MemberNotNull remove ! https://github.com/dotnet/roslyn/issues/41964
AssertBound();
return _lazyReferencedAssembliesMap;
return _lazyReferencedAssembliesMap!;
}
}
......@@ -225,8 +228,9 @@ internal bool HasCircularReference
{
get
{
// MemberNotNull remove ! https://github.com/dotnet/roslyn/issues/41964
AssertBound();
return _lazyReferencedModuleIndexMap;
return _lazyReferencedModuleIndexMap!;
}
}
......@@ -234,8 +238,9 @@ internal bool HasCircularReference
{
get
{
// MemberNotNull remove ! https://github.com/dotnet/roslyn/issues/41964
AssertBound();
return _lazyReferenceDirectiveMap;
return _lazyReferenceDirectiveMap!;
}
}
......@@ -248,12 +253,13 @@ internal ImmutableArray<MetadataReference> DirectiveReferences
}
}
internal override ImmutableDictionary<AssemblyIdentity, PortableExecutableReference> ImplicitReferenceResolutions
internal override ImmutableDictionary<AssemblyIdentity, PortableExecutableReference?> ImplicitReferenceResolutions
{
get
{
// MemberNotNull remove ! https://github.com/dotnet/roslyn/issues/41964
AssertBound();
return _lazyImplicitReferenceResolutions;
return _lazyImplicitReferenceResolutions!;
}
}
......@@ -268,7 +274,7 @@ internal override ImmutableArray<MetadataReference> ExplicitReferences
#region Symbols necessary to set up source assembly and module
internal TAssemblySymbol CorLibraryOpt
internal TAssemblySymbol? CorLibraryOpt
{
get
{
......@@ -346,6 +352,7 @@ internal void AssertUnbound()
Debug.Assert(_lazyCorLibraryOpt == null);
}
// MemberNotNull all the lazy maps below https://github.com/dotnet/roslyn/issues/41964
[Conditional("DEBUG")]
internal void AssertBound()
{
......@@ -390,10 +397,10 @@ internal bool IsBound
IDictionary<(string, string), MetadataReference> boundReferenceDirectiveMap,
ImmutableArray<MetadataReference> directiveReferences,
ImmutableArray<MetadataReference> explicitReferences,
ImmutableDictionary<AssemblyIdentity, PortableExecutableReference> implicitReferenceResolutions,
ImmutableDictionary<AssemblyIdentity, PortableExecutableReference?> implicitReferenceResolutions,
bool containsCircularReferences,
ImmutableArray<Diagnostic> diagnostics,
TAssemblySymbol corLibraryOpt,
TAssemblySymbol? corLibraryOpt,
ImmutableArray<PEModule> referencedModules,
ImmutableArray<ModuleReferences<TAssemblySymbol>> referencedModulesReferences,
ImmutableArray<TAssemblySymbol> referencedAssemblies,
......@@ -511,14 +518,14 @@ internal bool IsBound
{
Debug.Assert(originalIdentities.Length == symbols.Length);
ImmutableDictionary<AssemblyIdentity, AssemblyIdentity>.Builder lazyBuilder = null;
ImmutableDictionary<AssemblyIdentity, AssemblyIdentity>.Builder? lazyBuilder = null;
for (int i = 0; i < originalIdentities.Length; i++)
{
var symbolIdentity = symbols[i].Identity;
var versionPattern = symbols[i].AssemblyVersionPattern;
var originalIdentity = originalIdentities[i];
if ((object)versionPattern != null)
if (versionPattern is object)
{
Debug.Assert(versionPattern.Build == ushort.MaxValue || versionPattern.Revision == ushort.MaxValue);
......@@ -555,14 +562,14 @@ internal static bool CompareVersionPartsSpecifiedInSource(Version version, Versi
// build and revision parts can differ only if the corresponding source versions were auto-generated:
var versionPattern = candidateSymbol.AssemblyVersionPattern;
Debug.Assert((object)versionPattern == null || versionPattern.Build == ushort.MaxValue || versionPattern.Revision == ushort.MaxValue);
Debug.Assert(versionPattern is null || versionPattern.Build == ushort.MaxValue || versionPattern.Revision == ushort.MaxValue);
if (((object)versionPattern == null || versionPattern.Build < ushort.MaxValue) && version.Build != candidateVersion.Build)
if ((versionPattern is null || versionPattern.Build < ushort.MaxValue) && version.Build != candidateVersion.Build)
{
return false;
}
if ((object)versionPattern == null && version.Revision != candidateVersion.Revision)
if (versionPattern is null && version.Revision != candidateVersion.Revision)
{
return false;
}
......@@ -611,7 +618,9 @@ internal static bool CompareVersionPartsSpecifiedInSource(Version version, Versi
// push dependencies onto the stack:
// +1 for the assembly being built:
foreach (var binding in bindingResult[assemblyIndex + 1].ReferenceBinding)
var referenceBinding = bindingResult[assemblyIndex + 1].ReferenceBinding;
Debug.Assert(referenceBinding is object);
foreach (var binding in referenceBinding)
{
if (binding.IsBound)
{
......@@ -648,7 +657,7 @@ internal static bool CompareVersionPartsSpecifiedInSource(Version version, Versi
return ReferencedAssembliesMap.Select(ra => KeyValuePairUtil.Create(ra.Key, (IAssemblySymbolInternal)ReferencedAssemblies[ra.Value]));
}
internal TAssemblySymbol GetReferencedAssemblySymbol(MetadataReference reference)
internal TAssemblySymbol? GetReferencedAssemblySymbol(MetadataReference reference)
{
int index;
return ReferencedAssembliesMap.TryGetValue(reference, out index) ? ReferencedAssemblies[index] : null;
......@@ -663,7 +672,7 @@ internal int GetReferencedModuleIndex(MetadataReference reference)
/// <summary>
/// Gets the <see cref="MetadataReference"/> that corresponds to the assembly symbol.
/// </summary>
internal override MetadataReference GetMetadataReference(IAssemblySymbolInternal assemblySymbol)
internal override MetadataReference? GetMetadataReference(IAssemblySymbolInternal? assemblySymbol)
{
foreach (var entry in ReferencedAssembliesMap)
{
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.PooledObjects;
......@@ -10,8 +12,8 @@ namespace Microsoft.CodeAnalysis
{
internal sealed class MergedAliases
{
public ArrayBuilder<string> AliasesOpt;
public ArrayBuilder<string> RecursiveAliasesOpt;
public ArrayBuilder<string>? AliasesOpt;
public ArrayBuilder<string>? RecursiveAliasesOpt;
/// <summary>
/// Adds aliases of a specified reference to the merged set of aliases.
......@@ -32,6 +34,7 @@ internal sealed class MergedAliases
/// </summary>
internal void Merge(MetadataReference reference)
{
ArrayBuilder<string> aliases;
if (reference.Properties.HasRecursiveAliases)
{
if (RecursiveAliasesOpt == null)
......@@ -40,6 +43,8 @@ internal void Merge(MetadataReference reference)
RecursiveAliasesOpt.AddRange(reference.Properties.Aliases);
return;
}
aliases = RecursiveAliasesOpt;
}
else
{
......@@ -49,10 +54,12 @@ internal void Merge(MetadataReference reference)
AliasesOpt.AddRange(reference.Properties.Aliases);
return;
}
aliases = AliasesOpt;
}
Merge(
aliases: reference.Properties.HasRecursiveAliases ? RecursiveAliasesOpt : AliasesOpt,
aliases: aliases,
newAliases: reference.Properties.Aliases);
}
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.Symbols;
......
......@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Diagnostics;
using Microsoft.CodeAnalysis.Symbols;
using Microsoft.CodeAnalysis.Text;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册