From 8a7ff2e9d89222eebef27da1f76d23de8887f2c1 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 16 Feb 2021 09:22:16 -0800 Subject: [PATCH 01/13] Handle failed SaveAsync operations Fixes #31548 Fixes #42178 --- .../ValuesSources/WeaklyCachedRecoverableValueSource.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/ValuesSources/WeaklyCachedRecoverableValueSource.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/ValuesSources/WeaklyCachedRecoverableValueSource.cs index d546ba6f07495..4dd83fcbc63dd 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/ValuesSources/WeaklyCachedRecoverableValueSource.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/ValuesSources/WeaklyCachedRecoverableValueSource.cs @@ -128,7 +128,11 @@ private void ResetRecoverySource(Task saveTask, T instance) { using (Gate.DisposableWait(CancellationToken.None)) { - _recoverySource = new AsyncLazy(RecoverAsync, Recover, cacheResult: false); + // Only assume the instance is saved if the saveTask completed successfully. If the save did not + // complete, we can still rely on a constant value source to provide the instance. + _recoverySource = saveTask.Status == TaskStatus.RanToCompletion + ? new AsyncLazy(RecoverAsync, Recover, cacheResult: false) + : new ConstantValueSource(instance); // Need to keep instance alive until recovery source is updated. GC.KeepAlive(instance); From 2455535bd806c960726a8d1d9b5396b78e526b80 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 16 Feb 2021 09:40:32 -0800 Subject: [PATCH 02/13] Link to dotnet/runtime#30878 instead of dotnet/roslyn#42178 --- .../Portable/TemporaryStorage/TemporaryStorageServiceFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Workspaces/Core/Portable/TemporaryStorage/TemporaryStorageServiceFactory.cs b/src/Workspaces/Core/Portable/TemporaryStorage/TemporaryStorageServiceFactory.cs index d27d050dbc51d..ee128c5bff73d 100644 --- a/src/Workspaces/Core/Portable/TemporaryStorage/TemporaryStorageServiceFactory.cs +++ b/src/Workspaces/Core/Portable/TemporaryStorage/TemporaryStorageServiceFactory.cs @@ -35,7 +35,7 @@ public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) // MemoryMapped files which are used by the TemporaryStorageService are present in .NET Framework (including Mono) // and .NET Core Windows. For non-Windows .NET Core scenarios, we can return the TrivialTemporaryStorageService - // until https://github.com/dotnet/roslyn/issues/42178 is fixed. + // until https://github.com/dotnet/runtime/issues/30878 is fixed. return PlatformInformation.IsWindows || PlatformInformation.IsRunningOnMono ? (ITemporaryStorageService)new TemporaryStorageService(textFactory) : TrivialTemporaryStorageService.Instance; From ca2ae8291b46c811ff9bffcc9bdc0e45fd553e53 Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Wed, 17 Feb 2021 08:23:24 -0800 Subject: [PATCH 03/13] Remove ErrorOutput The `ErrorOutput` field is not used in the compiler protocol because the compiler never writes to stderr. This was complicating the code path for no good reason and hence I decided to remove it. --- src/Compilers/Core/CommandLine/BuildProtocol.cs | 14 -------------- src/Compilers/Core/MSBuildTask/ManagedCompiler.cs | 10 ---------- .../Server/VBCSCompilerTests/BuildProtocolTest.cs | 1 - 3 files changed, 25 deletions(-) diff --git a/src/Compilers/Core/CommandLine/BuildProtocol.cs b/src/Compilers/Core/CommandLine/BuildProtocol.cs index a15eef118b73d..5bc507533ca63 100644 --- a/src/Compilers/Core/CommandLine/BuildProtocol.cs +++ b/src/Compilers/Core/CommandLine/BuildProtocol.cs @@ -370,7 +370,6 @@ await ReadAllAsync(stream, /// Length UInteger 4 /// ReturnCode Integer 4 /// Output String Variable - /// ErrorOutput String Variable /// /// Strings are encoded via a character count prefix as a /// 32-bit integer, followed by an array of characters. @@ -381,7 +380,6 @@ internal sealed class CompletedBuildResponse : BuildResponse public readonly int ReturnCode; public readonly bool Utf8Output; public readonly string Output; - public readonly string ErrorOutput; public CompletedBuildResponse(int returnCode, bool utf8output, @@ -390,11 +388,6 @@ public CompletedBuildResponse(int returnCode, ReturnCode = returnCode; Utf8Output = utf8output; Output = output ?? string.Empty; - - // This field existed to support writing to Console.Error. The compiler doesn't ever write to - // this field or Console.Error. This field is only kept around in order to maintain the existing - // protocol semantics. - ErrorOutput = string.Empty; } public override ResponseType Type => ResponseType.Completed; @@ -404,12 +397,6 @@ public static CompletedBuildResponse Create(BinaryReader reader) var returnCode = reader.ReadInt32(); var utf8Output = reader.ReadBoolean(); var output = ReadLengthPrefixedString(reader); - var errorOutput = ReadLengthPrefixedString(reader); - if (!string.IsNullOrEmpty(errorOutput)) - { - throw new InvalidOperationException(); - } - return new CompletedBuildResponse(returnCode, utf8Output, output); } @@ -418,7 +405,6 @@ protected override void AddResponseBody(BinaryWriter writer) writer.Write(ReturnCode); writer.Write(Utf8Output); WriteLengthPrefixedString(writer, Output); - WriteLengthPrefixedString(writer, ErrorOutput); } } diff --git a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs index 6209bc1686198..93288e1397826 100644 --- a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs +++ b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs @@ -629,16 +629,6 @@ private int HandleResponse(BuildResponse response, string pathToTool, string res case BuildResponse.ResponseType.Completed: var completedResponse = (CompletedBuildResponse)response; LogMessages(completedResponse.Output, StandardOutputImportanceToUse); - - if (LogStandardErrorAsError) - { - LogErrorMultiline(completedResponse.ErrorOutput); - } - else - { - LogMessages(completedResponse.ErrorOutput, StandardErrorImportanceToUse); - } - return completedResponse.ReturnCode; case BuildResponse.ResponseType.MismatchedVersion: diff --git a/src/Compilers/Server/VBCSCompilerTests/BuildProtocolTest.cs b/src/Compilers/Server/VBCSCompilerTests/BuildProtocolTest.cs index 63369912e1754..98e04464dff83 100644 --- a/src/Compilers/Server/VBCSCompilerTests/BuildProtocolTest.cs +++ b/src/Compilers/Server/VBCSCompilerTests/BuildProtocolTest.cs @@ -38,7 +38,6 @@ public async Task ReadWriteCompleted() Assert.Equal(42, read.ReturnCode); Assert.False(read.Utf8Output); Assert.Equal("a string", read.Output); - Assert.Equal("", read.ErrorOutput); } [Fact] From 6371eee71ae560a7fafe142811619d3401b1b1f7 Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Wed, 17 Feb 2021 08:56:45 -0800 Subject: [PATCH 04/13] Clean up the error message path Refactor a bit and clean up some comments to help make the flow of data a bit clearer here. --- src/Compilers/Core/MSBuildTask/Csc.cs | 2 +- .../Core/MSBuildTask/ManagedCompiler.cs | 25 ++++--------------- src/Compilers/Core/MSBuildTask/Vbc.cs | 17 ++++++------- 3 files changed, 14 insertions(+), 30 deletions(-) diff --git a/src/Compilers/Core/MSBuildTask/Csc.cs b/src/Compilers/Core/MSBuildTask/Csc.cs index c387386b77404..3dead94c8a72b 100644 --- a/src/Compilers/Core/MSBuildTask/Csc.cs +++ b/src/Compilers/Core/MSBuildTask/Csc.cs @@ -176,7 +176,7 @@ public string? Nullable // Same separators as those used by Process.OutputDataReceived to maintain consistency between csc and VBCSCompiler private static readonly string[] s_separators = { "\r\n", "\r", "\n" }; - internal override void LogMessages(string output, MessageImportance messageImportance) + private protected override void LogCompilerOutput(string output, MessageImportance messageImportance) { var lines = output.Split(s_separators, StringSplitOptions.RemoveEmptyEntries); foreach (string line in lines) diff --git a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs index 93288e1397826..0a02c851b469c 100644 --- a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs +++ b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs @@ -628,7 +628,7 @@ private int HandleResponse(BuildResponse response, string pathToTool, string res { case BuildResponse.ResponseType.Completed: var completedResponse = (CompletedBuildResponse)response; - LogMessages(completedResponse.Output, StandardOutputImportanceToUse); + LogCompilerOutput(completedResponse.Output, StandardOutputImportanceToUse); return completedResponse.ReturnCode; case BuildResponse.ResponseType.MismatchedVersion: @@ -667,27 +667,12 @@ void logMessage(string message, bool isError) } } - private void LogErrorMultiline(string output) - { - string[] lines = output.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); - foreach (string line in lines) - { - string trimmedMessage = line.Trim(); - if (trimmedMessage != "") - { - Log.LogError(trimmedMessage); - } - } - } - /// - /// Log each of the messages in the given output with the given importance. - /// We assume each line is a message to log. + /// Log the compiler output to MSBuild. Each language will override this to parse their output and log it + /// in the language specific manner. This often involves parsing the raw output and formatting it as + /// individual messages for MSBuild. /// - /// - /// Should be "private protected" visibility once it is introduced into C#. - /// - internal abstract void LogMessages(string output, MessageImportance messageImportance); + private protected abstract void LogCompilerOutput(string output, MessageImportance messageImportance); public string GenerateResponseFileContents() { diff --git a/src/Compilers/Core/MSBuildTask/Vbc.cs b/src/Compilers/Core/MSBuildTask/Vbc.cs index 5eacb63ad0bc2..f74e830993918 100644 --- a/src/Compilers/Core/MSBuildTask/Vbc.cs +++ b/src/Compilers/Core/MSBuildTask/Vbc.cs @@ -238,7 +238,7 @@ public string? PdbFile private static readonly string[] s_separator = { Environment.NewLine }; - internal override void LogMessages(string output, MessageImportance messageImportance) + private protected override void LogCompilerOutput(string output, MessageImportance messageImportance) { var lines = output.Split(s_separator, StringSplitOptions.None); foreach (string line in lines) @@ -614,15 +614,14 @@ protected override bool ValidateParameters() } /// - /// This method intercepts the lines to be logged coming from STDOUT from VBC. - /// Once we see a standard vb warning or error, then we capture it and grab the next 3 - /// lines so we can transform the string form the form of FileName.vb(line) to FileName.vb(line,column) - /// which will allow us to report the line and column to the IDE, and thus filter the error - /// in the duplicate case for multi-targeting, or just squiggle the appropriate token - /// instead of the entire line. + /// This method is called by MSBuild when running vbc as a separate process, it does not get called + /// for normal VBCSCompiler compilations. + /// + /// The vbc process emits multi-line error messages and this method is called for every line of + /// output one at a time. This method must queue up the messages and re-hydrate them back into the + /// original vbc structure such that we can call + /// with the complete error message. /// - /// A single line from the STDOUT of the vbc compiler - /// High,Low,Normal protected override void LogEventsFromTextOutput(string singleLine, MessageImportance messageImportance) { // We can return immediately if this was not called by the out of proc compiler From 4469be043659f36ce1924fa6f91e86bdb352bd00 Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Wed, 17 Feb 2021 11:18:15 -0800 Subject: [PATCH 05/13] Structured server error messages This change adds structured messages to the binlog about the behavior of the compiler server. These messages will help users, our own developers and automation understand the behavior of the compiler server within a build. --- .../Core/CommandLine/BuildProtocol.cs | 30 ++- .../Core/MSBuildTask/ManagedCompiler.cs | 178 +++++++++++------- .../AnalyzerConsistencyChecker.cs | 31 ++- .../VBCSCompiler/CompilerRequestHandler.cs | 9 +- .../VBCSCompilerServerTests.cs | 3 +- 5 files changed, 168 insertions(+), 83 deletions(-) diff --git a/src/Compilers/Core/CommandLine/BuildProtocol.cs b/src/Compilers/Core/CommandLine/BuildProtocol.cs index 5bc507533ca63..85ff232610709 100644 --- a/src/Compilers/Core/CommandLine/BuildProtocol.cs +++ b/src/Compilers/Core/CommandLine/BuildProtocol.cs @@ -350,7 +350,7 @@ await ReadAllAsync(stream, case ResponseType.IncorrectHash: return new IncorrectHashBuildResponse(); case ResponseType.AnalyzerInconsistency: - return new AnalyzerInconsistencyBuildResponse(); + return AnalyzerInconsistencyBuildResponse.Create(reader); case ResponseType.Shutdown: return ShutdownBuildResponse.Create(reader); case ResponseType.Rejected: @@ -455,11 +455,37 @@ internal sealed class AnalyzerInconsistencyBuildResponse : BuildResponse { public override ResponseType Type => ResponseType.AnalyzerInconsistency; + public ReadOnlyCollection ErrorMessages { get; } + + public AnalyzerInconsistencyBuildResponse(ReadOnlyCollection errorMessages) + { + ErrorMessages = errorMessages; + } + /// /// AnalyzerInconsistency has no body. /// /// - protected override void AddResponseBody(BinaryWriter writer) { } + protected override void AddResponseBody(BinaryWriter writer) + { + writer.Write(ErrorMessages.Count); + foreach (var message in ErrorMessages) + { + WriteLengthPrefixedString(writer, message); + } + } + + public static AnalyzerInconsistencyBuildResponse Create(BinaryReader reader) + { + var count = reader.ReadInt32(); + var list = new List(count); + for (var i = 0; i < count; i++) + { + list.Add(ReadLengthPrefixedString(reader) ?? ""); + } + + return new AnalyzerInconsistencyBuildResponse(new ReadOnlyCollection(list)); + } } internal sealed class RejectedBuildResponse : BuildResponse diff --git a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs index 0a02c851b469c..e396790f7b6c0 100644 --- a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs +++ b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs @@ -24,6 +24,31 @@ namespace Microsoft.CodeAnalysis.BuildTasks /// public abstract class ManagedCompiler : ManagedToolTask { + private enum CompilationKind + { + /// + /// Commpilation occured using the command line tool by normal processes, typically because + /// the customer opt'd out of the compiler server + /// + Tool, + + /// + /// Compilation occurred using the command line tool because the server was unable to complete + /// the request + /// + ToolFallback, + + /// + /// Compilation occured in the compiler server process + /// + Server, + + /// + /// Fatal error caused compilation to not even occur. + /// + FatalError, + } + private CancellationTokenSource? _sharedCompileCts; internal readonly PropertyDictionary _store = new PropertyDictionary(); @@ -476,6 +501,7 @@ protected override int ExecuteTool(string pathToTool, string responseFileCommand try { + using var logger = new CompilerServerLogger(); string workingDir = CurrentDirectoryToUse(); string? tempDir = BuildServerConnection.GetTempPath(workingDir); @@ -483,62 +509,44 @@ protected override int ExecuteTool(string pathToTool, string responseFileCommand HasToolBeenOverridden || !BuildServerConnection.IsCompilerServerSupported) { + LogCompilationMessage(logger, CompilationKind.Tool, $"using command line tool by design {pathToTool}"); return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); } - using var logger = new CompilerServerLogger(); - using (_sharedCompileCts = new CancellationTokenSource()) - { - - logger.Log($"CommandLine = '{commandLineCommands}'"); - logger.Log($"BuildResponseFile = '{responseFileCommands}'"); + _sharedCompileCts = new CancellationTokenSource(); + logger.Log($"CommandLine = '{commandLineCommands}'"); + logger.Log($"BuildResponseFile = '{responseFileCommands}'"); - var clientDir = Path.GetDirectoryName(PathToManagedTool); - if (clientDir is null || tempDir is null) - { - return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); - } - - // Note: we can't change the "tool path" printed to the console when we run - // the Csc/Vbc task since MSBuild logs it for us before we get here. Instead, - // we'll just print our own message that contains the real client location - Log.LogMessage(ErrorString.UsingSharedCompilation, clientDir); - - var buildPaths = new BuildPathsAlt( - clientDir: clientDir, - workingDir: workingDir, - // MSBuild doesn't need the .NET SDK directory - sdkDir: null, - tempDir: tempDir); - - // Note: using ToolArguments here (the property) since - // commandLineCommands (the parameter) may have been mucked with - // (to support using the dotnet cli) - var responseTask = BuildServerConnection.RunServerCompilationAsync( - Language, - RoslynString.IsNullOrEmpty(SharedCompilationId) ? null : SharedCompilationId, - GetArguments(ToolArguments, responseFileCommands).ToList(), - buildPaths, - keepAlive: null, - libEnvVariable: LibDirectoryToUse(), - logger: logger, - cancellationToken: _sharedCompileCts.Token); - - responseTask.Wait(_sharedCompileCts.Token); - - var response = responseTask.Result; - if (response != null) - { - ExitCode = HandleResponse(response, pathToTool, responseFileCommands, commandLineCommands, logger); - } - else - { - logger.LogError($"Server compilation failed, falling back to {pathToTool}"); - Log.LogMessage(ErrorString.SharedCompilationFallback, pathToTool); - - ExitCode = base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); - } + var clientDir = Path.GetDirectoryName(PathToManagedTool); + if (clientDir is null || tempDir is null) + { + LogCompilationMessage(logger, CompilationKind.Tool, $"using command line tool because we can't find client directory {PathToManagedTool}"); + return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); } + + var buildPaths = new BuildPathsAlt( + clientDir: clientDir, + workingDir: workingDir, + // MSBuild doesn't need the .NET SDK directory + sdkDir: null, + tempDir: tempDir); + + // Note: using ToolArguments here (the property) since + // commandLineCommands (the parameter) may have been mucked with + // (to support using the dotnet cli) + var responseTask = BuildServerConnection.RunServerCompilationAsync( + Language, + RoslynString.IsNullOrEmpty(SharedCompilationId) ? null : SharedCompilationId, + GetArguments(ToolArguments, responseFileCommands).ToList(), + buildPaths, + keepAlive: null, + libEnvVariable: LibDirectoryToUse(), + logger: logger, + cancellationToken: _sharedCompileCts.Token); + + responseTask.Wait(_sharedCompileCts.Token); + + ExitCode = HandleResponse(responseTask.Result, pathToTool, responseFileCommands, commandLineCommands, logger); } catch (OperationCanceledException) { @@ -551,6 +559,11 @@ protected override int ExecuteTool(string pathToTool, string responseFileCommand util.LogErrorFromException(e, showStackTrace: true, showDetail: true, file: null); ExitCode = -1; } + finally + { + _sharedCompileCts?.Dispose(); + _sharedCompileCts = null; + } return ExitCode; } @@ -617,8 +630,14 @@ private string CurrentDirectoryToUse() /// Handle a response from the server, reporting messages and returning /// the appropriate exit code. /// - private int HandleResponse(BuildResponse response, string pathToTool, string responseFileCommands, string commandLineCommands, ICompilerServerLogger logger) + private int HandleResponse(BuildResponse? response, string pathToTool, string responseFileCommands, string commandLineCommands, ICompilerServerLogger logger) { + if (response is null) + { + LogCompilationMessage(logger, CompilationKind.ToolFallback, "Could not launch server"); + return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); + } + if (response.Type != BuildResponse.ResponseType.Completed) { ValidateBootstrapUtil.AddFailedServerConnection(response.Type, OutputAssembly?.ItemSpec); @@ -629,42 +648,32 @@ private int HandleResponse(BuildResponse response, string pathToTool, string res case BuildResponse.ResponseType.Completed: var completedResponse = (CompletedBuildResponse)response; LogCompilerOutput(completedResponse.Output, StandardOutputImportanceToUse); + LogCompilationMessage(logger, CompilationKind.Server, ""); return completedResponse.ReturnCode; case BuildResponse.ResponseType.MismatchedVersion: - logMessage("Roslyn compiler server reports different protocol version than build task.", isError: true); + LogCompilationMessage(logger, CompilationKind.FatalError, "server reports different protocol version than build task."); return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); case BuildResponse.ResponseType.IncorrectHash: - logMessage("Roslyn compiler server reports different hash version than build task.", isError: true); + LogCompilationMessage(logger, CompilationKind.FatalError, "server reports different hash version than build task."); return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); case BuildResponse.ResponseType.Rejected: var rejectedResponse = (RejectedBuildResponse)response; - logMessage($"Request rejected: {rejectedResponse.Reason}", isError: false); + LogCompilationMessage(logger, CompilationKind.ToolFallback, $"server rejected the request '{rejectedResponse.Reason}'"); return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); case BuildResponse.ResponseType.AnalyzerInconsistency: - logMessage($"Server rejected request due to analyzer inconsistency", isError: false); + var analyzerResponse = (AnalyzerInconsistencyBuildResponse)response; + var combinedMessage = string.Join(", ", analyzerResponse.ErrorMessages.ToArray()); + LogCompilationMessage(logger, CompilationKind.ToolFallback, $"server rejected the request due to analyzer / generator issues '{combinedMessage}'"); return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); default: - logMessage($"Received an unrecognized response from the server: {response.Type}", isError: true); + LogCompilationMessage(logger, CompilationKind.ToolFallback, $"server gave an unrecognized response"); return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); } - - void logMessage(string message, bool isError) - { - logger.LogError(message); - if (isError) - { - Log.LogError(message); - } - else - { - Log.LogMessage(MessageImportance.Low, message); - } - } } /// @@ -674,6 +683,35 @@ void logMessage(string message, bool isError) /// private protected abstract void LogCompilerOutput(string output, MessageImportance messageImportance); + /// + /// Used to log a message that should go into both the compiler server log as well as the MSBuild logs + /// + /// These are intended to be processed by automation in the binlog hence do not change the structure of + /// the messages here. + /// + private void LogCompilationMessage(ICompilerServerLogger logger, CompilationKind kind, string diagnostic) + { + var category = kind switch + { + CompilationKind.Server => "server", + CompilationKind.Tool => "tool", + CompilationKind.ToolFallback => "server failed", + CompilationKind.FatalError => "fatal error", + _ => throw new Exception($"Unexpected value {kind}"), + }; + + var message = $"CompilerServer: {category} - {diagnostic}"; + logger.LogError(message); + if (kind == CompilationKind.FatalError) + { + Log.LogError(message); + } + else + { + Log.LogMessage(message); + } + } + public string GenerateResponseFileContents() { return GenerateResponseFileCommands(); diff --git a/src/Compilers/Server/VBCSCompiler/AnalyzerConsistencyChecker.cs b/src/Compilers/Server/VBCSCompiler/AnalyzerConsistencyChecker.cs index 4641ff1634311..198e69168e987 100644 --- a/src/Compilers/Server/VBCSCompiler/AnalyzerConsistencyChecker.cs +++ b/src/Compilers/Server/VBCSCompiler/AnalyzerConsistencyChecker.cs @@ -10,6 +10,8 @@ using System.Reflection; using Roslyn.Utilities; using Microsoft.CodeAnalysis.CommandLine; +using System.Diagnostics.CodeAnalysis; +using Microsoft.CodeAnalysis.VisualBasic; namespace Microsoft.CodeAnalysis.CompilerServer { @@ -19,16 +21,26 @@ public static bool Check( string baseDirectory, IEnumerable analyzerReferences, IAnalyzerAssemblyLoader loader, - ICompilerServerLogger? logger = null) + ICompilerServerLogger? logger = null) => Check(baseDirectory, analyzerReferences, loader, logger, out var _); + + public static bool Check( + string baseDirectory, + IEnumerable analyzerReferences, + IAnalyzerAssemblyLoader loader, + ICompilerServerLogger? logger, + [NotNullWhen(false)] + out List? errorMessages) { try { logger?.Log("Begin Analyzer Consistency Check"); - return CheckCore(baseDirectory, analyzerReferences, loader, logger); + return CheckCore(baseDirectory, analyzerReferences, loader, logger, out errorMessages); } catch (Exception e) { logger?.LogException(e, "Analyzer Consistency Check"); + errorMessages = new List(); + errorMessages.Add(e.Message); return false; } finally @@ -41,8 +53,11 @@ private static bool CheckCore( string baseDirectory, IEnumerable analyzerReferences, IAnalyzerAssemblyLoader loader, - ICompilerServerLogger? logger) + ICompilerServerLogger? logger, + [NotNullWhen(false)] + out List? errorMessages) { + errorMessages = null; var resolvedPaths = new List(); foreach (var analyzerReference in analyzerReferences) @@ -84,12 +99,16 @@ private static bool CheckCore( if (resolvedPathMvid != loadedAssemblyMvid) { - logger?.LogError($"Analyzer assembly {resolvedPath} has MVID '{resolvedPathMvid}' but loaded assembly '{loadedAssembly.FullName}' has MVID '{loadedAssemblyMvid}'."); - return false; + var message = $"Analyzer assembly {resolvedPath} has MVID '{resolvedPathMvid}' but loaded assembly '{loadedAssembly.FullName}' has MVID '{loadedAssemblyMvid}'."; + if (errorMessages is null) + { + errorMessages = new List(); + } + errorMessages.Add(message); } } - return true; + return errorMessages == null; } } } diff --git a/src/Compilers/Server/VBCSCompiler/CompilerRequestHandler.cs b/src/Compilers/Server/VBCSCompiler/CompilerRequestHandler.cs index bd16c6a19e14d..49d14abe47b1d 100644 --- a/src/Compilers/Server/VBCSCompiler/CompilerRequestHandler.cs +++ b/src/Compilers/Server/VBCSCompiler/CompilerRequestHandler.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Collections.ObjectModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; @@ -66,9 +67,9 @@ internal CompilerServerHost(string clientDirectory, string sdkDirectory, ICompil Logger = logger; } - private bool CheckAnalyzers(string baseDirectory, ImmutableArray analyzers) + private bool CheckAnalyzers(string baseDirectory, ImmutableArray analyzers, [NotNullWhen(false)] out List? errorMessages) { - return AnalyzerConsistencyChecker.Check(baseDirectory, analyzers, AnalyzerAssemblyLoader, logger: Logger); + return AnalyzerConsistencyChecker.Check(baseDirectory, analyzers, AnalyzerAssemblyLoader, Logger, out errorMessages); } public bool TryCreateCompiler(RunRequest request, BuildPaths buildPaths, [NotNullWhen(true)] out CommonCompiler? compiler) @@ -126,9 +127,9 @@ Run Compilation } bool utf8output = compiler.Arguments.Utf8Output; - if (!CheckAnalyzers(request.WorkingDirectory, compiler.Arguments.AnalyzerReferences)) + if (!CheckAnalyzers(request.WorkingDirectory, compiler.Arguments.AnalyzerReferences, out List? errorMessages)) { - return new AnalyzerInconsistencyBuildResponse(); + return new AnalyzerInconsistencyBuildResponse(new ReadOnlyCollection(errorMessages)); } Logger.Log($"Begin {request.Language} compiler run"); diff --git a/src/Compilers/Server/VBCSCompilerTests/VBCSCompilerServerTests.cs b/src/Compilers/Server/VBCSCompilerTests/VBCSCompilerServerTests.cs index 42e0a9eb41c35..cebf329637ca4 100644 --- a/src/Compilers/Server/VBCSCompilerTests/VBCSCompilerServerTests.cs +++ b/src/Compilers/Server/VBCSCompilerTests/VBCSCompilerServerTests.cs @@ -9,6 +9,7 @@ using Roslyn.Test.Utilities; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Collections.Specialized; using System.IO; using System.IO.Pipes; @@ -390,7 +391,7 @@ public async Task AnalyzerInconsistencyShouldShutdown() { var compilerServerHost = new TestableCompilerServerHost(delegate { - return new AnalyzerInconsistencyBuildResponse(); + return new AnalyzerInconsistencyBuildResponse(new ReadOnlyCollection(Array.Empty())); }); using var serverData = await ServerUtil.CreateServer(Logger, compilerServerHost: compilerServerHost).ConfigureAwait(false); From 9acd89794c4a79b50a8270e82b603ac5d1668719 Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Thu, 18 Feb 2021 10:30:45 -0800 Subject: [PATCH 06/13] Better log message --- src/Compilers/Core/MSBuildTask/ManagedCompiler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs index e396790f7b6c0..6491bf8542e1a 100644 --- a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs +++ b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs @@ -648,7 +648,7 @@ private int HandleResponse(BuildResponse? response, string pathToTool, string re case BuildResponse.ResponseType.Completed: var completedResponse = (CompletedBuildResponse)response; LogCompilerOutput(completedResponse.Output, StandardOutputImportanceToUse); - LogCompilationMessage(logger, CompilationKind.Server, ""); + LogCompilationMessage(logger, CompilationKind.Server, "server processed compilation"); return completedResponse.ReturnCode; case BuildResponse.ResponseType.MismatchedVersion: From 3ee164faefff4992d90e2f084f3185f2dd6d1a4a Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Thu, 18 Feb 2021 20:53:13 -0800 Subject: [PATCH 07/13] Avoid capture allocation in AnalyzerFileReference.GetSupportedLanguages --- .../DiagnosticAnalyzer/AnalyzerFileReference.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerFileReference.cs b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerFileReference.cs index 46d1b3ed487f7..f16e5b6d9e7f1 100644 --- a/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerFileReference.cs +++ b/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerFileReference.cs @@ -243,20 +243,28 @@ from supportedLanguage in supportedLanguages private static IEnumerable GetSupportedLanguages(TypeDefinition typeDef, PEModule peModule, Type attributeType, AttributeLanguagesFunc languagesFunc) { + IEnumerable? result = null; foreach (CustomAttributeHandle customAttrHandle in typeDef.GetCustomAttributes()) { if (peModule.IsTargetAttribute(customAttrHandle, attributeType.Namespace!, attributeType.Name, ctor: out _)) { - IEnumerable? attributeSupportedLanguages = languagesFunc(peModule, customAttrHandle); - if (attributeSupportedLanguages != null) + if (languagesFunc(peModule, customAttrHandle) is { } attributeSupportedLanguages) { - foreach (string item in attributeSupportedLanguages) + if (result is null) { - yield return item; + result = attributeSupportedLanguages; + } + else + { + // This is a slow path, but only occurs if a single type has multiple + // DiagnosticAnalyzerAttribute instances applied to it. + result = result.Concat(attributeSupportedLanguages); } } } } + + return result ?? SpecializedCollections.EmptyEnumerable(); } private static IEnumerable GetDiagnosticsAnalyzerSupportedLanguages(PEModule peModule, CustomAttributeHandle customAttrHandle) From 4aed0dbf37017acc8486876ffe89d777d03cdb2b Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Fri, 19 Feb 2021 08:57:55 -0800 Subject: [PATCH 08/13] Apply suggestions from code review Co-authored-by: Sam Harwell --- src/Compilers/Core/MSBuildTask/ManagedCompiler.cs | 10 +++++----- .../Server/VBCSCompiler/AnalyzerConsistencyChecker.cs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs index 6491bf8542e1a..3cbeb6eb0ce47 100644 --- a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs +++ b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs @@ -509,7 +509,7 @@ protected override int ExecuteTool(string pathToTool, string responseFileCommand HasToolBeenOverridden || !BuildServerConnection.IsCompilerServerSupported) { - LogCompilationMessage(logger, CompilationKind.Tool, $"using command line tool by design {pathToTool}"); + LogCompilationMessage(logger, CompilationKind.Tool, $"using command line tool by design '{pathToTool}'"); return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); } @@ -520,7 +520,7 @@ protected override int ExecuteTool(string pathToTool, string responseFileCommand var clientDir = Path.GetDirectoryName(PathToManagedTool); if (clientDir is null || tempDir is null) { - LogCompilationMessage(logger, CompilationKind.Tool, $"using command line tool because we can't find client directory {PathToManagedTool}"); + LogCompilationMessage(logger, CompilationKind.Tool, $"using command line tool because we could not find client directory '{PathToManagedTool}'"); return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); } @@ -634,7 +634,7 @@ private int HandleResponse(BuildResponse? response, string pathToTool, string re { if (response is null) { - LogCompilationMessage(logger, CompilationKind.ToolFallback, "Could not launch server"); + LogCompilationMessage(logger, CompilationKind.ToolFallback, "could not launch server"); return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); } @@ -652,11 +652,11 @@ private int HandleResponse(BuildResponse? response, string pathToTool, string re return completedResponse.ReturnCode; case BuildResponse.ResponseType.MismatchedVersion: - LogCompilationMessage(logger, CompilationKind.FatalError, "server reports different protocol version than build task."); + LogCompilationMessage(logger, CompilationKind.FatalError, "server reports different protocol version than build task"); return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); case BuildResponse.ResponseType.IncorrectHash: - LogCompilationMessage(logger, CompilationKind.FatalError, "server reports different hash version than build task."); + LogCompilationMessage(logger, CompilationKind.FatalError, "server reports different hash version than build task"); return base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands); case BuildResponse.ResponseType.Rejected: diff --git a/src/Compilers/Server/VBCSCompiler/AnalyzerConsistencyChecker.cs b/src/Compilers/Server/VBCSCompiler/AnalyzerConsistencyChecker.cs index 198e69168e987..9996e42fe8021 100644 --- a/src/Compilers/Server/VBCSCompiler/AnalyzerConsistencyChecker.cs +++ b/src/Compilers/Server/VBCSCompiler/AnalyzerConsistencyChecker.cs @@ -99,7 +99,7 @@ private static bool CheckCore( if (resolvedPathMvid != loadedAssemblyMvid) { - var message = $"Analyzer assembly {resolvedPath} has MVID '{resolvedPathMvid}' but loaded assembly '{loadedAssembly.FullName}' has MVID '{loadedAssemblyMvid}'."; + var message = $"analyzer assembly '{resolvedPath}' has MVID '{resolvedPathMvid}' but loaded assembly '{loadedAssembly.FullName}' has MVID '{loadedAssemblyMvid}'"; if (errorMessages is null) { errorMessages = new List(); From be8c0569b42ac0d4574cb0911fea25ad73ff0ba7 Mon Sep 17 00:00:00 2001 From: Youssef Victor <31348972+Youssef1313@users.noreply.github.com> Date: Fri, 19 Feb 2021 21:26:57 +0200 Subject: [PATCH 09/13] Check reference equality for strongly-typed equals in records (#51149) --- .../AnonymousTypeMethodBodySynthesizer.cs | 7 +- .../Records/SynthesizedRecordEquals.cs | 6 +- .../Test/Semantic/Semantics/RecordTests.cs | 705 +++++++++++------- .../Symbols/AnonymousTypesSymbolTests.cs | 130 ++-- .../Test/Symbol/Symbols/Source/RecordTests.cs | 372 ++++----- .../AnonymousTypeSyntheticMethods.vb | 10 +- .../CodeGen/AnonymousTypesCodeGenTests.vb | 97 +-- 7 files changed, 758 insertions(+), 569 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Compiler/AnonymousTypeMethodBodySynthesizer.cs b/src/Compilers/CSharp/Portable/Compiler/AnonymousTypeMethodBodySynthesizer.cs index 4b67ad2d8ed1b..9d9fac748c464 100644 --- a/src/Compilers/CSharp/Portable/Compiler/AnonymousTypeMethodBodySynthesizer.cs +++ b/src/Compilers/CSharp/Portable/Compiler/AnonymousTypeMethodBodySynthesizer.cs @@ -102,10 +102,10 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState, // // { // $anonymous$ local = value as $anonymous$; - // return local != null + // return (object)local == this || (local != null // && System.Collections.Generic.EqualityComparer.Default.Equals(this.backingFld_1, local.backingFld_1) // ... - // && System.Collections.Generic.EqualityComparer.Default.Equals(this.backingFld_N, local.backingFld_N); + // && System.Collections.Generic.EqualityComparer.Default.Equals(this.backingFld_N, local.backingFld_N)); // } // Type and type expression @@ -137,6 +137,9 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState, fields.Free(); } + // Compare references + retExpression = F.LogicalOr(F.ObjectEqual(F.This(), boundLocal), retExpression); + // Final return statement BoundStatement retStatement = F.Return(retExpression); diff --git a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEquals.cs b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEquals.cs index 7f21860a8aeb7..81e8b3bbb1961 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEquals.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Synthesized/Records/SynthesizedRecordEquals.cs @@ -115,8 +115,8 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState, // delegate to: // // virtual bool Equals(Derived other) => - // base.Equals((Base)other) && - // field1 == other.field1 && ... && fieldN == other.fieldN; + // (object)other == this || (base.Equals((Base)other) && + // field1 == other.field1 && ... && fieldN == other.fieldN); retExpr = F.Call( F.Base(baseEquals.ContainingType), baseEquals, @@ -155,7 +155,7 @@ internal override void GenerateMethodBody(TypeCompilationState compilationState, } fields.Free(); - + retExpr = F.LogicalOr(F.ObjectEqual(F.This(), other), retExpr); F.CloseMethod(F.Block(F.Return(retExpr))); } catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs index 93f403b162577..f325b277f8157 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs @@ -11025,18 +11025,23 @@ .maxstack 2 }"); verifier.VerifyIL("A.Equals(A)", @"{ - // Code size 23 (0x17) + // Code size 29 (0x1d) .maxstack 2 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_0015 - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type A.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type A.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: ret - IL_0015: ldc.i4.0 - IL_0016: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_001b + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0019 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type A.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type A.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: ret + IL_0019: ldc.i4.0 + IL_001a: ret + IL_001b: ldc.i4.1 + IL_001c: ret }"); verifier.VerifyIL("A.GetHashCode()", @"{ @@ -11097,28 +11102,33 @@ .maxstack 2 }"); verifier.VerifyIL("B.Equals(B)", @"{ - // Code size 58 (0x3a) + // Code size 64 (0x40) .maxstack 3 IL_0000: ldarg.0 IL_0001: ldarg.1 - IL_0002: call ""bool A.Equals(A)"" - IL_0007: brfalse.s IL_0038 - IL_0009: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_000e: ldarg.0 - IL_000f: ldfld ""object B.k__BackingField"" - IL_0014: ldarg.1 - IL_0015: ldfld ""object B.k__BackingField"" - IL_001a: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(object, object)"" - IL_001f: brfalse.s IL_0038 - IL_0021: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_0026: ldarg.0 - IL_0027: ldfld ""object B.k__BackingField"" - IL_002c: ldarg.1 - IL_002d: ldfld ""object B.k__BackingField"" - IL_0032: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(object, object)"" - IL_0037: ret - IL_0038: ldc.i4.0 - IL_0039: ret + IL_0002: beq.s IL_003e + IL_0004: ldarg.0 + IL_0005: ldarg.1 + IL_0006: call ""bool A.Equals(A)"" + IL_000b: brfalse.s IL_003c + IL_000d: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_0012: ldarg.0 + IL_0013: ldfld ""object B.k__BackingField"" + IL_0018: ldarg.1 + IL_0019: ldfld ""object B.k__BackingField"" + IL_001e: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(object, object)"" + IL_0023: brfalse.s IL_003c + IL_0025: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_002a: ldarg.0 + IL_002b: ldfld ""object B.k__BackingField"" + IL_0030: ldarg.1 + IL_0031: ldfld ""object B.k__BackingField"" + IL_0036: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(object, object)"" + IL_003b: ret + IL_003c: ldc.i4.0 + IL_003d: ret + IL_003e: ldc.i4.1 + IL_003f: ret }"); verifier.VerifyIL("B.GetHashCode()", @"{ @@ -11208,18 +11218,23 @@ .maxstack 1 }"); verifier.VerifyIL("A.Equals(A)", @"{ - // Code size 23 (0x17) + // Code size 29 (0x1d) .maxstack 2 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_0015 - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type A.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type A.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: ret - IL_0015: ldc.i4.0 - IL_0016: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_001b + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0019 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type A.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type A.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: ret + IL_0019: ldc.i4.0 + IL_001a: ret + IL_001b: ldc.i4.1 + IL_001c: ret }"); verifier.VerifyIL("A.GetHashCode()", @"{ @@ -11250,12 +11265,17 @@ .maxstack 2 }"); verifier.VerifyIL("B.Equals(B)", @"{ - // Code size 8 (0x8) + // Code size 14 (0xe) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 - IL_0002: call ""bool A.Equals(A)"" - IL_0007: ret + IL_0002: beq.s IL_000c + IL_0004: ldarg.0 + IL_0005: ldarg.1 + IL_0006: call ""bool A.Equals(A)"" + IL_000b: ret + IL_000c: ldc.i4.1 + IL_000d: ret }"); verifier.VerifyIL("B.GetHashCode()", @"{ @@ -11312,28 +11332,33 @@ .maxstack 2 }"); verifier.VerifyIL("C.Equals(C)", @"{ - // Code size 58 (0x3a) + // Code size 64 (0x40) .maxstack 3 IL_0000: ldarg.0 IL_0001: ldarg.1 - IL_0002: call ""bool B.Equals(B)"" - IL_0007: brfalse.s IL_0038 - IL_0009: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_000e: ldarg.0 - IL_000f: ldfld ""object C.k__BackingField"" - IL_0014: ldarg.1 - IL_0015: ldfld ""object C.k__BackingField"" - IL_001a: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(object, object)"" - IL_001f: brfalse.s IL_0038 - IL_0021: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_0026: ldarg.0 - IL_0027: ldfld ""object C.k__BackingField"" - IL_002c: ldarg.1 - IL_002d: ldfld ""object C.k__BackingField"" - IL_0032: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(object, object)"" - IL_0037: ret - IL_0038: ldc.i4.0 - IL_0039: ret + IL_0002: beq.s IL_003e + IL_0004: ldarg.0 + IL_0005: ldarg.1 + IL_0006: call ""bool B.Equals(B)"" + IL_000b: brfalse.s IL_003c + IL_000d: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_0012: ldarg.0 + IL_0013: ldfld ""object C.k__BackingField"" + IL_0018: ldarg.1 + IL_0019: ldfld ""object C.k__BackingField"" + IL_001e: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(object, object)"" + IL_0023: brfalse.s IL_003c + IL_0025: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_002a: ldarg.0 + IL_002b: ldfld ""object C.k__BackingField"" + IL_0030: ldarg.1 + IL_0031: ldfld ""object C.k__BackingField"" + IL_0036: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(object, object)"" + IL_003b: ret + IL_003c: ldc.i4.0 + IL_003d: ret + IL_003e: ldc.i4.1 + IL_003f: ret }"); verifier.VerifyIL("C.GetHashCode()", @"{ @@ -11456,25 +11481,30 @@ .maxstack 2 }"); verifier.VerifyIL("A.Equals(A)", @"{ - // Code size 47 (0x2f) + // Code size 53 (0x35) .maxstack 3 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_002d - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type A.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type A.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: brfalse.s IL_002d - IL_0016: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_001b: ldarg.0 - IL_001c: ldfld ""object A.k__BackingField"" - IL_0021: ldarg.1 - IL_0022: ldfld ""object A.k__BackingField"" - IL_0027: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(object, object)"" - IL_002c: ret - IL_002d: ldc.i4.0 - IL_002e: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_0033 + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0031 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type A.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type A.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: brfalse.s IL_0031 + IL_001a: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_001f: ldarg.0 + IL_0020: ldfld ""object A.k__BackingField"" + IL_0025: ldarg.1 + IL_0026: ldfld ""object A.k__BackingField"" + IL_002b: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(object, object)"" + IL_0030: ret + IL_0031: ldc.i4.0 + IL_0032: ret + IL_0033: ldc.i4.1 + IL_0034: ret }"); verifier.VerifyIL("A.GetHashCode()", @"{ @@ -11528,12 +11558,17 @@ .maxstack 2 }"); verifier.VerifyIL("B.Equals(B)", @"{ - // Code size 8 (0x8) + // Code size 14 (0xe) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 - IL_0002: call ""bool A.Equals(A)"" - IL_0007: ret + IL_0002: beq.s IL_000c + IL_0004: ldarg.0 + IL_0005: ldarg.1 + IL_0006: call ""bool A.Equals(A)"" + IL_000b: ret + IL_000c: ldc.i4.1 + IL_000d: ret }"); verifier.VerifyIL("B.GetHashCode()", @"{ @@ -11592,28 +11627,33 @@ .maxstack 2 }"); verifier.VerifyIL("C.Equals(C)", @"{ - // Code size 58 (0x3a) + // Code size 64 (0x40) .maxstack 3 IL_0000: ldarg.0 IL_0001: ldarg.1 - IL_0002: call ""bool B.Equals(B)"" - IL_0007: brfalse.s IL_0038 - IL_0009: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_000e: ldarg.0 - IL_000f: ldfld ""object C.k__BackingField"" - IL_0014: ldarg.1 - IL_0015: ldfld ""object C.k__BackingField"" - IL_001a: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(object, object)"" - IL_001f: brfalse.s IL_0038 - IL_0021: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_0026: ldarg.0 - IL_0027: ldfld ""object C.k__BackingField"" - IL_002c: ldarg.1 - IL_002d: ldfld ""object C.k__BackingField"" - IL_0032: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(object, object)"" - IL_0037: ret - IL_0038: ldc.i4.0 - IL_0039: ret + IL_0002: beq.s IL_003e + IL_0004: ldarg.0 + IL_0005: ldarg.1 + IL_0006: call ""bool B.Equals(B)"" + IL_000b: brfalse.s IL_003c + IL_000d: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_0012: ldarg.0 + IL_0013: ldfld ""object C.k__BackingField"" + IL_0018: ldarg.1 + IL_0019: ldfld ""object C.k__BackingField"" + IL_001e: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(object, object)"" + IL_0023: brfalse.s IL_003c + IL_0025: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_002a: ldarg.0 + IL_002b: ldfld ""object C.k__BackingField"" + IL_0030: ldarg.1 + IL_0031: ldfld ""object C.k__BackingField"" + IL_0036: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(object, object)"" + IL_003b: ret + IL_003c: ldc.i4.0 + IL_003d: ret + IL_003e: ldc.i4.1 + IL_003f: ret }"); verifier.VerifyIL("C.GetHashCode()", @"{ @@ -22023,18 +22063,23 @@ static void Main() verifier.VerifyIL("C.Equals(C)", @"{ - // Code size 23 (0x17) + // Code size 29 (0x1d) .maxstack 2 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_0015 - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type C.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type C.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: ret - IL_0015: ldc.i4.0 - IL_0016: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_001b + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0019 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type C.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type C.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: ret + IL_0019: ldc.i4.0 + IL_001a: ret + IL_001b: ldc.i4.1 + IL_001c: ret }"); verifier.VerifyIL("C.Equals(object)", @"{ @@ -22087,25 +22132,30 @@ static void Main() verifier.VerifyIL("C.Equals(C)", @"{ - // Code size 47 (0x2f) + // Code size 53 (0x35) .maxstack 3 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_002d - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type C.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type C.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: brfalse.s IL_002d - IL_0016: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_001b: ldarg.0 - IL_001c: ldfld ""int C._id"" - IL_0021: ldarg.1 - IL_0022: ldfld ""int C._id"" - IL_0027: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_002c: ret - IL_002d: ldc.i4.0 - IL_002e: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_0033 + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0031 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type C.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type C.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: brfalse.s IL_0031 + IL_001a: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_001f: ldarg.0 + IL_0020: ldfld ""int C._id"" + IL_0025: ldarg.1 + IL_0026: ldfld ""int C._id"" + IL_002b: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0030: ret + IL_0031: ldc.i4.0 + IL_0032: ret + IL_0033: ldc.i4.1 + IL_0034: ret }"); verifier.VerifyIL("C.GetHashCode()", @"{ @@ -22184,36 +22234,46 @@ static void Main() verifier.VerifyIL("A.Equals(A)", @"{ - // Code size 23 (0x17) + // Code size 29 (0x1d) .maxstack 2 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_0015 - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type A.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type A.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: ret - IL_0015: ldc.i4.0 - IL_0016: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_001b + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0019 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type A.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type A.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: ret + IL_0019: ldc.i4.0 + IL_001a: ret + IL_001b: ldc.i4.1 + IL_001c: ret }"); verifier.VerifyIL("B1.Equals(B1)", @"{ - // Code size 34 (0x22) + // Code size 40 (0x28) .maxstack 3 IL_0000: ldarg.0 IL_0001: ldarg.1 - IL_0002: call ""bool A.Equals(A)"" - IL_0007: brfalse.s IL_0020 - IL_0009: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_000e: ldarg.0 - IL_000f: ldfld ""int B1.

