Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List patterns: parsing changes #53537

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ private PatternSyntax ParsePrimaryPattern(Precedence precedence, bool afterIs, b
case SyntaxKind.DotDotToken:
return _syntaxFactory.SlicePattern(
CheckFeatureAvailability(EatToken(), MessageID.IDS_FeatureSlicePattern),
IsPossibleSubpatternElement() ? ParseNegatedPattern(precedence, afterIs: false, whenIsKeyword) : null);
IsPossibleSubpatternElement() ? ParsePattern(precedence, afterIs: false, whenIsKeyword) : null);
case SyntaxKind.LessThanToken:
case SyntaxKind.LessThanEqualsToken:
case SyntaxKind.GreaterThanToken:
Expand Down Expand Up @@ -452,6 +452,7 @@ private bool IsValidPatternDesignation(bool whenIsKeyword)
case SyntaxKind.IdentifierToken:
case SyntaxKind.OpenBraceToken:
case SyntaxKind.OpenParenToken:
case SyntaxKind.OpenBracketToken:
// these all can start a pattern
return false;
default:
Expand Down Expand Up @@ -541,7 +542,10 @@ private PropertyPatternClauseSyntax ParsePropertyPatternClause()
closeKind: SyntaxKind.CloseBraceToken,
out bool isPropertyPatternClause);
var kind = isPropertyPatternClause ? SyntaxKind.PropertyPatternClause : SyntaxKind.ListPatternClause;
return _syntaxFactory.PropertyPatternClause(kind, openBraceToken, subPatterns, closeBraceToken);
var result = _syntaxFactory.PropertyPatternClause(kind, openBraceToken, subPatterns, closeBraceToken);
if (!isPropertyPatternClause)
result = CheckFeatureAvailability(result, MessageID.IDS_FeatureListPattern);
return result;
}

private void ParseSubpatternList(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,9 @@ void M1(object o, bool b)

var compilation = CreateCompilation(source, new[] { vbCompilation.EmitToImageReference() }, parseOptions: TestOptions.Regular8);
compilation.VerifyDiagnostics(
// (6,31): error CS8652: The feature 'list pattern' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// b = /*<bind>*/o is C1 { Prop[1]: var x }/*</bind>*/;
Diagnostic(ErrorCode.ERR_FeatureInPreview, "{ Prop[1]: var x }").WithArguments("list pattern").WithLocation(6, 31),
// (6,31): error CS9200: List patterns may not be used for a value of type 'C1'.
// b = /*<bind>*/o is C1 { Prop[1]: var x }/*</bind>*/;
Diagnostic(ErrorCode.ERR_UnsupportedTypeForListPattern, "{ Prop[1]: var x }").WithArguments("C1").WithLocation(6, 31),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ .locals init (char V_0, //first
}

[Fact]
public void LengthPattern()
public void LengthPattern_01()
{
var source = @"
using System;
Expand Down Expand Up @@ -335,6 +335,122 @@ .locals init (int V_0, //length
}");
}

[Fact]
public void LengthPattern_02()
{
var source = @"
using System;
class X
{
public static bool Test1(int[] a) => a is [1] or [2];
public static bool Test2(int[] a) => a is [1 or 2];
public static bool Test3(int[] a) => a is [>=1] and [<3];
public static bool Test4(int[] a) => a is [>=1 and <3];
public static bool Test5(int[] a) => a is [not 3];
public static bool Test6(int[] a) => a is {} and not [3];

public static void Main()
{
foreach (var a in new[] { new int[1], new int[2], new int[3] })
{
Console.WriteLine(Test1(a));
Console.WriteLine(Test2(a));
Console.WriteLine(Test3(a));
Console.WriteLine(Test4(a));
Console.WriteLine(Test5(a));
Console.WriteLine(Test6(a));
}
}
}
";
var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularWithListPatterns, options: TestOptions.ReleaseExe);
compilation.VerifyEmitDiagnostics();
string expectedOutput = @"
True
True
True
True
True
True
True
True
True
True
True
True
False
False
False
False
False
False
";
var verifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
string expectedIL12 = @"{
// Code size 24 (0x18)
.maxstack 2
.locals init (int V_0,
bool V_1)
IL_0000: ldarg.0
IL_0001: brfalse.s IL_0014
IL_0003: ldarg.0
IL_0004: callvirt ""int System.Array.Length.get""
IL_0009: stloc.0
IL_000a: ldloc.0
IL_000b: ldc.i4.1
IL_000c: sub
IL_000d: ldc.i4.1
IL_000e: bgt.un.s IL_0014
IL_0010: ldc.i4.1
IL_0011: stloc.1
IL_0012: br.s IL_0016
IL_0014: ldc.i4.0
IL_0015: stloc.1
IL_0016: ldloc.1
IL_0017: ret
}";
string expectedIL34 = @"{
// Code size 21 (0x15)
.maxstack 2
.locals init (int V_0)
IL_0000: ldarg.0
IL_0001: brfalse.s IL_0013
IL_0003: ldarg.0
IL_0004: callvirt ""int System.Array.Length.get""
IL_0009: stloc.0
IL_000a: ldloc.0
IL_000b: ldc.i4.1
IL_000c: blt.s IL_0013
IL_000e: ldloc.0
IL_000f: ldc.i4.3
IL_0010: clt
IL_0012: ret
IL_0013: ldc.i4.0
IL_0014: ret
}";
string expectedIL56 = @"{
// Code size 18 (0x12)
.maxstack 2
IL_0000: ldarg.0
IL_0001: brfalse.s IL_0010
IL_0003: ldarg.0
IL_0004: callvirt ""int System.Array.Length.get""
IL_0009: ldc.i4.3
IL_000a: ceq
IL_000c: ldc.i4.0
IL_000d: ceq
IL_000f: ret
IL_0010: ldc.i4.0
IL_0011: ret
}";
verifier.VerifyIL("X.Test1", expectedIL12);
verifier.VerifyIL("X.Test2", expectedIL12);
verifier.VerifyIL("X.Test3", expectedIL34);
verifier.VerifyIL("X.Test4", expectedIL34);
verifier.VerifyIL("X.Test5", expectedIL56);
verifier.VerifyIL("X.Test6", expectedIL56);
}

