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" } } 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/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/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/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() { diff --git a/src/Compilers/Core/CommandLine/BuildProtocol.cs b/src/Compilers/Core/CommandLine/BuildProtocol.cs index a15eef118b73d..6da53beb1f746 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: @@ -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); } } @@ -469,11 +455,33 @@ internal sealed class AnalyzerInconsistencyBuildResponse : BuildResponse { public override ResponseType Type => ResponseType.AnalyzerInconsistency; - ///

- /// AnalyzerInconsistency has no body. - /// - /// - protected override void AddResponseBody(BinaryWriter writer) { } + public ReadOnlyCollection ErrorMessages { get; } + + public AnalyzerInconsistencyBuildResponse(ReadOnlyCollection errorMessages) + { + ErrorMessages = errorMessages; + } + + 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 @@ -487,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/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 6209bc1686198..9917317580f28 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 occurred using the command line tool by normal processes, typically because + /// the customer opted out of the compiler server + /// + Tool, + + /// + /// Compilation occurred using the command line tool because the server was unable to complete + /// the request + /// + ToolFallback, + + /// + /// Compilation occurred 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()) - { + _sharedCompileCts = new CancellationTokenSource(); + logger.Log($"CommandLine = '{commandLineCommands}'"); + logger.Log($"BuildResponseFile = '{responseFileCommands}'"); - 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 could not 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); @@ -628,77 +647,71 @@ 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); - } - + LogCompilerOutput(completedResponse.Output, StandardOutputImportanceToUse); + LogCompilationMessage(logger, CompilationKind.Server, "server processed compilation"); 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); - } - } } - private void LogErrorMultiline(string output) + /// + /// 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. + /// + 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) { - string[] lines = output.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); - foreach (string line in lines) + var category = kind switch { - string trimmedMessage = line.Trim(); - if (trimmedMessage != "") - { - Log.LogError(trimmedMessage); - } + 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); } } - /// - /// Log each of the messages in the given output with the given importance. - /// We assume each line is a message to log. - /// - /// - /// Should be "private protected" visibility once it is introduced into C#. - /// - internal abstract void LogMessages(string output, MessageImportance messageImportance); - public string GenerateResponseFileContents() { return GenerateResponseFileCommands(); 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 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) diff --git a/src/Compilers/Server/VBCSCompiler/AnalyzerConsistencyChecker.cs b/src/Compilers/Server/VBCSCompiler/AnalyzerConsistencyChecker.cs index 4641ff1634311..ba0b1f6507569 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,13 @@ 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}'"; + 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/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] 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); 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 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; 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);