k__BackingField"" - IL_0014: ldarg.1 - IL_0015: ldfld ""int B1.

k__BackingField"" - IL_001a: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_001f: ret - IL_0020: ldc.i4.0 - IL_0021: ret + IL_0002: beq.s IL_0026 + IL_0004: ldarg.0 + IL_0005: ldarg.1 + IL_0006: call ""bool A.Equals(A)"" + IL_000b: brfalse.s IL_0024 + IL_000d: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_0012: ldarg.0 + IL_0013: ldfld ""int B1.

k__BackingField"" + IL_0018: ldarg.1 + IL_0019: ldfld ""int B1.

k__BackingField"" + IL_001e: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0023: ret + IL_0024: ldc.i4.0 + IL_0025: ret + IL_0026: ldc.i4.1 + IL_0027: ret }"); verifier.VerifyIL("B1.GetHashCode()", @"{ @@ -22292,34 +22352,44 @@ static void Main() verifier.VerifyIL("A.Equals(A)", @"{ - // Code size 47 (0x2f) + // Code size 53 (0x35) .maxstack 3 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_002d - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type A.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type A.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: brfalse.s IL_002d - IL_0016: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_001b: ldarg.0 - IL_001c: ldfld ""int A.

k__BackingField"" - IL_0021: ldarg.1 - IL_0022: ldfld ""int A.

k__BackingField"" - IL_0027: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_002c: ret - IL_002d: ldc.i4.0 - IL_002e: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_0033 + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0031 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type A.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type A.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: brfalse.s IL_0031 + IL_001a: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_001f: ldarg.0 + IL_0020: ldfld ""int A.

k__BackingField"" + IL_0025: ldarg.1 + IL_0026: ldfld ""int A.

k__BackingField"" + IL_002b: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0030: ret + IL_0031: ldc.i4.0 + IL_0032: ret + IL_0033: ldc.i4.1 + IL_0034: ret }"); verifier.VerifyIL("B1.Equals(B1)", @"{ - // Code size 8 (0x8) + // Code size 14 (0xe) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 - IL_0002: call ""bool A.Equals(A)"" - IL_0007: ret + IL_0002: beq.s IL_000c + IL_0004: ldarg.0 + IL_0005: ldarg.1 + IL_0006: call ""bool A.Equals(A)"" + IL_000b: ret + IL_000c: ldc.i4.1 + IL_000d: ret }"); verifier.VerifyIL("B1.GetHashCode()", @"{ @@ -22393,27 +22463,37 @@ static void Main() verifier.VerifyIL("A.Equals(A)", @"{ - // Code size 23 (0x17) + // Code size 29 (0x1d) .maxstack 2 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_0015 - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type A.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type A.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: ret - IL_0015: ldc.i4.0 - IL_0016: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_001b + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0019 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type A.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type A.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: ret + IL_0019: ldc.i4.0 + IL_001a: ret + IL_001b: ldc.i4.1 + IL_001c: ret }"); verifier.VerifyIL("C.Equals(C)", @"{ - // Code size 8 (0x8) + // Code size 14 (0xe) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 - IL_0002: call ""bool B.Equals(B)"" - IL_0007: ret + IL_0002: beq.s IL_000c + IL_0004: ldarg.0 + IL_0005: ldarg.1 + IL_0006: call ""bool B.Equals(B)"" + IL_000b: ret + IL_000c: ldc.i4.1 + IL_000d: ret }"); } @@ -22495,18 +22575,23 @@ static void Main() verifier.VerifyIL("A.Equals(A)", @"{ - // Code size 23 (0x17) + // Code size 29 (0x1d) .maxstack 2 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_0015 - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type A.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type A.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: ret - IL_0015: ldc.i4.0 - IL_0016: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_001b + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0019 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type A.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type A.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: ret + IL_0019: ldc.i4.0 + IL_001a: ret + IL_001b: ldc.i4.1 + IL_001c: ret }"); verifier.VerifyIL("B.Equals(A)", @"{ @@ -22528,12 +22613,17 @@ .maxstack 2 }"); verifier.VerifyIL("C.Equals(C)", @"{ - // Code size 8 (0x8) + // Code size 14 (0xe) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 - IL_0002: call ""bool B.Equals(B)"" - IL_0007: ret + IL_0002: beq.s IL_000c + IL_0004: ldarg.0 + IL_0005: ldarg.1 + IL_0006: call ""bool B.Equals(B)"" + IL_000b: ret + IL_000c: ldc.i4.1 + IL_000d: ret }"); VerifyVirtualMethod(comp.GetMember("A.get_EqualityContract"), isOverride: false); @@ -22681,44 +22771,54 @@ static void Main() verifier.VerifyIL("A.Equals(A)", @"{ - // Code size 47 (0x2f) + // Code size 53 (0x35) .maxstack 3 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_002d - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type A.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type A.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: brfalse.s IL_002d - IL_0016: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_001b: ldarg.0 - IL_001c: ldfld ""int A.k__BackingField"" - IL_0021: ldarg.1 - IL_0022: ldfld ""int A.k__BackingField"" - IL_0027: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_002c: ret - IL_002d: ldc.i4.0 - IL_002e: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_0033 + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0031 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type A.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type A.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: brfalse.s IL_0031 + IL_001a: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_001f: ldarg.0 + IL_0020: ldfld ""int A.k__BackingField"" + IL_0025: ldarg.1 + IL_0026: ldfld ""int A.k__BackingField"" + IL_002b: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0030: ret + IL_0031: ldc.i4.0 + IL_0032: ret + IL_0033: ldc.i4.1 + IL_0034: ret }"); // https://github.com/dotnet/roslyn/issues/44895: C.Equals() should compare B.Y. verifier.VerifyIL("C.Equals(C)", @"{ - // Code size 34 (0x22) + // Code size 40 (0x28) .maxstack 3 IL_0000: ldarg.0 IL_0001: ldarg.1 - IL_0002: call ""bool B.Equals(B)"" - IL_0007: brfalse.s IL_0020 - IL_0009: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_000e: ldarg.0 - IL_000f: ldfld ""int C.k__BackingField"" - IL_0014: ldarg.1 - IL_0015: ldfld ""int C.k__BackingField"" - IL_001a: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_001f: ret - IL_0020: ldc.i4.0 - IL_0021: ret + IL_0002: beq.s IL_0026 + IL_0004: ldarg.0 + IL_0005: ldarg.1 + IL_0006: call ""bool B.Equals(B)"" + IL_000b: brfalse.s IL_0024 + IL_000d: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_0012: ldarg.0 + IL_0013: ldfld ""int C.k__BackingField"" + IL_0018: ldarg.1 + IL_0019: ldfld ""int C.k__BackingField"" + IL_001e: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0023: ret + IL_0024: ldc.i4.0 + IL_0025: ret + IL_0026: ldc.i4.1 + IL_0027: ret }"); verifier.VerifyIL("C.GetHashCode()", @"{ @@ -22842,25 +22942,30 @@ static void Main() verifier.VerifyIL("A.Equals(A)", @"{ - // Code size 47 (0x2f) + // Code size 53 (0x35) .maxstack 3 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_002d - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type A.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type A.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: brfalse.s IL_002d - IL_0016: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_001b: ldarg.0 - IL_001c: ldfld ""int A.k__BackingField"" - IL_0021: ldarg.1 - IL_0022: ldfld ""int A.k__BackingField"" - IL_0027: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_002c: ret - IL_002d: ldc.i4.0 - IL_002e: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_0033 + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0031 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type A.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type A.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: brfalse.s IL_0031 + IL_001a: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_001f: ldarg.0 + IL_0020: ldfld ""int A.k__BackingField"" + IL_0025: ldarg.1 + IL_0026: ldfld ""int A.k__BackingField"" + IL_002b: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0030: ret + IL_0031: ldc.i4.0 + IL_0032: ret + IL_0033: ldc.i4.1 + IL_0034: ret }"); verifier.VerifyIL("B.Equals(A)", @"{ @@ -22873,21 +22978,26 @@ .maxstack 2 }"); verifier.VerifyIL("B.Equals(B)", @"{ - // Code size 34 (0x22) + // Code size 40 (0x28) .maxstack 3 IL_0000: ldarg.0 IL_0001: ldarg.1 - IL_0002: call ""bool A.Equals(A)"" - IL_0007: brfalse.s IL_0020 - IL_0009: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_000e: ldarg.0 - IL_000f: ldfld ""int B.k__BackingField"" - IL_0014: ldarg.1 - IL_0015: ldfld ""int B.k__BackingField"" - IL_001a: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_001f: ret - IL_0020: ldc.i4.0 - IL_0021: ret + IL_0002: beq.s IL_0026 + IL_0004: ldarg.0 + IL_0005: ldarg.1 + IL_0006: call ""bool A.Equals(A)"" + IL_000b: brfalse.s IL_0024 + IL_000d: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_0012: ldarg.0 + IL_0013: ldfld ""int B.k__BackingField"" + IL_0018: ldarg.1 + IL_0019: ldfld ""int B.k__BackingField"" + IL_001e: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0023: ret + IL_0024: ldc.i4.0 + IL_0025: ret + IL_0026: ldc.i4.1 + IL_0027: ret }"); verifier.VerifyIL("C.Equals(B)", @"{ @@ -22900,21 +23010,26 @@ .maxstack 2 }"); verifier.VerifyIL("C.Equals(C)", @"{ - // Code size 34 (0x22) + // Code size 40 (0x28) .maxstack 3 IL_0000: ldarg.0 IL_0001: ldarg.1 - IL_0002: call ""bool B.Equals(B)"" - IL_0007: brfalse.s IL_0020 - IL_0009: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_000e: ldarg.0 - IL_000f: ldfld ""int C.k__BackingField"" - IL_0014: ldarg.1 - IL_0015: ldfld ""int C.k__BackingField"" - IL_001a: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_001f: ret - IL_0020: ldc.i4.0 - IL_0021: ret + IL_0002: beq.s IL_0026 + IL_0004: ldarg.0 + IL_0005: ldarg.1 + IL_0006: call ""bool B.Equals(B)"" + IL_000b: brfalse.s IL_0024 + IL_000d: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_0012: ldarg.0 + IL_0013: ldfld ""int C.k__BackingField"" + IL_0018: ldarg.1 + IL_0019: ldfld ""int C.k__BackingField"" + IL_001e: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0023: ret + IL_0024: ldc.i4.0 + IL_0025: ret + IL_0026: ldc.i4.1 + IL_0027: ret }"); } @@ -23243,18 +23358,23 @@ static void Main() verifier.VerifyIL("A.Equals(A)", @"{ - // Code size 23 (0x17) + // Code size 29 (0x1d) .maxstack 2 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_0015 - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type A.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type A.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: ret - IL_0015: ldc.i4.0 - IL_0016: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_001b + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0019 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type A.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type A.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: ret + IL_0019: ldc.i4.0 + IL_001a: ret + IL_001b: ldc.i4.1 + IL_001c: ret }"); verifier.VerifyIL("B.Equals(A)", @"{ @@ -23267,12 +23387,17 @@ .maxstack 2 }"); verifier.VerifyIL("B.Equals(B)", @"{ - // Code size 8 (0x8) + // Code size 14 (0xe) .maxstack 2 IL_0000: ldarg.0 IL_0001: ldarg.1 - IL_0002: call ""bool A.Equals(A)"" - IL_0007: ret + IL_0002: beq.s IL_000c + IL_0004: ldarg.0 + IL_0005: ldarg.1 + IL_0006: call ""bool A.Equals(A)"" + IL_000b: ret + IL_000c: ldc.i4.1 + IL_000d: ret }"); } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/AnonymousTypesSymbolTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/AnonymousTypesSymbolTests.cs index a3f49fd205905..3f21385a75283 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/AnonymousTypesSymbolTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/AnonymousTypesSymbolTests.cs @@ -364,37 +364,42 @@ .maxstack 1 ).VerifyIL( "<>f__AnonymousType1<j__TPar, j__TPar, j__TPar>.Equals", @"{ - // Code size 83 (0x53) + // Code size 89 (0x59) .maxstack 3 .locals init (<>f__AnonymousType1<j__TPar, j__TPar, j__TPar> V_0) IL_0000: ldarg.1 IL_0001: isinst ""<>f__AnonymousType1<j__TPar, j__TPar, j__TPar>"" IL_0006: stloc.0 - IL_0007: ldloc.0 - IL_0008: brfalse.s IL_0051 - IL_000a: call ""System.Collections.Generic.EqualityComparer<j__TPar> System.Collections.Generic.EqualityComparer<j__TPar>.Default.get"" - IL_000f: ldarg.0 - IL_0010: ldfld ""j__TPar <>f__AnonymousType1<j__TPar, j__TPar, j__TPar>.i__Field"" - IL_0015: ldloc.0 - IL_0016: ldfld ""j__TPar <>f__AnonymousType1<j__TPar, j__TPar, j__TPar>.i__Field"" - IL_001b: callvirt ""bool System.Collections.Generic.EqualityComparer<j__TPar>.Equals(j__TPar, j__TPar)"" - IL_0020: brfalse.s IL_0051 - IL_0022: call ""System.Collections.Generic.EqualityComparer<j__TPar> System.Collections.Generic.EqualityComparer<j__TPar>.Default.get"" - IL_0027: ldarg.0 - IL_0028: ldfld ""j__TPar <>f__AnonymousType1<j__TPar, j__TPar, j__TPar>.i__Field"" - IL_002d: ldloc.0 - IL_002e: ldfld ""j__TPar <>f__AnonymousType1<j__TPar, j__TPar, j__TPar>.i__Field"" - IL_0033: callvirt ""bool System.Collections.Generic.EqualityComparer<j__TPar>.Equals(j__TPar, j__TPar)"" - IL_0038: brfalse.s IL_0051 - IL_003a: call ""System.Collections.Generic.EqualityComparer<j__TPar> System.Collections.Generic.EqualityComparer<j__TPar>.Default.get"" - IL_003f: ldarg.0 - IL_0040: ldfld ""j__TPar <>f__AnonymousType1<j__TPar, j__TPar, j__TPar>.i__Field"" - IL_0045: ldloc.0 - IL_0046: ldfld ""j__TPar <>f__AnonymousType1<j__TPar, j__TPar, j__TPar>.i__Field"" - IL_004b: callvirt ""bool System.Collections.Generic.EqualityComparer<j__TPar>.Equals(j__TPar, j__TPar)"" - IL_0050: ret - IL_0051: ldc.i4.0 - IL_0052: ret + IL_0007: ldarg.0 + IL_0008: ldloc.0 + IL_0009: beq.s IL_0057 + IL_000b: ldloc.0 + IL_000c: brfalse.s IL_0055 + IL_000e: call ""System.Collections.Generic.EqualityComparer<j__TPar> System.Collections.Generic.EqualityComparer<j__TPar>.Default.get"" + IL_0013: ldarg.0 + IL_0014: ldfld ""j__TPar <>f__AnonymousType1<j__TPar, j__TPar, j__TPar>.i__Field"" + IL_0019: ldloc.0 + IL_001a: ldfld ""j__TPar <>f__AnonymousType1<j__TPar, j__TPar, j__TPar>.i__Field"" + IL_001f: callvirt ""bool System.Collections.Generic.EqualityComparer<j__TPar>.Equals(j__TPar, j__TPar)"" + IL_0024: brfalse.s IL_0055 + IL_0026: call ""System.Collections.Generic.EqualityComparer<j__TPar> System.Collections.Generic.EqualityComparer<j__TPar>.Default.get"" + IL_002b: ldarg.0 + IL_002c: ldfld ""j__TPar <>f__AnonymousType1<j__TPar, j__TPar, j__TPar>.i__Field"" + IL_0031: ldloc.0 + IL_0032: ldfld ""j__TPar <>f__AnonymousType1<j__TPar, j__TPar, j__TPar>.i__Field"" + IL_0037: callvirt ""bool System.Collections.Generic.EqualityComparer<j__TPar>.Equals(j__TPar, j__TPar)"" + IL_003c: brfalse.s IL_0055 + IL_003e: call ""System.Collections.Generic.EqualityComparer<j__TPar> System.Collections.Generic.EqualityComparer<j__TPar>.Default.get"" + IL_0043: ldarg.0 + IL_0044: ldfld ""j__TPar <>f__AnonymousType1<j__TPar, j__TPar, j__TPar>.i__Field"" + IL_0049: ldloc.0 + IL_004a: ldfld ""j__TPar <>f__AnonymousType1<j__TPar, j__TPar, j__TPar>.i__Field"" + IL_004f: callvirt ""bool System.Collections.Generic.EqualityComparer<j__TPar>.Equals(j__TPar, j__TPar)"" + IL_0054: ret + IL_0055: ldc.i4.0 + IL_0056: ret + IL_0057: ldc.i4.1 + IL_0058: ret }" ).VerifyIL( "<>f__AnonymousType1<j__TPar, j__TPar, j__TPar>.GetHashCode", @@ -653,13 +658,21 @@ .maxstack 1 ).VerifyIL( "<>f__AnonymousType0.Equals", @"{ - // Code size 10 (0xa) + // Code size 18 (0x12) .maxstack 2 + .locals init (<>f__AnonymousType0 V_0) IL_0000: ldarg.1 IL_0001: isinst ""<>f__AnonymousType0"" - IL_0006: ldnull - IL_0007: cgt.un - IL_0009: ret + IL_0006: stloc.0 + IL_0007: ldarg.0 + IL_0008: ldloc.0 + IL_0009: beq.s IL_0010 + IL_000b: ldloc.0 + IL_000c: ldnull + IL_000d: cgt.un + IL_000f: ret + IL_0010: ldc.i4.1 + IL_0011: ret }" ).VerifyIL( "<>f__AnonymousType0.GetHashCode", @@ -789,37 +802,42 @@ .maxstack 2 ).VerifyIL( "<>f__AnonymousType0<j__TPar, j__TPar, j__TPar>.Equals", @"{ - // Code size 83 (0x53) + // Code size 89 (0x59) .maxstack 3 .locals init (<>f__AnonymousType0<j__TPar, j__TPar, j__TPar> V_0) IL_0000: ldarg.1 IL_0001: isinst ""<>f__AnonymousType0<j__TPar, j__TPar, j__TPar>"" IL_0006: stloc.0 - IL_0007: ldloc.0 - IL_0008: brfalse.s IL_0051 - IL_000a: call ""System.Collections.Generic.EqualityComparer<j__TPar> System.Collections.Generic.EqualityComparer<j__TPar>.Default.get"" - IL_000f: ldarg.0 - IL_0010: ldfld ""j__TPar <>f__AnonymousType0<j__TPar, j__TPar, j__TPar>.i__Field"" - IL_0015: ldloc.0 - IL_0016: ldfld ""j__TPar <>f__AnonymousType0<j__TPar, j__TPar, j__TPar>.i__Field"" - IL_001b: callvirt ""bool System.Collections.Generic.EqualityComparer<j__TPar>.Equals(j__TPar, j__TPar)"" - IL_0020: brfalse.s IL_0051 - IL_0022: call ""System.Collections.Generic.EqualityComparer<j__TPar> System.Collections.Generic.EqualityComparer<j__TPar>.Default.get"" - IL_0027: ldarg.0 - IL_0028: ldfld ""j__TPar <>f__AnonymousType0<j__TPar, j__TPar, j__TPar>.i__Field"" - IL_002d: ldloc.0 - IL_002e: ldfld ""j__TPar <>f__AnonymousType0<j__TPar, j__TPar, j__TPar>.i__Field"" - IL_0033: callvirt ""bool System.Collections.Generic.EqualityComparer<j__TPar>.Equals(j__TPar, j__TPar)"" - IL_0038: brfalse.s IL_0051 - IL_003a: call ""System.Collections.Generic.EqualityComparer<j__TPar> System.Collections.Generic.EqualityComparer<j__TPar>.Default.get"" - IL_003f: ldarg.0 - IL_0040: ldfld ""j__TPar <>f__AnonymousType0<j__TPar, j__TPar, j__TPar>.i__Field"" - IL_0045: ldloc.0 - IL_0046: ldfld ""j__TPar <>f__AnonymousType0<j__TPar, j__TPar, j__TPar>.i__Field"" - IL_004b: callvirt ""bool System.Collections.Generic.EqualityComparer<j__TPar>.Equals(j__TPar, j__TPar)"" - IL_0050: ret - IL_0051: ldc.i4.0 - IL_0052: ret + IL_0007: ldarg.0 + IL_0008: ldloc.0 + IL_0009: beq.s IL_0057 + IL_000b: ldloc.0 + IL_000c: brfalse.s IL_0055 + IL_000e: call ""System.Collections.Generic.EqualityComparer<j__TPar> System.Collections.Generic.EqualityComparer<j__TPar>.Default.get"" + IL_0013: ldarg.0 + IL_0014: ldfld ""j__TPar <>f__AnonymousType0<j__TPar, j__TPar, j__TPar>.i__Field"" + IL_0019: ldloc.0 + IL_001a: ldfld ""j__TPar <>f__AnonymousType0<j__TPar, j__TPar, j__TPar>.i__Field"" + IL_001f: callvirt ""bool System.Collections.Generic.EqualityComparer<j__TPar>.Equals(j__TPar, j__TPar)"" + IL_0024: brfalse.s IL_0055 + IL_0026: call ""System.Collections.Generic.EqualityComparer<j__TPar> System.Collections.Generic.EqualityComparer<j__TPar>.Default.get"" + IL_002b: ldarg.0 + IL_002c: ldfld ""j__TPar <>f__AnonymousType0<j__TPar, j__TPar, j__TPar>.i__Field"" + IL_0031: ldloc.0 + IL_0032: ldfld ""j__TPar <>f__AnonymousType0<j__TPar, j__TPar, j__TPar>.i__Field"" + IL_0037: callvirt ""bool System.Collections.Generic.EqualityComparer<j__TPar>.Equals(j__TPar, j__TPar)"" + IL_003c: brfalse.s IL_0055 + IL_003e: call ""System.Collections.Generic.EqualityComparer<j__TPar> System.Collections.Generic.EqualityComparer<j__TPar>.Default.get"" + IL_0043: ldarg.0 + IL_0044: ldfld ""j__TPar <>f__AnonymousType0<j__TPar, j__TPar, j__TPar>.i__Field"" + IL_0049: ldloc.0 + IL_004a: ldfld ""j__TPar <>f__AnonymousType0<j__TPar, j__TPar, j__TPar>.i__Field"" + IL_004f: callvirt ""bool System.Collections.Generic.EqualityComparer<j__TPar>.Equals(j__TPar, j__TPar)"" + IL_0054: ret + IL_0055: ldc.i4.0 + IL_0056: ret + IL_0057: ldc.i4.1 + IL_0058: ret }" ).VerifyIL( "<>f__AnonymousType0<j__TPar, j__TPar, j__TPar>.GetHashCode", diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs index abe33fc512dd7..75219d4ea9bfc 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs @@ -375,32 +375,37 @@ .maxstack 2 }"); verifier.VerifyIL("C.Equals(C)", @" { - // Code size 71 (0x47) + // Code size 77 (0x4d) .maxstack 3 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_0045 - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type C.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type C.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: brfalse.s IL_0045 - IL_0016: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_001b: ldarg.0 - IL_001c: ldfld ""int C.k__BackingField"" - IL_0021: ldarg.1 - IL_0022: ldfld ""int C.k__BackingField"" - IL_0027: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_002c: brfalse.s IL_0045 - IL_002e: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_0033: ldarg.0 - IL_0034: ldfld ""int C.k__BackingField"" - IL_0039: ldarg.1 - IL_003a: ldfld ""int C.k__BackingField"" - IL_003f: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_0044: ret - IL_0045: ldc.i4.0 - IL_0046: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_004b + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0049 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type C.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type C.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: brfalse.s IL_0049 + IL_001a: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_001f: ldarg.0 + IL_0020: ldfld ""int C.k__BackingField"" + IL_0025: ldarg.1 + IL_0026: ldfld ""int C.k__BackingField"" + IL_002b: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0030: brfalse.s IL_0049 + IL_0032: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_0037: ldarg.0 + IL_0038: ldfld ""int C.k__BackingField"" + IL_003d: ldarg.1 + IL_003e: ldfld ""int C.k__BackingField"" + IL_0043: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0048: ret + IL_0049: ldc.i4.0 + IL_004a: ret + IL_004b: ldc.i4.1 + IL_004c: ret }"); } @@ -470,39 +475,44 @@ public static void Main() verifier.VerifyIL("C.Equals(C)", @" { - // Code size 95 (0x5f) + // Code size 101 (0x65) .maxstack 3 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_005d - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type C.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type C.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: brfalse.s IL_005d - IL_0016: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_001b: ldarg.0 - IL_001c: ldfld ""int C.k__BackingField"" - IL_0021: ldarg.1 - IL_0022: ldfld ""int C.k__BackingField"" - IL_0027: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_002c: brfalse.s IL_005d - IL_002e: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_0033: ldarg.0 - IL_0034: ldfld ""int C.k__BackingField"" - IL_0039: ldarg.1 - IL_003a: ldfld ""int C.k__BackingField"" - IL_003f: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_0044: brfalse.s IL_005d - IL_0046: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_004b: ldarg.0 - IL_004c: ldfld ""int C.Z"" - IL_0051: ldarg.1 - IL_0052: ldfld ""int C.Z"" - IL_0057: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_005c: ret - IL_005d: ldc.i4.0 - IL_005e: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_0063 + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0061 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type C.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type C.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: brfalse.s IL_0061 + IL_001a: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_001f: ldarg.0 + IL_0020: ldfld ""int C.k__BackingField"" + IL_0025: ldarg.1 + IL_0026: ldfld ""int C.k__BackingField"" + IL_002b: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0030: brfalse.s IL_0061 + IL_0032: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_0037: ldarg.0 + IL_0038: ldfld ""int C.k__BackingField"" + IL_003d: ldarg.1 + IL_003e: ldfld ""int C.k__BackingField"" + IL_0043: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0048: brfalse.s IL_0061 + IL_004a: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_004f: ldarg.0 + IL_0050: ldfld ""int C.Z"" + IL_0055: ldarg.1 + IL_0056: ldfld ""int C.Z"" + IL_005b: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0060: ret + IL_0061: ldc.i4.0 + IL_0062: ret + IL_0063: ldc.i4.1 + IL_0064: ret }"); } @@ -559,32 +569,37 @@ public static void Main() verifier.VerifyIL("C.Equals(C)", @" { - // Code size 71 (0x47) + // Code size 77 (0x4d) .maxstack 3 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_0045 - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type C.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type C.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: brfalse.s IL_0045 - IL_0016: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_001b: ldarg.0 - IL_001c: ldfld ""int C.k__BackingField"" - IL_0021: ldarg.1 - IL_0022: ldfld ""int C.k__BackingField"" - IL_0027: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_002c: brfalse.s IL_0045 - IL_002e: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_0033: ldarg.0 - IL_0034: ldfld ""int C.k__BackingField"" - IL_0039: ldarg.1 - IL_003a: ldfld ""int C.k__BackingField"" - IL_003f: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_0044: ret - IL_0045: ldc.i4.0 - IL_0046: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_004b + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0049 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type C.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type C.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: brfalse.s IL_0049 + IL_001a: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_001f: ldarg.0 + IL_0020: ldfld ""int C.k__BackingField"" + IL_0025: ldarg.1 + IL_0026: ldfld ""int C.k__BackingField"" + IL_002b: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0030: brfalse.s IL_0049 + IL_0032: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_0037: ldarg.0 + IL_0038: ldfld ""int C.k__BackingField"" + IL_003d: ldarg.1 + IL_003e: ldfld ""int C.k__BackingField"" + IL_0043: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0048: ret + IL_0049: ldc.i4.0 + IL_004a: ret + IL_004b: ldc.i4.1 + IL_004c: ret }"); } @@ -616,32 +631,37 @@ public static void Main() True"); verifier.VerifyIL("C.Equals(C)", @" { - // Code size 71 (0x47) + // Code size 77 (0x4d) .maxstack 3 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_0045 - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type C.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type C.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: brfalse.s IL_0045 - IL_0016: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_001b: ldarg.0 - IL_001c: ldfld ""int C.k__BackingField"" - IL_0021: ldarg.1 - IL_0022: ldfld ""int C.k__BackingField"" - IL_0027: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_002c: brfalse.s IL_0045 - IL_002e: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_0033: ldarg.0 - IL_0034: ldfld ""int C.k__BackingField"" - IL_0039: ldarg.1 - IL_003a: ldfld ""int C.k__BackingField"" - IL_003f: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_0044: ret - IL_0045: ldc.i4.0 - IL_0046: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_004b + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0049 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type C.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type C.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: brfalse.s IL_0049 + IL_001a: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_001f: ldarg.0 + IL_0020: ldfld ""int C.k__BackingField"" + IL_0025: ldarg.1 + IL_0026: ldfld ""int C.k__BackingField"" + IL_002b: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0030: brfalse.s IL_0049 + IL_0032: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_0037: ldarg.0 + IL_0038: ldfld ""int C.k__BackingField"" + IL_003d: ldarg.1 + IL_003e: ldfld ""int C.k__BackingField"" + IL_0043: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0048: ret + IL_0049: ldc.i4.0 + IL_004a: ret + IL_004b: ldc.i4.1 + IL_004c: ret }"); } @@ -672,39 +692,44 @@ public static void Main() verifier.VerifyIL("C.Equals(C)", @" { - // Code size 95 (0x5f) + // Code size 101 (0x65) .maxstack 3 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_005d - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type C.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type C.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: brfalse.s IL_005d - IL_0016: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_001b: ldarg.0 - IL_001c: ldfld ""int C.k__BackingField"" - IL_0021: ldarg.1 - IL_0022: ldfld ""int C.k__BackingField"" - IL_0027: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_002c: brfalse.s IL_005d - IL_002e: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_0033: ldarg.0 - IL_0034: ldfld ""int C.k__BackingField"" - IL_0039: ldarg.1 - IL_003a: ldfld ""int C.k__BackingField"" - IL_003f: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_0044: brfalse.s IL_005d - IL_0046: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_004b: ldarg.0 - IL_004c: ldfld ""System.Action C.E"" - IL_0051: ldarg.1 - IL_0052: ldfld ""System.Action C.E"" - IL_0057: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(System.Action, System.Action)"" - IL_005c: ret - IL_005d: ldc.i4.0 - IL_005e: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_0063 + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0061 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type C.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type C.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: brfalse.s IL_0061 + IL_001a: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_001f: ldarg.0 + IL_0020: ldfld ""int C.k__BackingField"" + IL_0025: ldarg.1 + IL_0026: ldfld ""int C.k__BackingField"" + IL_002b: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0030: brfalse.s IL_0061 + IL_0032: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_0037: ldarg.0 + IL_0038: ldfld ""int C.k__BackingField"" + IL_003d: ldarg.1 + IL_003e: ldfld ""int C.k__BackingField"" + IL_0043: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0048: brfalse.s IL_0061 + IL_004a: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_004f: ldarg.0 + IL_0050: ldfld ""System.Action C.E"" + IL_0055: ldarg.1 + IL_0056: ldfld ""System.Action C.E"" + IL_005b: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(System.Action, System.Action)"" + IL_0060: ret + IL_0061: ldc.i4.0 + IL_0062: ret + IL_0063: ldc.i4.1 + IL_0064: ret }"); } @@ -1017,39 +1042,44 @@ .maxstack 2 }"); verifier.VerifyIL("C.Equals(C)", @" { - // Code size 95 (0x5f) + // Code size 101 (0x65) .maxstack 3 - IL_0000: ldarg.1 - IL_0001: brfalse.s IL_005d - IL_0003: ldarg.0 - IL_0004: callvirt ""System.Type C.EqualityContract.get"" - IL_0009: ldarg.1 - IL_000a: callvirt ""System.Type C.EqualityContract.get"" - IL_000f: call ""bool System.Type.op_Equality(System.Type, System.Type)"" - IL_0014: brfalse.s IL_005d - IL_0016: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_001b: ldarg.0 - IL_001c: ldfld ""int C.X"" - IL_0021: ldarg.1 - IL_0022: ldfld ""int C.X"" - IL_0027: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_002c: brfalse.s IL_005d - IL_002e: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_0033: ldarg.0 - IL_0034: ldfld ""int C.k__BackingField"" - IL_0039: ldarg.1 - IL_003a: ldfld ""int C.k__BackingField"" - IL_003f: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" - IL_0044: brfalse.s IL_005d - IL_0046: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" - IL_004b: ldarg.0 - IL_004c: ldfld ""System.Action C.E"" - IL_0051: ldarg.1 - IL_0052: ldfld ""System.Action C.E"" - IL_0057: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(System.Action, System.Action)"" - IL_005c: ret - IL_005d: ldc.i4.0 - IL_005e: ret + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: beq.s IL_0063 + IL_0004: ldarg.1 + IL_0005: brfalse.s IL_0061 + IL_0007: ldarg.0 + IL_0008: callvirt ""System.Type C.EqualityContract.get"" + IL_000d: ldarg.1 + IL_000e: callvirt ""System.Type C.EqualityContract.get"" + IL_0013: call ""bool System.Type.op_Equality(System.Type, System.Type)"" + IL_0018: brfalse.s IL_0061 + IL_001a: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_001f: ldarg.0 + IL_0020: ldfld ""int C.X"" + IL_0025: ldarg.1 + IL_0026: ldfld ""int C.X"" + IL_002b: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0030: brfalse.s IL_0061 + IL_0032: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_0037: ldarg.0 + IL_0038: ldfld ""int C.k__BackingField"" + IL_003d: ldarg.1 + IL_003e: ldfld ""int C.k__BackingField"" + IL_0043: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(int, int)"" + IL_0048: brfalse.s IL_0061 + IL_004a: call ""System.Collections.Generic.EqualityComparer System.Collections.Generic.EqualityComparer.Default.get"" + IL_004f: ldarg.0 + IL_0050: ldfld ""System.Action C.E"" + IL_0055: ldarg.1 + IL_0056: ldfld ""System.Action C.E"" + IL_005b: callvirt ""bool System.Collections.Generic.EqualityComparer.Equals(System.Action, System.Action)"" + IL_0060: ret + IL_0061: ldc.i4.0 + IL_0062: ret + IL_0063: ldc.i4.1 + IL_0064: ret }"); } diff --git a/src/Compilers/VisualBasic/Portable/Binding/SyntheticBoundTrees/AnonymousTypeSyntheticMethods.vb b/src/Compilers/VisualBasic/Portable/Binding/SyntheticBoundTrees/AnonymousTypeSyntheticMethods.vb index a004e23485100..58d2083bcbc03 100644 --- a/src/Compilers/VisualBasic/Portable/Binding/SyntheticBoundTrees/AnonymousTypeSyntheticMethods.vb +++ b/src/Compilers/VisualBasic/Portable/Binding/SyntheticBoundTrees/AnonymousTypeSyntheticMethods.vb @@ -213,9 +213,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ConversionKind.WideningReference, objectType, Nothing).MakeCompilerGenerated(), nothingLiteral, booleanType, reverse:=True) - ' Final equality check: AndAlso + ' Final equality check: Me Is val OrElse ( AndAlso ) Dim finalEqualityCheck = BuildAndAlso(valIsNotNothing, combinedFieldCheck, booleanType) + Dim meIsValCheck = BuildIsCheck(boundMeReference, boundValReference, booleanType) + finalEqualityCheck = BuildOrElse(meIsValCheck, finalEqualityCheck, booleanType) + ' Create a bound block Return New BoundBlock(syntax, Nothing, ImmutableArray.Create(localMyFieldBoxed, localOtherFieldBoxed), @@ -312,6 +315,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Return New BoundBinaryOperator(Syntax, BinaryOperatorKind.AndAlso, left, right, False, booleanType).MakeCompilerGenerated() End Function + + Private Function BuildOrElse(left As BoundExpression, right As BoundExpression, booleanType As TypeSymbol) As BoundExpression + Return New BoundBinaryOperator(Syntax, BinaryOperatorKind.OrElse, + left, right, False, booleanType).MakeCompilerGenerated() + End Function End Class Partial Private NotInheritable Class AnonymousTypeToStringMethodSymbol diff --git a/src/Compilers/VisualBasic/Test/Emit/CodeGen/AnonymousTypesCodeGenTests.vb b/src/Compilers/VisualBasic/Test/Emit/CodeGen/AnonymousTypesCodeGenTests.vb index 11b170b15028d..fbaef717764cf 100644 --- a/src/Compilers/VisualBasic/Test/Emit/CodeGen/AnonymousTypesCodeGenTests.vb +++ b/src/Compilers/VisualBasic/Test/Emit/CodeGen/AnonymousTypesCodeGenTests.vb @@ -462,58 +462,63 @@ False VerifyIL("VB$AnonymousType_0(Of T0, T1, T2).Equals(VB$AnonymousType_0(Of T0, T1, T2))", ) End Sub From 073598befa473d80c4e4ce167146d6eebf8da25d Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Fri, 19 Feb 2021 12:43:52 -0800 Subject: [PATCH 10/13] Apply suggestions from code review Co-authored-by: Rikki Gibson --- src/Compilers/Core/MSBuildTask/ManagedCompiler.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs index 3cbeb6eb0ce47..9917317580f28 100644 --- a/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs +++ b/src/Compilers/Core/MSBuildTask/ManagedCompiler.cs @@ -27,8 +27,8 @@ public abstract class ManagedCompiler : ManagedToolTask private enum CompilationKind { ///

- /// Commpilation occured using the command line tool by normal processes, typically because - /// the customer opt'd out of the compiler server + /// Commpilation occurred using the command line tool by normal processes, typically because + /// the customer opted out of the compiler server /// Tool, @@ -39,7 +39,7 @@ private enum CompilationKind ToolFallback, /// - /// Compilation occured in the compiler server process + /// Compilation occurred in the compiler server process /// Server, From 007046dce893b887d48d1a635f8c746af30c9c8f Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Fri, 19 Feb 2021 12:45:21 -0800 Subject: [PATCH 11/13] PR feedback --- src/Compilers/Core/CommandLine/BuildProtocol.cs | 8 -------- .../Server/VBCSCompiler/AnalyzerConsistencyChecker.cs | 5 +---- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/Compilers/Core/CommandLine/BuildProtocol.cs b/src/Compilers/Core/CommandLine/BuildProtocol.cs index 85ff232610709..6da53beb1f746 100644 --- a/src/Compilers/Core/CommandLine/BuildProtocol.cs +++ b/src/Compilers/Core/CommandLine/BuildProtocol.cs @@ -462,10 +462,6 @@ public AnalyzerInconsistencyBuildResponse(ReadOnlyCollection errorMessag ErrorMessages = errorMessages; } - /// - /// AnalyzerInconsistency has no body. - /// - /// protected override void AddResponseBody(BinaryWriter writer) { writer.Write(ErrorMessages.Count); @@ -499,10 +495,6 @@ public RejectedBuildResponse(string reason) Reason = reason; } - /// - /// AnalyzerInconsistency has no body. - /// - /// protected override void AddResponseBody(BinaryWriter writer) { WriteLengthPrefixedString(writer, Reason); diff --git a/src/Compilers/Server/VBCSCompiler/AnalyzerConsistencyChecker.cs b/src/Compilers/Server/VBCSCompiler/AnalyzerConsistencyChecker.cs index 9996e42fe8021..ba0b1f6507569 100644 --- a/src/Compilers/Server/VBCSCompiler/AnalyzerConsistencyChecker.cs +++ b/src/Compilers/Server/VBCSCompiler/AnalyzerConsistencyChecker.cs @@ -100,10 +100,7 @@ private static bool CheckCore( if (resolvedPathMvid != loadedAssemblyMvid) { var message = $"analyzer assembly '{resolvedPath}' has MVID '{resolvedPathMvid}' but loaded assembly '{loadedAssembly.FullName}' has MVID '{loadedAssemblyMvid}'"; - if (errorMessages is null) - { - errorMessages = new List(); - } + errorMessages ??= new List(); errorMessages.Add(message); } } From 1955f409bf199a8359e688ff81771fc49ef5d5cb Mon Sep 17 00:00:00 2001 From: Bernd Baumanns Date: Fri, 19 Feb 2021 23:27:36 +0100 Subject: [PATCH 12/13] Fix NormalizeWhitespace - String Interpolation with e.g. Initializer-expressions (#51213) Co-authored-by: CyrusNajmabadi Co-authored-by: Bernd Baumanns --- .../Portable/Syntax/SyntaxNormalizer.cs | 30 +++++++++++++++++++ .../Syntax/Syntax/SyntaxNormalizerTests.cs | 27 +++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs index a362cb4c12612..46b26c57c47ef 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs @@ -27,6 +27,7 @@ internal class SyntaxNormalizer : CSharpSyntaxRewriter private bool _afterLineBreak; private bool _afterIndentation; + private bool _inSingleLineInterpolation; // CONSIDER: if we become concerned about space, we shouldn't actually need any // of the values between indentations[0] and indentations[initialDepth] (exclusive). @@ -177,6 +178,11 @@ private static bool NeedsIndentAfterLineBreak(SyntaxToken token) private int LineBreaksAfter(SyntaxToken currentToken, SyntaxToken nextToken) { + if (_inSingleLineInterpolation) + { + return 0; + } + if (currentToken.IsKind(SyntaxKind.EndOfDirectiveToken)) { return 1; @@ -915,5 +921,29 @@ node is QueryExpressionSyntax || return 0; } + + public override SyntaxNode? VisitInterpolatedStringExpression(InterpolatedStringExpressionSyntax node) + { + if (node.StringStartToken.Kind() == SyntaxKind.InterpolatedStringStartToken) + { + //Just for non verbatim strings we want to make sure that the formatting of interpolations does not emit line breaks. + //See: https://github.com/dotnet/roslyn/issues/50742 + // + //The flag _inSingleLineInterpolation is set to true while visiting InterpolatedStringExpressionSyntax and checked in LineBreaksAfter + //to suppress adding newlines. + var old = _inSingleLineInterpolation; + _inSingleLineInterpolation = true; + try + { + return base.VisitInterpolatedStringExpression(node); + } + finally + { + _inSingleLineInterpolation = old; + } + } + + return base.VisitInterpolatedStringExpression(node); + } } } diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs index 341ab42ae6fb5..4101ceb06b9cc 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs @@ -16,6 +16,33 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public class SyntaxNormalizerTests { + [Fact, WorkItem(50742, "https://github.com/dotnet/roslyn/issues/50742")] + public void TestLineBreakInterpolations() + { + TestNormalizeExpression( + @"$""Printed: { new Printer() { TextToPrint = ""Hello world!"" }.PrintedText }""", + @"$""Printed: {new Printer(){TextToPrint = ""Hello world!""}.PrintedText}""" + ); + } + + [Fact, WorkItem(50742, "https://github.com/dotnet/roslyn/issues/50742")] + public void TestVerbatimStringInterpolationWithLineBreaks() + { + TestNormalizeStatement(@"Console.WriteLine($@""Test with line +breaks +{ + new[]{ + 1, 2, 3 + }[2] +} + "");", + @"Console.WriteLine($@""Test with line +breaks +{new[]{1, 2, 3}[2]} + "");" + ); + } + [Fact] public void TestNormalizeExpression1() { From 3ee6a8fea776de589329d6298df0dd80109bea3b Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Sat, 20 Feb 2021 01:02:58 +0000 Subject: [PATCH 13/13] Update dependencies from https://github.com/dotnet/arcade build 20210218.7 (#51334) [master] Update dependencies from dotnet/arcade --- eng/Version.Details.xml | 8 ++++---- eng/common/tools.sh | 43 +++++++++++++++++++++++++++++++++++------ global.json | 4 ++-- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 2efcc7ae278e7..148bd1902c0ed 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -3,17 +3,17 @@ - + https://github.com/dotnet/arcade - 1c06c541c2dc6edb3d652cb092785eb341ef8331 + 4957a6f3dd5f6fd1ca9ff06f9c50402f2e3b17e8 https://github.com/dotnet/roslyn 69f354dd21df8dac374c35169bdabb9000cfdea3 - + https://github.com/dotnet/arcade - 1c06c541c2dc6edb3d652cb092785eb341ef8331 + 4957a6f3dd5f6fd1ca9ff06f9c50402f2e3b17e8 diff --git a/eng/common/tools.sh b/eng/common/tools.sh index acbb0c5b3ffd7..4df7e60e884e9 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -234,6 +234,28 @@ function InstallDotNet { } } +function with_retries { + local maxRetries=5 + local retries=1 + echo "Trying to run '$@' for maximum of $maxRetries attempts." + while [[ $((retries++)) -le $maxRetries ]]; do + "$@" + + if [[ $? == 0 ]]; then + echo "Ran '$@' successfully." + return 0 + fi + + timeout=$((3**$retries-1)) + echo "Failed to execute '$@'. Waiting $timeout seconds before next attempt ($retries out of $maxRetries)." 1>&2 + sleep $timeout + done + + echo "Failed to execute '$@' for $maxRetries times." 1>&2 + + return 1 +} + function GetDotNetInstallScript { local root=$1 local install_script="$root/dotnet-install.sh" @@ -246,13 +268,22 @@ function GetDotNetInstallScript { # Use curl if available, otherwise use wget if command -v curl > /dev/null; then + # first, try directly, if this fails we will retry with verbose logging curl "$install_script_url" -sSL --retry 10 --create-dirs -o "$install_script" || { - local exit_code=$? - Write-PipelineTelemetryError -category 'InitializeToolset' "Failed to acquire dotnet install script (exit code '$exit_code')." - ExitWithExitCode $exit_code + if command -v openssl &> /dev/null + then + echo "Curl failed; dumping some information about dotnet.microsoft.com for later investigation" + echo | openssl s_client -showcerts -servername dotnet.microsoft.com -connect dotnet.microsoft.com:443 + fi + echo "Will now retry the same URL with verbose logging." + with_retries curl "$install_script_url" -sSL --verbose --retry 10 --create-dirs -o "$install_script" || { + local exit_code=$? + Write-PipelineTelemetryError -category 'InitializeToolset' "Failed to acquire dotnet install script (exit code '$exit_code')." + ExitWithExitCode $exit_code + } } - else - wget -q -O "$install_script" "$install_script_url" || { + else + with_retries wget -v -O "$install_script" "$install_script_url" || { local exit_code=$? Write-PipelineTelemetryError -category 'InitializeToolset' "Failed to acquire dotnet install script (exit code '$exit_code')." ExitWithExitCode $exit_code @@ -267,7 +298,7 @@ function InitializeBuildTool { if [[ -n "${_InitializeBuildTool:-}" ]]; then return fi - + InitializeDotNetCli $restore # return values diff --git a/global.json b/global.json index 810dceca21e9f..b506768176d21 100644 --- a/global.json +++ b/global.json @@ -12,7 +12,7 @@ "xcopy-msbuild": "16.8.0-preview2.1" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.21116.3", - "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.21116.3" + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.21118.7", + "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.21118.7" } }