[Fact]
public void LengthPattern_InputType()
{
Expand Down Expand Up @@ -1584,7 +1700,8 @@ public void M(int[] a)
_ = a is {1,2,3} and {1,2,3};
_ = a is ([>0]) and ([<0]); // 5
_ = a is ([>0]) and ([>=0]);
// PROTOTYPE(list-patterns) Parsing length patterns inside combinators
_ = a is [>0] and [<0]; // 6
_ = a is [>0] and [>=0];
}
}
";
Expand All @@ -1604,7 +1721,10 @@ public void M(int[] a)
Diagnostic(ErrorCode.ERR_IsPatternImpossible, "a is {1,2,3} and {1,2,4}").WithArguments("int[]").WithLocation(13, 13),
// (15,13): error CS8518: An expression of type 'int[]' can never match the provided pattern.
// _ = a is ([>0]) and ([<0]); // 5
Diagnostic(ErrorCode.ERR_IsPatternImpossible, "a is ([>0]) and ([<0])").WithArguments("int[]").WithLocation(15, 13)
Diagnostic(ErrorCode.ERR_IsPatternImpossible, "a is ([>0]) and ([<0])").WithArguments("int[]").WithLocation(15, 13),
// (17,13): error CS8518: An expression of type 'int[]' can never match the provided pattern.
// _ = a is [>0] and [<0]; // 6
Diagnostic(ErrorCode.ERR_IsPatternImpossible, "a is [>0] and [<0]").WithArguments("int[]").WithLocation(17, 13)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6656,6 +6656,9 @@ public void TrailingCommaInPropertyPattern_01()
public void TrailingCommaInPropertyPattern_02()
{
UsingExpression("e is { , }",
// (1,6): error CS8652: The feature 'list pattern' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
// e is { , }
Diagnostic(ErrorCode.ERR_FeatureInPreview, "{ , }").WithArguments("list pattern").WithLocation(1, 6),
// (1,8): error CS8504: Pattern missing
// e is { , }
Diagnostic(ErrorCode.ERR_MissingPattern, ",").WithLocation(1, 8)
Expand Down
Loading