Skip to content

Commit

Permalink
Merge pull request #42348 from jaredpar/nullable-ref
Browse files Browse the repository at this point in the history
Annotate ReferenceManager
  • Loading branch information
jaredpar authored Mar 24, 2020
2 parents fd0bf09 + e159727 commit 9e78614
Show file tree
Hide file tree
Showing 15 changed files with 217 additions and 153 deletions.
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"tools": {
"dotnet": "3.1.101",
"dotnet": "3.1.200",
"vs": {
"version": "16.4"
},
Expand Down
73 changes: 44 additions & 29 deletions src/Compilers/CSharp/Portable/Symbols/ReferenceManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -553,12 +554,12 @@ private static void InitializeNewSymbols(

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);
}
}

Expand All @@ -569,36 +570,41 @@ private static void InitializeNewSymbols(

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.
linkedReferencedAssembliesBuilder.Clear();

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();
Expand All @@ -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;
Expand Down Expand Up @@ -687,7 +697,7 @@ private static void SetupReferencesForRetargetingAssembly(

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);
Expand All @@ -708,11 +718,13 @@ private static void SetupReferencesForRetargetingAssembly(
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;
Expand All @@ -729,7 +741,7 @@ private static void SetupReferencesForFileAssembly(
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);
Expand Down Expand Up @@ -772,7 +784,10 @@ private static void SetupReferencesForSourceAssembly(

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);
Expand Down Expand Up @@ -809,9 +824,9 @@ private static AssemblySymbol GetAssemblyDefinitionSymbol(
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)
{
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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)
{
Expand Down
6 changes: 4 additions & 2 deletions src/Compilers/Core/Portable/ReferenceManager/AssemblyData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand All @@ -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()}]";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -102,7 +104,7 @@ public override AssemblyReferenceBinding[] BindAssemblyReferences(
return boundReferences;
}

public override bool IsMatchingAssembly(TAssemblySymbol assembly)
public override bool IsMatchingAssembly(TAssemblySymbol? assembly)
{
throw ExceptionUtilities.Unreachable;
}
Expand Down Expand Up @@ -131,7 +133,7 @@ public override bool DeclaresTheObjectClass
}
}

public override Compilation SourceCompilation => null;
public override Compilation? SourceCompilation => null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -93,7 +95,7 @@ internal int DefinitionIndex
}
}

internal AssemblyIdentity ReferenceIdentity
internal AssemblyIdentity? ReferenceIdentity
{
get
{
Expand All @@ -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";
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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
Expand All @@ -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.
Expand Down
Loading

0 comments on commit 9e78614

Please sign in to comment.