From 38fe7365f800ca68ff85ab40b2868cc017c4a170 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Wed, 1 Dec 2021 06:10:54 -0800 Subject: [PATCH 1/4] Standardize list pattern lowering on Index constructor. Fixes #57825. Relevant spec adjustment https://github.com/dotnet/csharplang/pull/5484. --- .../CSharp/Portable/Binder/Binder_Patterns.cs | 6 +- .../LocalRewriter.PatternLocalRewriter.cs | 5 +- .../LocalRewriter_IndexerAccess.cs | 18 + .../Test/Emit/CodeGen/IndexAndRangeTests.cs | 149 +++-- .../PatternMatchingTests_ListPatterns.cs | 552 +++++++++--------- .../Symbol/Symbols/MissingSpecialMember.cs | 1 - .../Core/Portable/WellKnownMember.cs | 2 - .../Core/Portable/WellKnownMembers.cs | 9 - .../WellKnownTypeValidationTests.vb | 6 +- 9 files changed, 401 insertions(+), 347 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs index bf19f78e71699..70134463608d7 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs @@ -374,11 +374,7 @@ private bool BindLengthAndIndexerForListPattern(SyntaxNode node, TypeSymbol inpu if (!systemIndexType.HasUseSiteError) { - // Check required well-known member. They may not be needed - // during lowering, but it's simpler to always require them to prevent - // the user from getting surprising errors when optimizations fail - _ = GetWellKnownTypeMember(WellKnownMember.System_Index__op_Implicit_FromInt32, diagnostics, syntax: node); - + // Check required well-known member. _ = GetWellKnownTypeMember(WellKnownMember.System_Index__ctor, diagnostics, syntax: node); } diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.PatternLocalRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.PatternLocalRewriter.cs index 1bb4ae224a451..7305f5dca79d5 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.PatternLocalRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.PatternLocalRewriter.cs @@ -303,14 +303,15 @@ void addArg(RefKind refKind, BoundExpression expression) BoundExpression makeUnloweredIndexArgument(int index) { // LocalRewriter.MakePatternIndexOffsetExpression understands this format + var ctor = (MethodSymbol)_factory.WellKnownMember(WellKnownMember.System_Index__ctor); + if (index < 0) { - var ctor = (MethodSymbol)_factory.WellKnownMember(WellKnownMember.System_Index__ctor); return new BoundFromEndIndexExpression(_factory.Syntax, _factory.Literal(-index), methodOpt: ctor, _factory.WellKnownType(WellKnownType.System_Index)); } - return _factory.Convert(_factory.WellKnownType(WellKnownType.System_Index), _factory.Literal(index)); + return _factory.New(ctor, _factory.Literal(index), _factory.Literal(false)); } BoundExpression makeUnloweredRangeArgument(BoundDagSliceEvaluation e) diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs index c6e9842e1c473..7dcfc2ff21c88 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs @@ -432,6 +432,24 @@ private BoundExpression DetermineMakePatternIndexOffsetExpressionStrategy( strategy = PatternIndexOffsetLoweringStrategy.UseAsIs; return VisitExpression(operand); } + else if (unloweredExpr is BoundObjectCreationExpression { Constructor: MethodSymbol constructor, Arguments: { Length: 2 } arguments } && + (object)constructor == _compilation.GetWellKnownTypeMember(WellKnownMember.System_Index__ctor) && + arguments[0] is { Type.SpecialType: SpecialType.System_Int32, ConstantValue.Value: int _ and >= 0 } index && + arguments[1] is { ConstantValue.Value: bool fromEnd }) + { + if (fromEnd) + { + // We can replace the `argument.GetOffset(length)` call with `length - index` + strategy = PatternIndexOffsetLoweringStrategy.SubtractFromLength; + } + else + { + // We can return the int directly + strategy = PatternIndexOffsetLoweringStrategy.UseAsIs; + } + + return VisitExpression(index); + } else { // `argument.GetOffset(length)` diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs index 9df6223c84419..1fcca23225730 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs @@ -1632,44 +1632,81 @@ class C public static void Main() { var s = ""abcdef""; - Console.WriteLine(s[new Index(1, false)]); + int i = 1; + Console.WriteLine(s[new Index(i, false)]); Console.WriteLine(s[(Index)2]); Console.WriteLine(s[^1]); + Console.WriteLine(s[new Index(3, false)]); + Console.WriteLine(s[new Index(2, true)]); + i = 6; + Console.WriteLine(s[new Index(i, true)]); } }", expectedOutput: @"b c -f"); +f +d +e +a"); verifier.VerifyIL("C.Main", @" { - // Code size 70 (0x46) + // Code size 139 (0x8b) .maxstack 4 - .locals init (string V_0, - System.Index V_1) + .locals init (int V_0, //i + string V_1, + System.Index V_2) IL_0000: ldstr ""abcdef"" - IL_0005: dup + IL_0005: ldc.i4.1 IL_0006: stloc.0 - IL_0007: ldloc.0 - IL_0008: ldc.i4.1 - IL_0009: ldc.i4.0 - IL_000a: newobj ""System.Index..ctor(int, bool)"" - IL_000f: stloc.1 - IL_0010: ldloca.s V_1 - IL_0012: ldloc.0 - IL_0013: callvirt ""int string.Length.get"" - IL_0018: call ""int System.Index.GetOffset(int)"" - IL_001d: callvirt ""char string.this[int].get"" - IL_0022: call ""void System.Console.WriteLine(char)"" - IL_0027: dup - IL_0028: ldc.i4.2 - IL_0029: callvirt ""char string.this[int].get"" - IL_002e: call ""void System.Console.WriteLine(char)"" - IL_0033: dup - IL_0034: callvirt ""int string.Length.get"" - IL_0039: ldc.i4.1 - IL_003a: sub - IL_003b: callvirt ""char string.this[int].get"" - IL_0040: call ""void System.Console.WriteLine(char)"" - IL_0045: ret + IL_0007: dup + IL_0008: stloc.1 + IL_0009: ldloc.1 + IL_000a: ldloc.0 + IL_000b: ldc.i4.0 + IL_000c: newobj ""System.Index..ctor(int, bool)"" + IL_0011: stloc.2 + IL_0012: ldloca.s V_2 + IL_0014: ldloc.1 + IL_0015: callvirt ""int string.Length.get"" + IL_001a: call ""int System.Index.GetOffset(int)"" + IL_001f: callvirt ""char string.this[int].get"" + IL_0024: call ""void System.Console.WriteLine(char)"" + IL_0029: dup + IL_002a: ldc.i4.2 + IL_002b: callvirt ""char string.this[int].get"" + IL_0030: call ""void System.Console.WriteLine(char)"" + IL_0035: dup + IL_0036: dup + IL_0037: callvirt ""int string.Length.get"" + IL_003c: ldc.i4.1 + IL_003d: sub + IL_003e: callvirt ""char string.this[int].get"" + IL_0043: call ""void System.Console.WriteLine(char)"" + IL_0048: dup + IL_0049: ldc.i4.3 + IL_004a: callvirt ""char string.this[int].get"" + IL_004f: call ""void System.Console.WriteLine(char)"" + IL_0054: dup + IL_0055: dup + IL_0056: callvirt ""int string.Length.get"" + IL_005b: ldc.i4.2 + IL_005c: sub + IL_005d: callvirt ""char string.this[int].get"" + IL_0062: call ""void System.Console.WriteLine(char)"" + IL_0067: ldc.i4.6 + IL_0068: stloc.0 + IL_0069: stloc.1 + IL_006a: ldloc.1 + IL_006b: ldloc.0 + IL_006c: ldc.i4.1 + IL_006d: newobj ""System.Index..ctor(int, bool)"" + IL_0072: stloc.2 + IL_0073: ldloca.s V_2 + IL_0075: ldloc.1 + IL_0076: callvirt ""int string.Length.get"" + IL_007b: call ""int System.Index.GetOffset(int)"" + IL_0080: callvirt ""char string.this[int].get"" + IL_0085: call ""void System.Console.WriteLine(char)"" + IL_008a: ret } "); } @@ -1819,7 +1856,8 @@ public static void Main() public static void M(int[] array) { - Console.WriteLine(array[new Index(1, false)]); + bool fromEnd = false; + Console.WriteLine(array[new Index(1, fromEnd)]); Console.WriteLine(array[^1]); } }", TestOptions.ReleaseExe); @@ -1827,33 +1865,36 @@ public static void M(int[] array) 11"); verifier.VerifyIL("C.M", @" { - // Code size 40 (0x28) + // Code size 42 (0x2a) .maxstack 3 - .locals init (int[] V_0, - System.Index V_1) - IL_0000: ldarg.0 + .locals init (bool V_0, //fromEnd + int[] V_1, + System.Index V_2) + IL_0000: ldc.i4.0 IL_0001: stloc.0 - IL_0002: ldloc.0 - IL_0003: ldc.i4.1 - IL_0004: ldc.i4.0 - IL_0005: newobj ""System.Index..ctor(int, bool)"" - IL_000a: stloc.1 - IL_000b: ldloca.s V_1 - IL_000d: ldloc.0 - IL_000e: ldlen - IL_000f: conv.i4 - IL_0010: call ""int System.Index.GetOffset(int)"" - IL_0015: ldelem.i4 - IL_0016: call ""void System.Console.WriteLine(int)"" - IL_001b: ldarg.0 - IL_001c: dup - IL_001d: ldlen - IL_001e: conv.i4 - IL_001f: ldc.i4.1 - IL_0020: sub - IL_0021: ldelem.i4 - IL_0022: call ""void System.Console.WriteLine(int)"" - IL_0027: ret + IL_0002: ldarg.0 + IL_0003: stloc.1 + IL_0004: ldloc.1 + IL_0005: ldc.i4.1 + IL_0006: ldloc.0 + IL_0007: newobj ""System.Index..ctor(int, bool)"" + IL_000c: stloc.2 + IL_000d: ldloca.s V_2 + IL_000f: ldloc.1 + IL_0010: ldlen + IL_0011: conv.i4 + IL_0012: call ""int System.Index.GetOffset(int)"" + IL_0017: ldelem.i4 + IL_0018: call ""void System.Console.WriteLine(int)"" + IL_001d: ldarg.0 + IL_001e: dup + IL_001f: ldlen + IL_0020: conv.i4 + IL_0021: ldc.i4.1 + IL_0022: sub + IL_0023: ldelem.i4 + IL_0024: call ""void System.Console.WriteLine(int)"" + IL_0029: ret }"); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_ListPatterns.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_ListPatterns.cs index 4ed06230a62df..b37f3f6004704 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_ListPatterns.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_ListPatterns.cs @@ -125,7 +125,7 @@ .locals init (char V_0, //first "), () => verifier.VerifyIL("X.Test(char[])", @" { - // Code size 71 (0x47) + // Code size 72 (0x48) .maxstack 4 .locals init (char V_0, //first char[] V_1, //others @@ -135,43 +135,44 @@ .locals init (char V_0, //first IL_0000: ldarg.0 IL_0001: stloc.3 IL_0002: ldloc.3 - IL_0003: brfalse.s IL_0045 + IL_0003: brfalse.s IL_0046 IL_0005: ldloc.3 IL_0006: callvirt ""int System.Array.Length.get"" IL_000b: stloc.s V_4 IL_000d: ldloc.s V_4 IL_000f: ldc.i4.1 - IL_0010: ble.un.s IL_0038 + IL_0010: ble.un.s IL_0039 IL_0012: ldloc.3 IL_0013: ldc.i4.0 IL_0014: ldelem.u2 IL_0015: stloc.0 IL_0016: ldloc.3 IL_0017: ldc.i4.1 - IL_0018: call ""System.Index System.Index.op_Implicit(int)"" - IL_001d: ldc.i4.1 + IL_0018: ldc.i4.0 + IL_0019: newobj ""System.Index..ctor(int, bool)"" IL_001e: ldc.i4.1 - IL_001f: newobj ""System.Index..ctor(int, bool)"" - IL_0024: newobj ""System.Range..ctor(System.Index, System.Index)"" - IL_0029: call ""char[] System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray(char[], System.Range)"" - IL_002e: stloc.1 - IL_002f: ldloc.3 - IL_0030: ldloc.s V_4 - IL_0032: ldc.i4.1 - IL_0033: sub - IL_0034: ldelem.u2 - IL_0035: stloc.2 - IL_0036: br.s IL_003a - IL_0038: ldc.i4.1 - IL_0039: ret - IL_003a: ldloc.0 - IL_003b: ldloc.2 - IL_003c: bne.un.s IL_0045 - IL_003e: ldloc.1 - IL_003f: call ""bool X.Test(char[])"" - IL_0044: ret - IL_0045: ldc.i4.0 - IL_0046: ret + IL_001f: ldc.i4.1 + IL_0020: newobj ""System.Index..ctor(int, bool)"" + IL_0025: newobj ""System.Range..ctor(System.Index, System.Index)"" + IL_002a: call ""char[] System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray(char[], System.Range)"" + IL_002f: stloc.1 + IL_0030: ldloc.3 + IL_0031: ldloc.s V_4 + IL_0033: ldc.i4.1 + IL_0034: sub + IL_0035: ldelem.u2 + IL_0036: stloc.2 + IL_0037: br.s IL_003b + IL_0039: ldc.i4.1 + IL_003a: ret + IL_003b: ldloc.0 + IL_003c: ldloc.2 + IL_003d: bne.un.s IL_0046 + IL_003f: ldloc.1 + IL_0040: call ""bool X.Test(char[])"" + IL_0045: ret + IL_0046: ldc.i4.0 + IL_0047: ret } "), () => verifier.VerifyIL("X.Test(string)", @" @@ -336,90 +337,94 @@ public static void Main() AssertEx.Multiple( () => verifier.VerifyIL("X.Test1", @" { - // Code size 30 (0x1e) - .maxstack 2 + // Code size 31 (0x1f) + .maxstack 3 IL_0000: ldarg.0 - IL_0001: brfalse.s IL_001c + IL_0001: brfalse.s IL_001d IL_0003: ldarg.0 IL_0004: callvirt ""int Test1.Length.get"" IL_0009: ldc.i4.1 - IL_000a: bne.un.s IL_001c + IL_000a: bne.un.s IL_001d IL_000c: ldarg.0 IL_000d: ldc.i4.0 - IL_000e: call ""System.Index System.Index.op_Implicit(int)"" - IL_0013: callvirt ""int Test1.this[System.Index].get"" - IL_0018: ldc.i4.1 - IL_0019: ceq - IL_001b: ret - IL_001c: ldc.i4.0 - IL_001d: ret + IL_000e: ldc.i4.0 + IL_000f: newobj ""System.Index..ctor(int, bool)"" + IL_0014: callvirt ""int Test1.this[System.Index].get"" + IL_0019: ldc.i4.1 + IL_001a: ceq + IL_001c: ret + IL_001d: ldc.i4.0 + IL_001e: ret }"), () => verifier.VerifyIL("X.Test2", @" { - // Code size 31 (0x1f) + // Code size 32 (0x20) .maxstack 3 IL_0000: ldarg.0 - IL_0001: brfalse.s IL_001d + IL_0001: brfalse.s IL_001e IL_0003: ldarg.0 IL_0004: callvirt ""int Test2.Length.get"" IL_0009: ldc.i4.1 - IL_000a: bne.un.s IL_001d + IL_000a: bne.un.s IL_001e IL_000c: ldarg.0 IL_000d: ldc.i4.0 - IL_000e: call ""System.Index System.Index.op_Implicit(int)"" - IL_0013: ldc.i4.5 - IL_0014: callvirt ""int Test2.this[System.Index, int].get"" - IL_0019: ldc.i4.1 - IL_001a: ceq - IL_001c: ret - IL_001d: ldc.i4.0 - IL_001e: ret + IL_000e: ldc.i4.0 + IL_000f: newobj ""System.Index..ctor(int, bool)"" + IL_0014: ldc.i4.5 + IL_0015: callvirt ""int Test2.this[System.Index, int].get"" + IL_001a: ldc.i4.1 + IL_001b: ceq + IL_001d: ret + IL_001e: ldc.i4.0 + IL_001f: ret }"), () => verifier.VerifyIL("X.Test3", @" { - // Code size 35 (0x23) + // Code size 36 (0x24) .maxstack 3 IL_0000: ldarg.0 - IL_0001: brfalse.s IL_0021 + IL_0001: brfalse.s IL_0022 IL_0003: ldarg.0 IL_0004: callvirt ""int Test3.Length.get"" IL_0009: ldc.i4.1 - IL_000a: bne.un.s IL_0021 + IL_000a: bne.un.s IL_0022 IL_000c: ldarg.0 IL_000d: ldc.i4.0 - IL_000e: call ""System.Index System.Index.op_Implicit(int)"" - IL_0013: call ""int[] System.Array.Empty()"" - IL_0018: callvirt ""int Test3.this[System.Index, params int[]].get"" - IL_001d: ldc.i4.1 - IL_001e: ceq - IL_0020: ret - IL_0021: ldc.i4.0 - IL_0022: ret + IL_000e: ldc.i4.0 + IL_000f: newobj ""System.Index..ctor(int, bool)"" + IL_0014: call ""int[] System.Array.Empty()"" + IL_0019: callvirt ""int Test3.this[System.Index, params int[]].get"" + IL_001e: ldc.i4.1 + IL_001f: ceq + IL_0021: ret + IL_0022: ldc.i4.0 + IL_0023: ret }"), () => verifier.VerifyIL("X.Test4", @" { - // Code size 43 (0x2b) - .maxstack 5 + // Code size 44 (0x2c) + .maxstack 6 IL_0000: ldarg.0 - IL_0001: brfalse.s IL_0029 + IL_0001: brfalse.s IL_002a IL_0003: ldarg.0 IL_0004: callvirt ""int Test4.Length.get"" IL_0009: ldc.i4.1 - IL_000a: bne.un.s IL_0029 + IL_000a: bne.un.s IL_002a IL_000c: ldarg.0 IL_000d: ldc.i4.1 IL_000e: newarr ""System.Index"" IL_0013: dup IL_0014: ldc.i4.0 IL_0015: ldc.i4.0 - IL_0016: call ""System.Index System.Index.op_Implicit(int)"" - IL_001b: stelem ""System.Index"" - IL_0020: callvirt ""int Test4.this[params System.Index[]].get"" - IL_0025: ldc.i4.1 - IL_0026: ceq - IL_0028: ret - IL_0029: ldc.i4.0 - IL_002a: ret + IL_0016: ldc.i4.0 + IL_0017: newobj ""System.Index..ctor(int, bool)"" + IL_001c: stelem ""System.Index"" + IL_0021: callvirt ""int Test4.this[params System.Index[]].get"" + IL_0026: ldc.i4.1 + IL_0027: ceq + IL_0029: ret + IL_002a: ldc.i4.0 + IL_002b: ret }"), () => verifier.VerifyIL("X.Test5", @" { @@ -519,81 +524,84 @@ public static void Main() AssertEx.Multiple( () => verifier.VerifyIL("X.Test1", @" { - // Code size 40 (0x28) + // Code size 41 (0x29) .maxstack 4 IL_0000: ldarg.0 - IL_0001: brfalse.s IL_0026 + IL_0001: brfalse.s IL_0027 IL_0003: ldarg.0 IL_0004: callvirt ""int Test1.Count.get"" IL_0009: pop IL_000a: ldarg.0 IL_000b: ldc.i4.0 - IL_000c: call ""System.Index System.Index.op_Implicit(int)"" - IL_0011: ldc.i4.0 - IL_0012: ldc.i4.1 - IL_0013: newobj ""System.Index..ctor(int, bool)"" - IL_0018: newobj ""System.Range..ctor(System.Index, System.Index)"" - IL_001d: callvirt ""int Test1.this[System.Range].get"" - IL_0022: ldc.i4.1 - IL_0023: ceq - IL_0025: ret - IL_0026: ldc.i4.0 - IL_0027: ret + IL_000c: ldc.i4.0 + IL_000d: newobj ""System.Index..ctor(int, bool)"" + IL_0012: ldc.i4.0 + IL_0013: ldc.i4.1 + IL_0014: newobj ""System.Index..ctor(int, bool)"" + IL_0019: newobj ""System.Range..ctor(System.Index, System.Index)"" + IL_001e: callvirt ""int Test1.this[System.Range].get"" + IL_0023: ldc.i4.1 + IL_0024: ceq + IL_0026: ret + IL_0027: ldc.i4.0 + IL_0028: ret }"), () => verifier.VerifyIL("X.Test2", @" { - // Code size 41 (0x29) + // Code size 42 (0x2a) .maxstack 4 IL_0000: ldarg.0 - IL_0001: brfalse.s IL_0027 + IL_0001: brfalse.s IL_0028 IL_0003: ldarg.0 IL_0004: callvirt ""int Test2.Count.get"" IL_0009: pop IL_000a: ldarg.0 IL_000b: ldc.i4.0 - IL_000c: call ""System.Index System.Index.op_Implicit(int)"" - IL_0011: ldc.i4.0 - IL_0012: ldc.i4.1 - IL_0013: newobj ""System.Index..ctor(int, bool)"" - IL_0018: newobj ""System.Range..ctor(System.Index, System.Index)"" - IL_001d: ldc.i4.5 - IL_001e: callvirt ""int Test2.this[System.Range, int].get"" - IL_0023: ldc.i4.1 - IL_0024: ceq - IL_0026: ret - IL_0027: ldc.i4.0 - IL_0028: ret + IL_000c: ldc.i4.0 + IL_000d: newobj ""System.Index..ctor(int, bool)"" + IL_0012: ldc.i4.0 + IL_0013: ldc.i4.1 + IL_0014: newobj ""System.Index..ctor(int, bool)"" + IL_0019: newobj ""System.Range..ctor(System.Index, System.Index)"" + IL_001e: ldc.i4.5 + IL_001f: callvirt ""int Test2.this[System.Range, int].get"" + IL_0024: ldc.i4.1 + IL_0025: ceq + IL_0027: ret + IL_0028: ldc.i4.0 + IL_0029: ret }"), () => verifier.VerifyIL("X.Test3", @" { - // Code size 45 (0x2d) + // Code size 46 (0x2e) .maxstack 4 IL_0000: ldarg.0 - IL_0001: brfalse.s IL_002b + IL_0001: brfalse.s IL_002c IL_0003: ldarg.0 IL_0004: callvirt ""int Test3.Count.get"" IL_0009: pop IL_000a: ldarg.0 IL_000b: ldc.i4.0 - IL_000c: call ""System.Index System.Index.op_Implicit(int)"" - IL_0011: ldc.i4.0 - IL_0012: ldc.i4.1 - IL_0013: newobj ""System.Index..ctor(int, bool)"" - IL_0018: newobj ""System.Range..ctor(System.Index, System.Index)"" - IL_001d: call ""int[] System.Array.Empty()"" - IL_0022: callvirt ""int Test3.this[System.Range, params int[]].get"" - IL_0027: ldc.i4.1 - IL_0028: ceq - IL_002a: ret - IL_002b: ldc.i4.0 - IL_002c: ret + IL_000c: ldc.i4.0 + IL_000d: newobj ""System.Index..ctor(int, bool)"" + IL_0012: ldc.i4.0 + IL_0013: ldc.i4.1 + IL_0014: newobj ""System.Index..ctor(int, bool)"" + IL_0019: newobj ""System.Range..ctor(System.Index, System.Index)"" + IL_001e: call ""int[] System.Array.Empty()"" + IL_0023: callvirt ""int Test3.this[System.Range, params int[]].get"" + IL_0028: ldc.i4.1 + IL_0029: ceq + IL_002b: ret + IL_002c: ldc.i4.0 + IL_002d: ret }"), () => verifier.VerifyIL("X.Test4", @" { - // Code size 53 (0x35) + // Code size 54 (0x36) .maxstack 7 IL_0000: ldarg.0 - IL_0001: brfalse.s IL_0033 + IL_0001: brfalse.s IL_0034 IL_0003: ldarg.0 IL_0004: callvirt ""int Test4.Count.get"" IL_0009: pop @@ -603,18 +611,19 @@ .maxstack 7 IL_0011: dup IL_0012: ldc.i4.0 IL_0013: ldc.i4.0 - IL_0014: call ""System.Index System.Index.op_Implicit(int)"" - IL_0019: ldc.i4.0 - IL_001a: ldc.i4.1 - IL_001b: newobj ""System.Index..ctor(int, bool)"" - IL_0020: newobj ""System.Range..ctor(System.Index, System.Index)"" - IL_0025: stelem ""System.Range"" - IL_002a: callvirt ""int Test4.this[params System.Range[]].get"" - IL_002f: ldc.i4.1 - IL_0030: ceq - IL_0032: ret - IL_0033: ldc.i4.0 - IL_0034: ret + IL_0014: ldc.i4.0 + IL_0015: newobj ""System.Index..ctor(int, bool)"" + IL_001a: ldc.i4.0 + IL_001b: ldc.i4.1 + IL_001c: newobj ""System.Index..ctor(int, bool)"" + IL_0021: newobj ""System.Range..ctor(System.Index, System.Index)"" + IL_0026: stelem ""System.Range"" + IL_002b: callvirt ""int Test4.this[params System.Range[]].get"" + IL_0030: ldc.i4.1 + IL_0031: ceq + IL_0033: ret + IL_0034: ldc.i4.0 + IL_0035: ret }"), () => verifier.VerifyIL("X.Test5", @" { @@ -753,15 +762,9 @@ public static void Main() "; var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularWithListPatterns); compilation.VerifyEmitDiagnostics( - // (20,24): error CS0656: Missing compiler required member 'System.Index.op_Implicit' - // _ = new X() is [1]; - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[1]").WithArguments("System.Index", "op_Implicit").WithLocation(20, 24), // (20,24): error CS0656: Missing compiler required member 'System.Index..ctor' // _ = new X() is [1]; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[1]").WithArguments("System.Index", ".ctor").WithLocation(20, 24), - // (21,24): error CS0656: Missing compiler required member 'System.Index.op_Implicit' - // _ = new X() is [.. 1]; - Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[.. 1]").WithArguments("System.Index", "op_Implicit").WithLocation(21, 24), // (21,24): error CS0656: Missing compiler required member 'System.Index..ctor' // _ = new X() is [.. 1]; Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "[.. 1]").WithArguments("System.Index", ".ctor").WithLocation(21, 24), @@ -2099,39 +2102,41 @@ public static void Main() var verifier = CompileAndVerify(compilation, expectedOutput: "True"); verifier.VerifyIL("X.Main", @" { - // Code size 71 (0x47) + // Code size 73 (0x49) .maxstack 4 .locals init (Test1 V_0) IL_0000: newobj ""Test1..ctor()"" IL_0005: stloc.0 IL_0006: ldloc.0 - IL_0007: brfalse.s IL_0040 + IL_0007: brfalse.s IL_0042 IL_0009: ldloc.0 IL_000a: callvirt ""int Test1.Count.get"" IL_000f: ldc.i4.1 - IL_0010: bne.un.s IL_0040 + IL_0010: bne.un.s IL_0042 IL_0012: ldloc.0 IL_0013: ldc.i4.0 - IL_0014: call ""System.Index System.Index.op_Implicit(int)"" - IL_0019: callvirt ""ref int Test1.this[System.Index].get"" - IL_001e: ldind.i4 - IL_001f: ldc.i4.1 - IL_0020: bne.un.s IL_0040 - IL_0022: ldloc.0 - IL_0023: ldc.i4.0 - IL_0024: call ""System.Index System.Index.op_Implicit(int)"" - IL_0029: ldc.i4.0 - IL_002a: ldc.i4.1 - IL_002b: newobj ""System.Index..ctor(int, bool)"" - IL_0030: newobj ""System.Range..ctor(System.Index, System.Index)"" - IL_0035: callvirt ""ref int Test1.this[System.Range].get"" - IL_003a: ldind.i4 - IL_003b: ldc.i4.1 - IL_003c: ceq - IL_003e: br.s IL_0041 - IL_0040: ldc.i4.0 - IL_0041: call ""void System.Console.WriteLine(bool)"" - IL_0046: ret + IL_0014: ldc.i4.0 + IL_0015: newobj ""System.Index..ctor(int, bool)"" + IL_001a: callvirt ""ref int Test1.this[System.Index].get"" + IL_001f: ldind.i4 + IL_0020: ldc.i4.1 + IL_0021: bne.un.s IL_0042 + IL_0023: ldloc.0 + IL_0024: ldc.i4.0 + IL_0025: ldc.i4.0 + IL_0026: newobj ""System.Index..ctor(int, bool)"" + IL_002b: ldc.i4.0 + IL_002c: ldc.i4.1 + IL_002d: newobj ""System.Index..ctor(int, bool)"" + IL_0032: newobj ""System.Range..ctor(System.Index, System.Index)"" + IL_0037: callvirt ""ref int Test1.this[System.Range].get"" + IL_003c: ldind.i4 + IL_003d: ldc.i4.1 + IL_003e: ceq + IL_0040: br.s IL_0043 + IL_0042: ldc.i4.0 + IL_0043: call ""void System.Console.WriteLine(bool)"" + IL_0048: ret }"); } @@ -5049,7 +5054,7 @@ void M2() verifier.VerifyIL("C.M", @" { - // Code size 77 (0x4d) + // Code size 79 (0x4f) .maxstack 4 .locals init (string V_0, //item string V_1, //rest @@ -5059,35 +5064,37 @@ .locals init (string V_0, //item IL_0000: ldarg.0 IL_0001: stloc.2 IL_0002: ldloc.2 - IL_0003: brfalse.s IL_004c + IL_0003: brfalse.s IL_004e IL_0005: ldloc.2 IL_0006: callvirt ""int C.Length.get"" IL_000b: ldc.i4.1 - IL_000c: blt.s IL_004c + IL_000c: blt.s IL_004e IL_000e: ldloc.2 IL_000f: ldc.i4.0 - IL_0010: call ""System.Index System.Index.op_Implicit(int)"" - IL_0015: stloc.3 - IL_0016: ldloca.s V_3 - IL_0018: callvirt ""string C.this[in System.Index].get"" - IL_001d: stloc.0 - IL_001e: ldloc.2 - IL_001f: ldc.i4.1 - IL_0020: call ""System.Index System.Index.op_Implicit(int)"" - IL_0025: ldc.i4.0 - IL_0026: ldc.i4.1 - IL_0027: newobj ""System.Index..ctor(int, bool)"" - IL_002c: newobj ""System.Range..ctor(System.Index, System.Index)"" - IL_0031: stloc.s V_4 - IL_0033: ldloca.s V_4 - IL_0035: callvirt ""string C.this[in System.Range].get"" - IL_003a: stloc.1 - IL_003b: ldloc.0 - IL_003c: ldloc.1 - IL_003d: newobj ""System.ValueTuple..ctor(string, string)"" - IL_0042: box ""System.ValueTuple"" - IL_0047: call ""void System.Console.Write(object)"" - IL_004c: ret + IL_0010: ldc.i4.0 + IL_0011: newobj ""System.Index..ctor(int, bool)"" + IL_0016: stloc.3 + IL_0017: ldloca.s V_3 + IL_0019: callvirt ""string C.this[in System.Index].get"" + IL_001e: stloc.0 + IL_001f: ldloc.2 + IL_0020: ldc.i4.1 + IL_0021: ldc.i4.0 + IL_0022: newobj ""System.Index..ctor(int, bool)"" + IL_0027: ldc.i4.0 + IL_0028: ldc.i4.1 + IL_0029: newobj ""System.Index..ctor(int, bool)"" + IL_002e: newobj ""System.Range..ctor(System.Index, System.Index)"" + IL_0033: stloc.s V_4 + IL_0035: ldloca.s V_4 + IL_0037: callvirt ""string C.this[in System.Range].get"" + IL_003c: stloc.1 + IL_003d: ldloc.0 + IL_003e: ldloc.1 + IL_003f: newobj ""System.ValueTuple..ctor(string, string)"" + IL_0044: box ""System.ValueTuple"" + IL_0049: call ""void System.Console.Write(object)"" + IL_004e: ret } "); } @@ -5135,7 +5142,7 @@ void M2() verifier.VerifyIL("C.M", @" { - // Code size 80 (0x50) + // Code size 82 (0x52) .maxstack 4 .locals init (string V_0, //item string V_1, //rest @@ -5143,33 +5150,35 @@ .locals init (string V_0, //item IL_0000: ldarg.0 IL_0001: stloc.2 IL_0002: ldloc.2 - IL_0003: brfalse.s IL_004f + IL_0003: brfalse.s IL_0051 IL_0005: ldloc.2 IL_0006: callvirt ""int C.Length.get"" IL_000b: ldc.i4.1 - IL_000c: blt.s IL_004f + IL_000c: blt.s IL_0051 IL_000e: ldloc.2 IL_000f: ldc.i4.0 - IL_0010: call ""System.Index System.Index.op_Implicit(int)"" - IL_0015: call ""MyIndex MyIndex.op_Implicit(System.Index)"" - IL_001a: callvirt ""string C.this[MyIndex].get"" - IL_001f: stloc.0 - IL_0020: ldloc.2 - IL_0021: ldc.i4.1 - IL_0022: call ""System.Index System.Index.op_Implicit(int)"" - IL_0027: ldc.i4.0 - IL_0028: ldc.i4.1 - IL_0029: newobj ""System.Index..ctor(int, bool)"" - IL_002e: newobj ""System.Range..ctor(System.Index, System.Index)"" - IL_0033: call ""MyRange MyRange.op_Implicit(System.Range)"" - IL_0038: callvirt ""string C.this[MyRange].get"" - IL_003d: stloc.1 - IL_003e: ldloc.0 - IL_003f: ldloc.1 - IL_0040: newobj ""System.ValueTuple..ctor(string, string)"" - IL_0045: box ""System.ValueTuple"" - IL_004a: call ""void System.Console.Write(object)"" - IL_004f: ret + IL_0010: ldc.i4.0 + IL_0011: newobj ""System.Index..ctor(int, bool)"" + IL_0016: call ""MyIndex MyIndex.op_Implicit(System.Index)"" + IL_001b: callvirt ""string C.this[MyIndex].get"" + IL_0020: stloc.0 + IL_0021: ldloc.2 + IL_0022: ldc.i4.1 + IL_0023: ldc.i4.0 + IL_0024: newobj ""System.Index..ctor(int, bool)"" + IL_0029: ldc.i4.0 + IL_002a: ldc.i4.1 + IL_002b: newobj ""System.Index..ctor(int, bool)"" + IL_0030: newobj ""System.Range..ctor(System.Index, System.Index)"" + IL_0035: call ""MyRange MyRange.op_Implicit(System.Range)"" + IL_003a: callvirt ""string C.this[MyRange].get"" + IL_003f: stloc.1 + IL_0040: ldloc.0 + IL_0041: ldloc.1 + IL_0042: newobj ""System.ValueTuple..ctor(string, string)"" + IL_0047: box ""System.ValueTuple"" + IL_004c: call ""void System.Console.Write(object)"" + IL_0051: ret } "); } @@ -7438,41 +7447,43 @@ public static void Print(ConsList? list) var verifier = CompileAndVerify(compilation, verify: Verification.Fails); verifier.VerifyIL("ConsList.Print", @" { - // Code size 82 (0x52) + // Code size 84 (0x54) .maxstack 4 .locals init (object V_0, //head ConsList V_1) //tail IL_0000: ldarg.0 - IL_0001: brfalse.s IL_0034 + IL_0001: brfalse.s IL_0036 IL_0003: ldarg.0 IL_0004: callvirt ""int ConsList.Length.get"" IL_0009: ldc.i4.1 - IL_000a: blt.s IL_0051 + IL_000a: blt.s IL_0053 IL_000c: ldarg.0 IL_000d: ldc.i4.0 - IL_000e: call ""System.Index System.Index.op_Implicit(int)"" - IL_0013: callvirt ""object ConsList.this[System.Index].get"" - IL_0018: stloc.0 - IL_0019: ldarg.0 - IL_001a: ldc.i4.1 - IL_001b: call ""System.Index System.Index.op_Implicit(int)"" - IL_0020: ldc.i4.0 - IL_0021: ldc.i4.1 - IL_0022: newobj ""System.Index..ctor(int, bool)"" - IL_0027: newobj ""System.Range..ctor(System.Index, System.Index)"" - IL_002c: callvirt ""ConsList ConsList.this[System.Range].get"" - IL_0031: stloc.1 - IL_0032: br.s IL_0035 - IL_0034: ret - IL_0035: ldloc.0 - IL_0036: callvirt ""string object.ToString()"" - IL_003b: ldstr "" "" - IL_0040: call ""string string.Concat(string, string)"" - IL_0045: call ""void System.Console.Write(string)"" - IL_004a: ldloc.1 - IL_004b: call ""void ConsList.Print(ConsList)"" - IL_0050: ret - IL_0051: ret + IL_000e: ldc.i4.0 + IL_000f: newobj ""System.Index..ctor(int, bool)"" + IL_0014: callvirt ""object ConsList.this[System.Index].get"" + IL_0019: stloc.0 + IL_001a: ldarg.0 + IL_001b: ldc.i4.1 + IL_001c: ldc.i4.0 + IL_001d: newobj ""System.Index..ctor(int, bool)"" + IL_0022: ldc.i4.0 + IL_0023: ldc.i4.1 + IL_0024: newobj ""System.Index..ctor(int, bool)"" + IL_0029: newobj ""System.Range..ctor(System.Index, System.Index)"" + IL_002e: callvirt ""ConsList ConsList.this[System.Range].get"" + IL_0033: stloc.1 + IL_0034: br.s IL_0037 + IL_0036: ret + IL_0037: ldloc.0 + IL_0038: callvirt ""string object.ToString()"" + IL_003d: ldstr "" "" + IL_0042: call ""string string.Concat(string, string)"" + IL_0047: call ""void System.Console.Write(string)"" + IL_004c: ldloc.1 + IL_004d: call ""void ConsList.Print(ConsList)"" + IL_0052: ret + IL_0053: ret } "); } @@ -7726,7 +7737,7 @@ public static void Main() // Tracked by https://github.com/dotnet/roslyn/issues/57728 verifier.VerifyIL("C.Main", @" { - // Code size 118 (0x76) + // Code size 119 (0x77) .maxstack 5 .locals init (int[] V_0, //x int[] V_1, @@ -7743,54 +7754,55 @@ .locals init (int[] V_0, //x IL_000d: stelem.i4 IL_000e: stloc.1 IL_000f: ldloc.1 - IL_0010: brfalse.s IL_0075 + IL_0010: brfalse.s IL_0076 IL_0012: ldloc.1 IL_0013: callvirt ""int System.Array.Length.get"" IL_0018: ldc.i4.2 - IL_0019: blt.s IL_0075 + IL_0019: blt.s IL_0076 IL_001b: ldloc.1 IL_001c: ldc.i4.1 - IL_001d: call ""System.Index System.Index.op_Implicit(int)"" - IL_0022: ldc.i4.1 + IL_001d: ldc.i4.0 + IL_001e: newobj ""System.Index..ctor(int, bool)"" IL_0023: ldc.i4.1 - IL_0024: newobj ""System.Index..ctor(int, bool)"" - IL_0029: newobj ""System.Range..ctor(System.Index, System.Index)"" - IL_002e: call ""int[] System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray(int[], System.Range)"" - IL_0033: stloc.0 - IL_0034: ldc.i4.4 - IL_0035: newarr ""int"" - IL_003a: dup - IL_003b: ldc.i4.1 - IL_003c: ldc.i4.4 - IL_003d: stelem.i4 - IL_003e: dup - IL_003f: ldc.i4.2 + IL_0024: ldc.i4.1 + IL_0025: newobj ""System.Index..ctor(int, bool)"" + IL_002a: newobj ""System.Range..ctor(System.Index, System.Index)"" + IL_002f: call ""int[] System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray(int[], System.Range)"" + IL_0034: stloc.0 + IL_0035: ldc.i4.4 + IL_0036: newarr ""int"" + IL_003b: dup + IL_003c: ldc.i4.1 + IL_003d: ldc.i4.4 + IL_003e: stelem.i4 + IL_003f: dup IL_0040: ldc.i4.2 - IL_0041: stelem.i4 - IL_0042: ldc.i4.1 - IL_0043: call ""System.Index System.Index.op_Implicit(int)"" - IL_0048: ldc.i4.1 + IL_0041: ldc.i4.2 + IL_0042: stelem.i4 + IL_0043: ldc.i4.1 + IL_0044: call ""System.Index System.Index.op_Implicit(int)"" IL_0049: ldc.i4.1 - IL_004a: newobj ""System.Index..ctor(int, bool)"" - IL_004f: newobj ""System.Range..ctor(System.Index, System.Index)"" - IL_0054: call ""int[] System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray(int[], System.Range)"" - IL_0059: stloc.2 - IL_005a: ldloc.0 - IL_005b: ldc.i4.0 - IL_005c: ldelem.i4 - IL_005d: ldloc.0 - IL_005e: ldc.i4.1 - IL_005f: ldelem.i4 - IL_0060: ldloc.2 - IL_0061: ldc.i4.0 - IL_0062: ldelem.i4 - IL_0063: ldloc.2 - IL_0064: ldc.i4.1 - IL_0065: ldelem.i4 - IL_0066: newobj ""System.ValueTuple..ctor(int, int, int, int)"" - IL_006b: box ""System.ValueTuple"" - IL_0070: call ""void System.Console.Write(object)"" - IL_0075: ret + IL_004a: ldc.i4.1 + IL_004b: newobj ""System.Index..ctor(int, bool)"" + IL_0050: newobj ""System.Range..ctor(System.Index, System.Index)"" + IL_0055: call ""int[] System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray(int[], System.Range)"" + IL_005a: stloc.2 + IL_005b: ldloc.0 + IL_005c: ldc.i4.0 + IL_005d: ldelem.i4 + IL_005e: ldloc.0 + IL_005f: ldc.i4.1 + IL_0060: ldelem.i4 + IL_0061: ldloc.2 + IL_0062: ldc.i4.0 + IL_0063: ldelem.i4 + IL_0064: ldloc.2 + IL_0065: ldc.i4.1 + IL_0066: ldelem.i4 + IL_0067: newobj ""System.ValueTuple..ctor(int, int, int, int)"" + IL_006c: box ""System.ValueTuple"" + IL_0071: call ""void System.Console.Write(object)"" + IL_0076: ret } "); } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs index a0cc6ec261cce..f1511be8f3a69 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/MissingSpecialMember.cs @@ -964,7 +964,6 @@ public void AllWellKnownTypeMembers() case WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctor: case WellKnownMember.System_Runtime_CompilerServices_NativeIntegerAttribute__ctorTransformFlags: case WellKnownMember.System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear: - case WellKnownMember.System_Index__op_Implicit_FromInt32: // Not yet in the platform. continue; case WellKnownMember.Microsoft_CodeAnalysis_Runtime_Instrumentation__CreatePayloadForMethodsSpanningSingleFile: diff --git a/src/Compilers/Core/Portable/WellKnownMember.cs b/src/Compilers/Core/Portable/WellKnownMember.cs index e0868c6410ace..7df1c2d23a983 100644 --- a/src/Compilers/Core/Portable/WellKnownMember.cs +++ b/src/Compilers/Core/Portable/WellKnownMember.cs @@ -515,8 +515,6 @@ internal enum WellKnownMember System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear, - System_Index__op_Implicit_FromInt32, - Count // Remember to update the AllWellKnownTypeMembers tests when making changes here diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs index d6cae77858322..5d91cc3c17988 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -3527,14 +3527,6 @@ static WellKnownMembers() 0, // Method Signature (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_String, // Return Type - // System_Index__op_Implicit_FromInt32 - (byte)(MemberFlags.Method | MemberFlags.Static), // Flags - (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Index - WellKnownType.ExtSentinel), // DeclaringTypeId - 0, // Arity - 1, // Method Signature - (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Index - WellKnownType.ExtSentinel), // Return Type - (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Int32, - }; string[] allNames = new string[(int)WellKnownMember.Count] @@ -3978,7 +3970,6 @@ static WellKnownMembers() "Append", // System_Text_StringBuilder__AppendObject ".ctor", // System_Text_StringBuilder__ctor "ToStringAndClear", // System_Runtime_CompilerServices_DefaultInterpolatedStringHandler__ToStringAndClear - "op_Implicit", // System_Index__op_Implicit_FromInt32 }; s_descriptors = MemberDescriptor.InitializeFromStream(new System.IO.MemoryStream(initializationBytes, writable: false), allNames); diff --git a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb index 5454d830e7731..a8b6b5df00e13 100644 --- a/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb +++ b/src/Compilers/VisualBasic/Test/Symbol/SymbolsTests/WellKnownTypeValidationTests.vb @@ -716,8 +716,7 @@ End Namespace WellKnownMember.System_Runtime_CompilerServices_ITuple__get_Item, WellKnownMember.System_Runtime_CompilerServices_ITuple__get_Length, WellKnownMember.System_Runtime_CompilerServices_SwitchExpressionException__ctor, - WellKnownMember.System_Runtime_CompilerServices_SwitchExpressionException__ctorObject, - WellKnownMember.System_Index__op_Implicit_FromInt32 + WellKnownMember.System_Runtime_CompilerServices_SwitchExpressionException__ctorObject ' Not always available. Continue For End Select @@ -859,8 +858,7 @@ End Namespace WellKnownMember.System_Runtime_CompilerServices_ITuple__get_Item, WellKnownMember.System_Runtime_CompilerServices_ITuple__get_Length, WellKnownMember.System_Runtime_CompilerServices_SwitchExpressionException__ctor, - WellKnownMember.System_Runtime_CompilerServices_SwitchExpressionException__ctorObject, - WellKnownMember.System_Index__op_Implicit_FromInt32 + WellKnownMember.System_Runtime_CompilerServices_SwitchExpressionException__ctorObject ' Not always available. Continue For End Select From aa7d25396f271ed1cbb9323ba6c58075c0e2a42f Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Wed, 1 Dec 2021 06:18:12 -0800 Subject: [PATCH 2/4] Fixup --- .../Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs index 7dcfc2ff21c88..60ae09eb95eca 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs @@ -435,7 +435,7 @@ private BoundExpression DetermineMakePatternIndexOffsetExpressionStrategy( else if (unloweredExpr is BoundObjectCreationExpression { Constructor: MethodSymbol constructor, Arguments: { Length: 2 } arguments } && (object)constructor == _compilation.GetWellKnownTypeMember(WellKnownMember.System_Index__ctor) && arguments[0] is { Type.SpecialType: SpecialType.System_Int32, ConstantValue.Value: int _ and >= 0 } index && - arguments[1] is { ConstantValue.Value: bool fromEnd }) + arguments[1] is { Type.SpecialType: SpecialType.System_Boolean, ConstantValue.Value: bool fromEnd }) { if (fromEnd) { From 1b81fa3db17ca33e2edd9be055cd2940776b061a Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Wed, 1 Dec 2021 06:38:40 -0800 Subject: [PATCH 3/4] Fixup --- .../LocalRewriter_IndexerAccess.cs | 2 +- .../Test/Emit/CodeGen/IndexAndRangeTests.cs | 51 +++++++++++++------ 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs index 60ae09eb95eca..e4aa62b0c508a 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IndexerAccess.cs @@ -432,7 +432,7 @@ private BoundExpression DetermineMakePatternIndexOffsetExpressionStrategy( strategy = PatternIndexOffsetLoweringStrategy.UseAsIs; return VisitExpression(operand); } - else if (unloweredExpr is BoundObjectCreationExpression { Constructor: MethodSymbol constructor, Arguments: { Length: 2 } arguments } && + else if (unloweredExpr is BoundObjectCreationExpression { Constructor: MethodSymbol constructor, Arguments: { Length: 2 } arguments, ArgsToParamsOpt: { IsDefaultOrEmpty: true }, InitializerExpressionOpt: null } && (object)constructor == _compilation.GetWellKnownTypeMember(WellKnownMember.System_Index__ctor) && arguments[0] is { Type.SpecialType: SpecialType.System_Int32, ConstantValue.Value: int _ and >= 0 } index && arguments[1] is { Type.SpecialType: SpecialType.System_Boolean, ConstantValue.Value: bool fromEnd }) diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs index 1fcca23225730..7a95f82bdbfc0 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs @@ -1640,16 +1640,20 @@ public static void Main() Console.WriteLine(s[new Index(2, true)]); i = 6; Console.WriteLine(s[new Index(i, true)]); + Console.WriteLine(s[new Index(value: 2, fromEnd: false)]); + Console.WriteLine(s[new Index(fromEnd: true, value: 3)]); } }", expectedOutput: @"b c f d e -a"); +a +c +d"); verifier.VerifyIL("C.Main", @" { - // Code size 139 (0x8b) + // Code size 185 (0xb9) .maxstack 4 .locals init (int V_0, //i string V_1, @@ -1694,19 +1698,36 @@ .locals init (int V_0, //i IL_0062: call ""void System.Console.WriteLine(char)"" IL_0067: ldc.i4.6 IL_0068: stloc.0 - IL_0069: stloc.1 - IL_006a: ldloc.1 - IL_006b: ldloc.0 - IL_006c: ldc.i4.1 - IL_006d: newobj ""System.Index..ctor(int, bool)"" - IL_0072: stloc.2 - IL_0073: ldloca.s V_2 - IL_0075: ldloc.1 - IL_0076: callvirt ""int string.Length.get"" - IL_007b: call ""int System.Index.GetOffset(int)"" - IL_0080: callvirt ""char string.this[int].get"" - IL_0085: call ""void System.Console.WriteLine(char)"" - IL_008a: ret + IL_0069: dup + IL_006a: stloc.1 + IL_006b: ldloc.1 + IL_006c: ldloc.0 + IL_006d: ldc.i4.1 + IL_006e: newobj ""System.Index..ctor(int, bool)"" + IL_0073: stloc.2 + IL_0074: ldloca.s V_2 + IL_0076: ldloc.1 + IL_0077: callvirt ""int string.Length.get"" + IL_007c: call ""int System.Index.GetOffset(int)"" + IL_0081: callvirt ""char string.this[int].get"" + IL_0086: call ""void System.Console.WriteLine(char)"" + IL_008b: dup + IL_008c: ldc.i4.2 + IL_008d: callvirt ""char string.this[int].get"" + IL_0092: call ""void System.Console.WriteLine(char)"" + IL_0097: stloc.1 + IL_0098: ldloc.1 + IL_0099: ldc.i4.3 + IL_009a: ldc.i4.1 + IL_009b: newobj ""System.Index..ctor(int, bool)"" + IL_00a0: stloc.2 + IL_00a1: ldloca.s V_2 + IL_00a3: ldloc.1 + IL_00a4: callvirt ""int string.Length.get"" + IL_00a9: call ""int System.Index.GetOffset(int)"" + IL_00ae: callvirt ""char string.this[int].get"" + IL_00b3: call ""void System.Console.WriteLine(char)"" + IL_00b8: ret } "); } From aa095b04ebf4b7bbb6ce5ed3ef7b7ec007b7b318 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Thu, 2 Dec 2021 14:43:28 -0800 Subject: [PATCH 4/4] Add a test scenario with initializer. --- .../Test/Emit/CodeGen/IndexAndRangeTests.cs | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs index 7a95f82bdbfc0..62f565161795d 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/IndexAndRangeTests.cs @@ -1642,6 +1642,7 @@ public static void Main() Console.WriteLine(s[new Index(i, true)]); Console.WriteLine(s[new Index(value: 2, fromEnd: false)]); Console.WriteLine(s[new Index(fromEnd: true, value: 3)]); + Console.WriteLine(s[new Index(3, false) {}]); } }", expectedOutput: @"b c @@ -1650,10 +1651,11 @@ public static void Main() e a c +d d"); verifier.VerifyIL("C.Main", @" { - // Code size 185 (0xb9) + // Code size 219 (0xdb) .maxstack 4 .locals init (int V_0, //i string V_1, @@ -1715,19 +1717,32 @@ .locals init (int V_0, //i IL_008c: ldc.i4.2 IL_008d: callvirt ""char string.this[int].get"" IL_0092: call ""void System.Console.WriteLine(char)"" - IL_0097: stloc.1 - IL_0098: ldloc.1 - IL_0099: ldc.i4.3 - IL_009a: ldc.i4.1 - IL_009b: newobj ""System.Index..ctor(int, bool)"" - IL_00a0: stloc.2 - IL_00a1: ldloca.s V_2 - IL_00a3: ldloc.1 - IL_00a4: callvirt ""int string.Length.get"" - IL_00a9: call ""int System.Index.GetOffset(int)"" - IL_00ae: callvirt ""char string.this[int].get"" - IL_00b3: call ""void System.Console.WriteLine(char)"" - IL_00b8: ret + IL_0097: dup + IL_0098: stloc.1 + IL_0099: ldloc.1 + IL_009a: ldc.i4.3 + IL_009b: ldc.i4.1 + IL_009c: newobj ""System.Index..ctor(int, bool)"" + IL_00a1: stloc.2 + IL_00a2: ldloca.s V_2 + IL_00a4: ldloc.1 + IL_00a5: callvirt ""int string.Length.get"" + IL_00aa: call ""int System.Index.GetOffset(int)"" + IL_00af: callvirt ""char string.this[int].get"" + IL_00b4: call ""void System.Console.WriteLine(char)"" + IL_00b9: stloc.1 + IL_00ba: ldloc.1 + IL_00bb: ldc.i4.3 + IL_00bc: ldc.i4.0 + IL_00bd: newobj ""System.Index..ctor(int, bool)"" + IL_00c2: stloc.2 + IL_00c3: ldloca.s V_2 + IL_00c5: ldloc.1 + IL_00c6: callvirt ""int string.Length.get"" + IL_00cb: call ""int System.Index.GetOffset(int)"" + IL_00d0: callvirt ""char string.this[int].get"" + IL_00d5: call ""void System.Console.WriteLine(char)"" + IL_00da: ret } "); }