diff --git a/docs/features/patterns.md b/docs/features/patterns.md index 225aaf0189fb26cc2ac0d4482e7552cf328afc79..8b3d84269163391001da52c2154cc4f2ddb0300e 100644 --- a/docs/features/patterns.md +++ b/docs/features/patterns.md @@ -3,104 +3,130 @@ Pattern Matching for C# ======================= -Pattern matching extensions for C# enable many of the benefits of algebraic data types and pattern matching from functional languages, but in a way that smoothly integrates with the feel of the underlying language. The basic features are: [record types](records.md), which are types whose semantic meaning is described by the shape of the data; and pattern matching, which is a new expression form that enables extremely concise multilevel decomposition of these data types. Elements of this approach are inspired by related features in the programming languages [F#](http://www.msr-waypoint.net/pubs/79947/p29-syme.pdf "Extensible Pattern Matching Via a Lightweight Language") and [Scala](http://lampwww.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf "Matching Objects With Patterns"). +Pattern matching extensions for C# enable many of the benefits of algebraic data types and pattern matching from functional languages, but in a way that smoothly integrates with the feel of the underlying language. The basic features are: [record types](records.md), which are types whose semantic meaning is described by the shape of the data (treated as a separate feature); and pattern matching, which is a new form that enables extremely concise multilevel decomposition of these data types. Elements of this approach are inspired by related features in the programming languages [F#](http://www.msr-waypoint.net/pubs/79947/p29-syme.pdf "Extensible Pattern Matching Via a Lightweight Language") and [Scala](http://lampwww.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf "Matching Objects With Patterns"). ## Is Expression The `is` operator is extended to test an expression against a *pattern*. ```antlr -relational_expression +is_pattern_expression : relational_expression 'is' pattern ; + +relational_expression + : is_pattern_expression + ; ``` This form of *relational_expression* is in addition to the existing forms in the C# specification. It is a compile-time error if the *relational_expression* to the left of the `is` token does not designate a value or does not have a type. +A *constant_pattern* appearing as the right-hand-side of an *is_pattern_expression* is syntactically restricted to be a *shift_expression*, even though a *constant_pattern* appearing elsewhere can syntactically be any *expression*. For simplicity that restriction is not shown in the grammar. + Every *identifier* of the pattern introduces a new local variable that is *definitely assigned* after the `is` operator is `true` (i.e. *definitely assigned when true*). +> Note: There is technically an ambiguity between *type* in an `is-expression` and *constant_pattern* in an *is_pattern_expression*, either of which might be a valid parse of a qualified identifier. We try to bind it as a type for compatibility with previous versions of the language; only if that fails do we resolve it as a constant pattern. + ## Patterns Patterns are used in the `is` operator and in a *switch_statement* to express the shape of data against which incoming data is to be compared. Patterns may be recursive so that parts of the data may be matched against sub-patterns. ```antlr pattern - : type_pattern + : declaration_pattern | constant_pattern - | wildcard_pattern + | deconstruction_pattern + | property_pattern + | discard_pattern | var_pattern - | recursive_pattern ; -type_pattern - : type identifier - ; - -wildcard_pattern - : '*' - ; - -var_pattern - : 'var' identifier +declaration_pattern + : type simple_designation ; constant_pattern - : shift_expression + : constant_expression ; -recursive_pattern - : positional_pattern - | property_pattern +property_pattern + : type? property_subpattern simple_designation? ; -positional_pattern - : type? '(' subpattern_list? ')' +property_subpattern + : '{' subpatterns? '}' ; -subpattern_list +subpatterns : subpattern - | subpattern ',' subpattern_list + | subpattern ',' subpatterns ; subpattern - : argument_name? pattern + : pattern + | identifier ':' pattern ; -property_pattern - : type? '{' property_subpattern_list? '}' - | type identifier '{' property_subpattern_list? '}' - | var identifier '{' property_subpattern_list? '}' +deconstruction_pattern + : type? '(' subpatterns? ')' property_subpattern? simple_designation? ; -property_subpattern_list - : property_subpattern - | property_subpattern ',' property_subpattern_list +simple_designation + : single_variable_designation + | discard_designation ; -property_subpattern - : identifier 'is' pattern +discard_pattern + : discard_designation + ; + +var_pattern + : 'var' designation ; ``` -> Note: There is technically an ambiguity between *type* in an `is-expression` and *constant_pattern*, either of which might be a valid parse of a qualified identifier. We try to bind it as a type for compatibility with previous versions of the language; only if that fails do we resolve it as we do in other contexts, to the first thing found (which must be either a constant or a type). This ambiguity is only present on the right-hand-side of an `is` expression. +It is a semantic error if any _subpattern_ of a _property_pattern_ does not contain an _identifier_ (it must be of the second form, which has an _identifier_). + +There is no special "null-checking pattern", as the ability to check for null falls out as a special case of a trivial property pattern. To check if the string `s` is non-null, you can write any of the following forms + +``` c# +if (s is object o) ... // o is of type object +if (s is string x) ... // x is of type string +if (s is {} x) ... // x is of type string +if (s is {}) ... +``` + +Every pattern is bound against a hypothetical *input operand*. In the case of an *is_pattern_expression*, that is the value of the left-hand-side. In the case of a branch of a `switch` statement, it is the switch expression. In the case of a nested pattern, it is the result of extracting the relevant value from the enclosing object. ### Type Pattern -The *type_pattern* both tests that an expression is of a given type and casts it to that type if the test succeeds. This introduces a local variable of the given type named by the given identifier. That local variable is *definitely assigned* when the result of the pattern-matching operation is true. +The *type_pattern* both tests that the input operand holds a value of a given type and casts it to that type if the test succeeds. This introduces a local variable of the given type named by the *simple_designation*. That local variable is *definitely assigned* when the result of the pattern-matching operation is true. ```antlr type_pattern - : type identifier + : type simple_designation ; ``` -The runtime semantic of this expression is that it tests the runtime type of the left-hand *relational_expression* operand against the *type* in the pattern. If it is of that runtime type (or some subtype), the result of the `is operator` is `true`. It declares a new local variable named by the *identifier* that is assigned the value of the left-hand operand when the result is `true`. +The runtime semantic of this expression is that it tests the runtime type of the input operand against the *type* in the pattern. If it is of that runtime type (or some subtype), the result of the `is operator` is `true`. If the *simple_designation* is a *single_variable_designation*, then it declares a new local variable named by the *identifier* that is assigned the value of the input operand when the result is `true`. Certain combinations of static type of the left-hand-side and the given type are considered incompatible and result in compile-time error. A value of static type `E` is said to be *pattern compatible* with the type `T` if there exists an identity conversion, an implicit reference conversion, a boxing conversion, an explicit reference conversion, or an unboxing conversion from `E` to `T`. It is a compile-time error if an expression of type `E` is not pattern compatible with the type in a type pattern that it is matched with. +> Note: this is not quite correct for type parameters, which should be considered pattern compatible always. + The type pattern is useful for performing run-time type tests of reference types, and replaces the idiom ```cs +Type v; +if (value is Type) +{ + v = (Type)value; +} +``` + +or + +``` c# var v = expr as Type; if (v != null) { // code using v } ``` @@ -111,7 +137,7 @@ With the slightly more concise if (expr is Type v) { // code using v } ``` -It is an error if *type* is a nullable value type and the *identifier* is present. +It is an error if *type* is a nullable value type. The type pattern can be used to test values of nullable types: a value of type `Nullable` (or a boxed `T`) matches a type pattern `T2 id` if the value is non-null and the type of `T2` is `T`, or some base type or interface of `T`. For example, in the code fragment @@ -120,15 +146,15 @@ int? x = 3; if (x is int v) { // code using v } ``` -The condition of the `if` statement is `true` at runtime and the variable `v` holds the value `3` of type `int` inside the block. +The condition of the `if` statement is `true` at runtime and the variable `v` holds the value `3` of type `int`. ### Constant Pattern -A constant pattern tests the value of an expression against a constant value. The constant may be any constant expression, such as a literal, the name of a declared `const` variable, or an enumeration constant, or a `typeof` expression. +A constant pattern tests the value of an expression against a constant value. The constant may be any constant expression, such as a literal, the name of a declared `const` variable, or an enumeration constant. If both *e* and *c* are of integral types, the pattern is considered matched if the result of the expression `e == c` is `true`. -Otherwise the pattern is considered matching if `object.Equals(e, c)` returns `true`. In this case it is a compile-time error if the static type of *e* is not *pattern compatible* with the type of the constant. +Otherwise the pattern is considered matching if `object.Equals(c, e)` returns `true`. In this case it is a compile-time error if the static type of *e* is not *pattern compatible* with the type of the constant. ```antlr constant_pattern @@ -138,323 +164,112 @@ constant_pattern ### Var Pattern -An expression *e* matches the pattern `var identifier` always. In other words, a match to a *var pattern* always succeeds. At runtime the value of *e* is bound to a newly introduced local variable. The type of the local variable is the static type of *e*. - -If the name `var` binds to a type, then we instead treat the pattern as a *type_pattern*. - -### Wildcard Pattern - -An expression *e* matches the pattern `*` always. In other words, every expression matches the wildcard pattern. - -### Positional Pattern - -A positional pattern enables the program to invoke an appropriate `operator is`, and (if the operator has a `void` return type, or returns `true`) perform further pattern matching on the values that are returned from it. It also supports a tuple-like pattern syntax when the static type is the same as the type containing `operator is`, or if the runtime type of the expression implements `ITuple`. - -```antlr -positional_pattern - : type? '(' subpattern_list? ')' +``` antlr +var_pattern + : 'var' designation ; ``` -If the *type* is omitted, we take it to be the static type of *e*. In this case it is an error if *e* does not have a type. +An input operand matches the pattern `var identifier` always. In other words, a match to a *var pattern* with a *simple_designator* always succeeds. At runtime the value of the input operand is bound to a newly introduced local variable. The type of the local variable is the static type of the input operand. -Given a match of an expression *e* to the pattern *type* `(` *subpattern_list* `)`, a method is selected by searching in *type* for accessible declarations of `operator is` and selecting one among them using *match operator overload resolution*. +It is an error if the name `var` binds to a type where a *var_pattern* is used. -- If a suitable `operator is` exists, it is a compile-time error if the expression *e* is not *pattern compatible* with the type of the first argument of the selected operator. If the *type* is omitted, it is an error if the `operator is` found does not have the static type of *e* as its first parameter. At runtime the value of the expression is tested against the type of the first parameter as in a type pattern. If this fails then the positional pattern match fails and the result is `false`. If it succeeds, the operator is invoked with fresh compiler-generated variables to receive the `out` parameters. Each value that was received is matched against the corresponding *subpattern*, and the match succeeds if all of these succeed. The order in which subpatterns are matched is unspecified, and a failed match may not match all subpatterns. -- If no suitable `operator is` exists, but the expression is *pattern compatible* with the type `System.ITuple`, and no *argument_name* appears among the subpatterns, then we match using `ITuple`. [Note: this needs to be made more precise.] -- Otherwise the pattern is a compile-time error. +> Note: we need to describe the semantics when the *designation* is a *tuple_designation*. -If a *subpattern* has an *argument_name*, then every subsequent *subpattern* must have an *argument_name*. In this case each argument name must match a parameter name (of an overloaded `operator is` in the first bullet above). [Note: this needs to be made more precise.] +### Discard Pattern -### Property Pattern +An input operand matches the discard `_` always. In other words, every expression matches the discard pattern. -A property pattern enables the program to recursively match values extracted by the use of properties. +### Property Pattern -```antlr +``` antlr property_pattern - : type? '{' property_subpattern_list? '}' - | type identifier '{' property_subpattern_list? '}' - | var identifier '{' property_subpattern_list? '}' - ; - -property_subpattern_list - : property_subpattern - | property_subpattern ',' property_subpattern_list - ; + : type? property_subpattern simple_designation? + ; property_subpattern - : identifier 'is' pattern - ; -``` - -Given a match of an expression *e* to the pattern *type* `{` *property_pattern_list* `}`, it is a compile-time error if the expression *e* is not *pattern compatible* with the type *T* designated by *type*. If the type is absent or designated by `var`, we take it to be the static type of *e*. If the *identifier* is present, it declares a pattern variable of type *type*. Each of the identifiers appearing on the left-hand-side of its *property_pattern_list* must designate a readable property or field of *T*. If the *identifier* of the *property_pattern* is present, it defines a pattern variable of type *T*. - -At runtime, the expression is tested against *T*. If this fails then the property pattern match fails and the result is `false`. If it succeeds, then each *property_subpattern* field or property is read and its value matched against its corresponding pattern. The result of the whole match is `false` only if the result of any of these is `false`. The order in which subpatterns are matched is not specified, and a failed match may not match all subpatterns at runtime. If the match succeeds and the *identifier* of the *property_pattern* is present, it is assigned the matched value. - -> Note: The property pattern can be used to pattern-match with anonymous types. - -### Scope of Pattern Variables - -The scope of a pattern variable is as follows: - -- If the pattern appears in the condition of an `if` statement, its scope is the condition and controlled statement of the `if` statement, but not its `else` clause. -- If the pattern appears in the `when` clause of a `catch`, its scope is the *catch_clause*. -- If the pattern appears in a *switch_label*, its scope is the *switch_section*. -- If the pattern is the *pattern* of or in the *expression* of a *match_section*, its scope is that *match_section*. -- If the pattern appears in the `when` clause of a *switch_label* or *match_label*, its scope of that *switch_section* or *match_section*. -- If the pattern appears in the body of an expression_bodied lambda, its scope is that lambda's body. -- If the pattern appears in the body of an expression_bodied method or property, its scope is that expression body. -- If the pattern appears in the body of an expression_bodied local function, its scope is that method body. -- If the pattern appears in a *ctor_initializer*, its scope is the constructor body. -- If the pattern appears in a field initializer, its scope is that field initializer. -- If the pattern appears in the pattern of a *let_statement*, its scope is the enclosing block. -- If the pattern appears in the pattern of a *case_expression*, its scope is the *case_expression*. -- Otherwise if the pattern appears directly in some *statement*, its scope is that *statement*. - -Other cases are errors for other reasons (e.g. in a parameter's default value or an attribute, both of which are an error because those contexts require a constant expression). - -The use of a pattern variables is a value, not a variable. In other words pattern variables are read-only. - -## User_defined operator is - -An explicit `operator is` may be declared to extend the pattern matching capabilities. Such a method is invoked by the `is` operator or a *switch_statement* with a *positional_pattern*. - -For example, suppose we have a type representing a Cartesian point in 2-space: - -```cs -public class Cartesian -{ - public int X { get; } - public int Y { get; } -} -``` - -We may sometimes think of them in polar coordinates: - -```cs -public static class Polar -{ - public static bool operator is(Cartesian c, out double R, out double Theta) - { - R = Math.Sqrt(c.X*c.X + c.Y*c.Y); - Theta = Math.Atan2(c.Y, c.X); - return c.X != 0 || c.Y != 0; - } -} -``` - -And now we can operate on `Cartesian` values using polar coordinates - -```cs -var c = Cartesian(3, 4); -if (c is Polar(var R, *)) Console.WriteLine(R); -``` - -Which prints `5`. - -## Switch Statement - -The `switch` statement is extended to select for execution the first block having an associated pattern that matches the *switch expression*. + : '{' subpatterns? '}' + ; -```antlr -switch_label - : 'case' complex_pattern case_guard? ':' - | 'case' constant_expression case_guard? ':' - | 'default' ':' - ; +subpatterns + : subpattern + | subpattern ',' subpatterns + ; -case_guard - : 'when' expression - ; +subpattern + : pattern + | identifier ':' pattern + ; ``` -[TODO: we need to explain the interaction with definite assignment here.] -[TODO: we need to describe the scope of pattern variables appearing in the *switch_label*.] +A property pattern tests the input operand to see if it is an instance of a given type, and also tests some of its accessible properties or fields to see if they match given subpatterns. -The order in which patterns are matched is not defined. A compiler is permitted to match patterns out of order, and to reuse the results of already matched patterns to compute the result of matching of other patterns. +The type to be tested is selected as follows: +- If there is a *type* part of the *property_pattern*, then that is the type to be tested. The type must not be a nullable value type. +- Otherwise if the input operand is not a nullable value type, its static type is used. +- Otherwise the underlying type of the input operand's type is used. -In some cases the compiler can prove that a switch section can have no effect at runtime because its pattern is subsumed by a previous case. In these cases a warning may be produced. [TODO: these warnings should be mandatory and we should specify precisely when they are produced.] +The *simple_designation*, if it is a *single_variable_designation*, names a newly introduced variable of this type. -If a *case-guard* is present, its expression is of type `bool`. It is evaluated as an additional condition that must be satisfied for the case to be considered satisfied. +Each of the *subpattern*s appearing int the *property_subpattern* specifies a property or field to be checked. The subpattern must be of the second form, with the *identifier* present. The *identifier* must name an accessible and readable instance property or field of the type to be tested. -## Match Expression +At runtime, a *subpattern* is *satisfied* if the value of that property or field, when treated as the input operand of the *subpattern*'s pattern, matches. -A *match_expression* is added to support `switch`-like semantics for an expression context. +A property pattern matches if the type test succeeds and all subpatterns are satisfied. The order in which subpatterns are matched is not specified, and a failed match may not test all subpatterns at runtime. -The C# language syntax is augmented with the following syntactic productions: +### Deconstruction Pattern -```antlr -relational_expression - : match_expression - ; +A deconstruction pattern is similar to a *property_pattern*, but involves the deconstruction of a *tuple* or the invocation of a user-defined *Deconstruct* method. -match_expression - : relational_expression 'switch' match_block - ; - -match_block - : '(' match_sections ','? ')' - ; - -match_sections - : match_section - | match_sections ',' match_section +``` antlr +deconstruction_pattern + : type? '(' subpatterns? ')' property_subpattern? simple_designation? ; - -match_section - : 'case' pattern case_guard? ':' expression - ; - -case_guard - : 'when' expression - ; ``` -The *match_expression* is not allowed as an *expression_statement*. - -The type of the *match_expression* is the *best common type* of the expressions appearing to the right of the `:` tokens of the *match section*s. - -It is an error if the compiler can prove (using a set of techniques that has not yet been specified) that some *match_section*'s pattern cannot affect the result because some previous pattern will always match. - -At runtime, the result of the *match_expression* is the value of the *expression* of the first *match_section* for which the expression on the left-hand-side of the *match_expression* matches the *match_section*'s pattern, and for which the *case_guard* of the *match_section*, if present, evaluates to `true`. +It is an error if a deconstruction pattern has a single subpattern but omits the type. -## Case expression +The type to be tested is determined as in the *property_pattern*. That type must be a tuple type whose *cardinality* is the same as the number of *subpatterns* between parentheses, or it must be a type that contains a unique `Deconstruct` method with that number of `out` parameters, as defined for the *deconstruction assignment* feature. -A *case_expression* is a shorthand version of the *match_expression* where there is only one case. +A subpattern between parentheses in a *deconstruction_pattern* is satisfied if the value retrieved from the input operand's deconstruction for that position, when treated as the input operand for the corresponding pattern, matches. If such a subpattern has an *identifier*, it is a compile-time error if that is not the name of the corresponding tuple element or `Deconstruct` `out` parameter. -```antlr -relational_expression - : case_expression - ; +A deconstruction pattern matches if the type test succeeds and all subpatterns are satisfied. The order in which subpatterns are matched is not specified, and a failed match may not test all subpatterns at runtime. -case_expression - : shift_expression 'case' pattern ':' shift_expression - ; -``` +> Note: this specification does not yet treat `ITuple` for positional matching. +> -A *case_expression* of the form *e1* `case` *pattern* `:` *e2* is shorthand for *e1* `switch` `(` `case` *pattern* `:` *e2* `)` +## Switch Expression -## Throw expression +A *switch_expression* is added to support `switch`-like semantics for an expression context. -We extend the set of expression forms to include +The C# language syntax is augmented with the following syntactic productions: -```antlr -throw_expression - : 'throw' null_coalescing_expression - ; -null_coalescing_expression - : throw_expression +``` antlr +switch_expression + : null_coalescing_expression switch '{' switch_expression_case_list '}' ; -``` - -The type rules are as follows: - -- A *throw_expression* has no type. -- A *throw_expression* is convertible to every type by an implicit conversion. - -The flow-analysis rules are as follows: - -- For every variable *v*, *v* is definitely assigned before the *null_coalescing_expression* of a *throw_expression* iff it is definitely assigned before the *throw_expression*. -- For every variable *v*, *v* is definitely assigned after *throw_expression*. - -A *throw expression* is permitted in only the following syntactic contexts: -- As the second or third operand of a ternary conditional operator `?:` -- As the second operand of a null coalescing operator `??` -- After the colon of a *match section* -- As the body of an expression-bodied lambda or method. - -## Destructuring assignment - -Inspired by an [F# feature](https://msdn.microsoft.com/en-us/library/dd233238.aspx) and a [conversation on github](https://github.com/dotnet/roslyn/issues/5154#issuecomment-151974994), and similar features in [Swift](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Statements.html) and proposed for [Rust](https://github.com/mbrubeck/rfcs/blob/if-not-let/text/0000-let-else.md), we support decomposition with a *let statement*: - -```antlr -block_statement - : let_statement +switch_expression_case_list + : switch_expression_case + | switch_expression_case_list ',' switch_expression_case ; - -let_statement - : 'let' identifier '=' expression ';' - | 'let' pattern '=' expression ';' - | 'let' pattern '=' expression 'else' embedded_statement - | 'let' pattern '=' expression 'when' expression 'else' embedded_statement +switch_expression_case + : pattern where_clause? '=>' expression ; ``` -`let` is an existing contextual keyword. - -The form -> `let` *identifier* `=` *expression* `;` - -is shorthand for - -> `let` `var` *identifier* `=` *expression* `;` - -(i.e. a *var_pattern*) and is a convenient way for declaring a read-only local variable. - -Semantically, it is an error unless precisely one of the following is true -- the compiler can prove that the expression always matches the pattern; or -- an `else` clause is present. - -Any pattern variables in the *pattern* are in scope throughout the enclosing block. They are not definitely assigned before the `else` clause. They are definitely assigned after the *let_statement* if there is no `else` clause or they are definitely assigned at the end of the `else` clause (which could only occur because the end point of the `else` clause is unreachable). It is an error to use these variables before their point of definition. - -A *let_statement* is a *block_statement* and not an *embedded_statement* because its primary purpose is to introduce names into the enclosing scope. It therefore does not introduce a dangling-else ambiguity. - -If a `when` clause is present, the expression following it must be of type `bool`. - -At runtime the expression to the right of `=` is evaluated and matched against the *pattern*. If the match fails control transfers to the `else` clause. If the match succeeds and there is a `when` clause, the expression following `when` is evaluated, and if its value is `false` control transfers to the `else` clause. +The *switch_expression* is not allowed as an *expression_statement*. -## Some Possible Optimizations +The type of the *switch_expression* is the *best common type* of the expressions appearing to the right of the `=>` tokens of the *switch_expression_case*s. -The compilation of pattern matching can take advantage of common parts of patterns. For example, if the top-level type test of two successive patterns in a *switch_statement* is the same type, the generated code can skip the type test for the second pattern. +It is an error if the compiler can prove (using a set of techniques that has not yet been specified) that some *switch_section*'s pattern cannot affect the result because some previous pattern will always match. -When some of the patterns are integers or strings, the compiler can generate the same kind of code it generates for a switch-statement in earlier versions of the language. +At runtime, the result of the *switch_expression* is the value of the *expression* of the first *switch_expression_case* for which the expression on the left-hand-side of the *switch_expression* matches the *switch_expression_case*'s pattern, and for which the expression of the *where_clause* of the *switch_expression_case*, if present, evaluates to `true`. -For more on these kinds of optimizations, see [[Scott and Ramsey (2000)]](http://www.cs.tufts.edu/~nr/cs257/archive/norman-ramsey/match.pdf "When Do Match-Compilation Heuristics Matter?"). - -It would be possible to support declaring a type hierarchy closed, meaning that all subtypes of the given type are declared in the same assembly. In that case the compiler can generate an internal tag field to distinguish among the different subtypes and reduce the number of type tests required at runtime. Closed hierarchies enable the compiler to detect when a set of matches are complete. It is also possible to provide a slightly weaker form of this optimization while allowing the hierarchy to be open. +> Note: we need to specify what happens if the set of cases is incomplete, both at compile-time and at runtime. ## Some Examples of Pattern Matching -### Is-As - -We can replace the idiom - -```cs -var v = expr as Type; -if (v != null) { - // code using v -} -``` - -With the slightly more concise and direct - -```cs -if (expr is Type v) { - // code using v -} -``` - -### Testing nullable - -We can replace the idiom - -```cs -Type? v = x?.y?.z; -if (v.HasValue) { - var value = v.GetValueOrDefault(); - // code using value -} -``` - -With the slightly more concise and direct - -```cs -if (x?.y?.z is Type value) { - // code using value -} -``` - ### Arithmetic simplification Suppose we define a set of recursive types to represent expressions (per a separate proposal): @@ -475,7 +290,7 @@ Expr Deriv(Expr e) { switch (e) { case X(): return Const(1); - case Const(*): return Const(0); + case Const(_): return Const(0); case Add(var Left, var Right): return Add(Deriv(Left), Deriv(Right)); case Mult(var Left, var Right): @@ -492,8 +307,8 @@ An expression simplifier demonstrates positional patterns: Expr Simplify(Expr e) { switch (e) { - case Mult(Const(0), *): return Const(0); - case Mult(*, Const(0)): return Const(0); + case Mult(Const(0), _): return Const(0); + case Mult(_, Const(0)): return Const(0); case Mult(Const(1), var x): return Simplify(x); case Mult(var x, Const(1)): return Simplify(x); case Mult(Const(var l), Const(var r)): return Const(l*r); @@ -505,47 +320,3 @@ Expr Simplify(Expr e) } } ``` - -### A match expression (contributed by @orthoxerox): - -```cs -var areas = - from primitive in primitives - let area = primitive switch ( - case Line l: 0, - case Rectangle r: r.Width * r.Height, - case Circle c: Math.PI * c.Radius * c.Radius, - case *: throw new ApplicationException() - ) - select new { Primitive = primitive, Area = area }; -``` - -### Tuple decomposition - -The *let_statement* would apply to tuples as follows. Given - -```cs -public (int, int) Coordinates => … -``` - -You could receive the results into a block scope this way - -```cs - let (int x, int y) = Coordinates; -``` - -(This assumes that the tuple types define an appropriate `operator is`.) - -### Roslyn diagnostic analyzers - -Much of the Roslyn compiler code base, and client code written to use Roslyn for producing user-defined diagnostics, could have its core logic simplified by using syntax-based pattern matching. - -### Cloud computing applications - -[NOTE: This section needs much more explanation and examples.] - -* Records are very convenient for communicating data in a distributed system (client-server and server-server). - It is also useful for returning multiple results from an async method. -* "Views", or user-written operator "is", is useful for treating, for example, - json as if it is an application-specific data structure. Pattern matching is very convenient for - dispatching in an actors framework. diff --git a/docs/features/patterns.work.md b/docs/features/patterns.work.md index 4a0874ca1e3f06c629a1133eff79010cfb91649f..4ac2171d51778052a26a2e6caf2fc5142fd7f2d5 100644 --- a/docs/features/patterns.work.md +++ b/docs/features/patterns.work.md @@ -4,14 +4,22 @@ - [ ] The specification needs to be updated with the additional syntax forms being added. See https://github.com/dotnet/csharplang/issues/1054 for a summary of the proposed changes vs C# 7. ### Unimplemented parts -- [ ] Fallback to a recursive pattern when a parenthesized expression is used. - [ ] Give an error when a wildcard is used but something named `_` is in scope. +- [ ] Implement the switch statement in the presence of recursive patterns + - [x] Parsing + - [x] Binding + - [ ] Lowering + - [ ] Code-gen + - [ ] Debug info + - [ ] Edit-and-continue - [ ] Implement the match expression - [ ] Parsing - [ ] Binding - [ ] Lowering - [ ] Code-gen +- [ ] It is an error if the name `var` binds to a type in a var pattern. Implement and test. + ### Test plan needed - [ ] We need a test plan for these additions. Here is a high-level list of some tests that are needed - [ ] Scoping mechanism works for pattern variables in recursive patterns diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs index 03916566cdef0c76139a51209e052654520dc6e5..dc1e06caa7ff35d3bea631d263360402c9de3250 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs @@ -256,10 +256,15 @@ private BoundExpression FixTupleLiteral(ArrayBuilder che } else { - ImmutableArray outPlaceholders; + if (variables.Count < 2) + { + Error(diagnostics, ErrorCode.ERR_DeconstructTooFewElements, syntax); + return false; + } + var inputPlaceholder = new BoundDeconstructValuePlaceholder(syntax, this.LocalScopeDepth, type); - var deconstructInvocation = MakeDeconstructInvocationExpression(variables.Count, - inputPlaceholder, rightSyntax, diagnostics, out outPlaceholders, requireTwoOrMoreElements: true); + BoundExpression deconstructInvocation = MakeDeconstructInvocationExpression(variables.Count, + inputPlaceholder, rightSyntax, diagnostics, outPlaceholders: out ImmutableArray outPlaceholders); if (deconstructInvocation.HasAnyErrors) { @@ -588,19 +593,13 @@ private static string ExtractDeconstructResultElementName(BoundExpression expres /// The overload resolution is similar to writing `receiver.Deconstruct(out var x1, out var x2, ...)`. /// private BoundExpression MakeDeconstructInvocationExpression( - int numCheckedVariables, BoundExpression receiver, SyntaxNode rightSyntax, - DiagnosticBag diagnostics, out ImmutableArray outPlaceholders, - bool requireTwoOrMoreElements) + int numCheckedVariables, + BoundExpression receiver, + SyntaxNode rightSyntax, + DiagnosticBag diagnostics, + out ImmutableArray outPlaceholders) { var receiverSyntax = (CSharpSyntaxNode)receiver.Syntax; - if (requireTwoOrMoreElements && numCheckedVariables < 2) - { - Error(diagnostics, ErrorCode.ERR_DeconstructTooFewElements, receiverSyntax); - outPlaceholders = default(ImmutableArray); - - return BadExpression(receiverSyntax, receiver); - } - if (receiver.Type.IsDynamic()) { Error(diagnostics, ErrorCode.ERR_CannotDeconstructDynamic, rightSyntax); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index a135eb56657664cb0b578330bdf785d2bca225d5..7b031b5727fbe9716c7c3c273465a6f23ad4ea79 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -585,7 +585,7 @@ private static BoundExpression BindDefaultLiteral(ExpressionSyntax node) return new BoundDefaultExpression(node, constantValueOpt: null, type: null); } - internal virtual BoundSwitchExpressionCase BindSwitchExpressionArm(SwitchExpressionArmSyntax node, DiagnosticBag diagnostics) + internal virtual BoundSwitchExpressionArm BindSwitchExpressionArm(SwitchExpressionArmSyntax node, DiagnosticBag diagnostics) { return this.Next.BindSwitchExpressionArm(node, diagnostics); } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs index 69488959759548d89861d5d7e8b02169c465dcbb..03cb58a589b35960de6ff2285d8a22dfbf51ae21 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs @@ -267,7 +267,7 @@ internal BoundExpression ConvertPatternExpression(TypeSymbol inputType, CSharpSy DiagnosticBag diagnostics) { TypeSyntax typeSyntax = node.Type; - BoundTypeExpression boundDeclType = BindPatternType(typeSyntax, operandType, ref hasErrors, out bool isVar, diagnostics); + BoundTypeExpression boundDeclType = BindPatternType(typeSyntax, operandType, diagnostics, ref hasErrors, out bool isVar); if (typeSyntax.IsVar && !isVar) { // PROTOTYPE(patterns2): For compatibility, we temporarily parse the var pattern with a simple designator as a declaration pattern. @@ -277,7 +277,8 @@ internal BoundExpression ConvertPatternExpression(TypeSymbol inputType, CSharpSy diagnostics.Add(ErrorCode.ERR_VarMayNotBindToType, typeSyntax.Location, (boundDeclType.AliasOpt ?? (Symbol)boundDeclType.Type).ToDisplayString()); } - boundDeclType = new BoundTypeExpression(typeSyntax, null, inferredType: true, type: operandType, hasErrors: true); + boundDeclType = new BoundTypeExpression( + syntax: typeSyntax, aliasOpt: null, inferredType: true, type: operandType, hasErrors: true); } TypeSymbol declType = boundDeclType.Type; @@ -290,9 +291,9 @@ internal BoundExpression ConvertPatternExpression(TypeSymbol inputType, CSharpSy private BoundTypeExpression BindPatternType( TypeSyntax typeSyntax, TypeSymbol operandType, + DiagnosticBag diagnostics, ref bool hasErrors, - out bool isVar, - DiagnosticBag diagnostics) + out bool isVar) { Debug.Assert(operandType != (object)null); @@ -357,7 +358,8 @@ internal BoundExpression ConvertPatternExpression(TypeSymbol inputType, CSharpSy } variableSymbol = localSymbol; - variableAccess = new BoundLocal(node, localSymbol, null, declType); + variableAccess = new BoundLocal( + syntax: node, localSymbol: localSymbol, constantValueOpt: null, type: declType); return; } else @@ -371,7 +373,8 @@ internal BoundExpression ConvertPatternExpression(TypeSymbol inputType, CSharpSy BoundExpression receiver = SynthesizeReceiver(node, expressionVariableField, diagnostics); variableSymbol = expressionVariableField; - variableAccess = new BoundFieldAccess(node, receiver, expressionVariableField, null, hasErrors); + variableAccess = new BoundFieldAccess( + syntax: node, receiver: receiver, fieldSymbol: expressionVariableField, constantValueOpt: null, hasErrors: hasErrors); return; } case DiscardDesignationSyntax _: @@ -385,11 +388,11 @@ internal BoundExpression ConvertPatternExpression(TypeSymbol inputType, CSharpSy } - TypeSymbol BindRecursivePatternType(TypeSyntax typeSyntax, TypeSymbol operandType, ref bool hasErrors, out BoundTypeExpression boundDeclType, DiagnosticBag diagnostics) + TypeSymbol BindRecursivePatternType(TypeSyntax typeSyntax, TypeSymbol operandType, DiagnosticBag diagnostics, ref bool hasErrors, out BoundTypeExpression boundDeclType) { if (typeSyntax != null) { - boundDeclType = BindPatternType(typeSyntax, operandType, ref hasErrors, out bool isVar, diagnostics); + boundDeclType = BindPatternType(typeSyntax, operandType, diagnostics, ref hasErrors, out bool isVar); if (isVar) { // The type `var` is not permitted in recursive patterns. If you want the type inferred, just omit it. @@ -414,7 +417,7 @@ TypeSymbol BindRecursivePatternType(TypeSyntax typeSyntax, TypeSymbol operandTyp private BoundPattern BindDeconstructionPattern(DeconstructionPatternSyntax node, TypeSymbol operandType, bool hasErrors, DiagnosticBag diagnostics) { TypeSyntax typeSyntax = node.Type; - TypeSymbol declType = BindRecursivePatternType(typeSyntax, operandType, ref hasErrors, out BoundTypeExpression boundDeclType, diagnostics); + TypeSymbol declType = BindRecursivePatternType(typeSyntax, operandType, diagnostics, ref hasErrors, out BoundTypeExpression boundDeclType); var patterns = ArrayBuilder.GetInstance(node.SubPatterns.Count); MethodSymbol deconstructMethod = null; @@ -442,7 +445,7 @@ private BoundPattern BindDeconstructionPattern(DeconstructionPatternSyntax node, // It is not a tuple type. Seek an appropriate Deconstruct method. var inputPlaceholder = new BoundImplicitReceiver(node, declType); // A fake receiver expression to permit us to reuse binding logic BoundExpression deconstruct = MakeDeconstructInvocationExpression( - node.SubPatterns.Count, inputPlaceholder, node, diagnostics, out ImmutableArray outPlaceholders, requireTwoOrMoreElements: false); + node.SubPatterns.Count, inputPlaceholder, node, diagnostics, outPlaceholders: out ImmutableArray outPlaceholders); deconstructMethod = deconstruct.ExpressionSymbol as MethodSymbol; // PROTOTYPE(patterns2): Set and check the deconstructMethod @@ -475,7 +478,7 @@ private BoundPattern BindDeconstructionPattern(DeconstructionPatternSyntax node, private BoundPattern BindVarPattern(VarPatternSyntax node, TypeSymbol operandType, bool hasErrors, DiagnosticBag diagnostics) { TypeSymbol declType = operandType; - Symbol foundType = BindVarType(node.VarKeyword, diagnostics, out bool isVar, null); + Symbol foundType = BindVarType(varToken: node.VarKeyword, diagnostics: diagnostics, isVar: out bool isVar, basesBeingResolved: null); if (!isVar) { // Give an error if there is a bindable type "var" in scope @@ -495,13 +498,17 @@ private BoundPattern BindVarDesignation(VarPatternSyntax node, VariableDesignati //return new BoundDiscardPattern(designation); // PROTOTYPE(patterns2): this should bind as a discard pattern, but for now we'll bind it as a declaration // pattern for compatibility with the later phases of the compiler that do not yet handle the discard pattern. - var boundOperandType = new BoundTypeExpression(node, null, operandType); // fake a type expression for the variable's type - return new BoundDeclarationPattern(designation, null, null, boundOperandType, isVar: true, hasErrors: hasErrors); + var boundOperandType = new BoundTypeExpression( + syntax: node, aliasOpt: null, type: operandType); // fake a type expression for the variable's type + return new BoundDeclarationPattern( + syntax: designation, variable: null, variableAccess: null, declaredType: boundOperandType, isVar: true, hasErrors: hasErrors); } case SyntaxKind.SingleVariableDesignation: { - BindPatternDesignation(node, designation, operandType, null, diagnostics, ref hasErrors, out Symbol variableSymbol, out BoundExpression variableAccess); - var boundOperandType = new BoundTypeExpression(node, null, operandType); // fake a type expression for the variable's type + BindPatternDesignation( + node: node, designation: designation, declType: operandType, typeSyntax: null, diagnostics: diagnostics, + hasErrors: ref hasErrors, variableSymbol: out Symbol variableSymbol, variableAccess: out BoundExpression variableAccess); + var boundOperandType = new BoundTypeExpression(syntax: node, aliasOpt: null, type: operandType); // fake a type expression for the variable's type return new BoundDeclarationPattern(designation, variableSymbol, variableAccess, boundOperandType, isVar: true, hasErrors: hasErrors); } case SyntaxKind.ParenthesizedVariableDesignation: @@ -515,7 +522,8 @@ private BoundPattern BindVarDesignation(VarPatternSyntax node, VariableDesignati ImmutableArray elementTypes = operandType.TupleElementTypes; if (elementTypes.Length != tupleDesignation.Variables.Count && !hasErrors) { - var location = new SourceLocation(node.SyntaxTree, new Text.TextSpan(tupleDesignation.OpenParenToken.SpanStart, tupleDesignation.CloseParenToken.Span.End - tupleDesignation.OpenParenToken.SpanStart)); + var location = new SourceLocation(node.SyntaxTree, + new Text.TextSpan(tupleDesignation.OpenParenToken.SpanStart, tupleDesignation.CloseParenToken.Span.End - tupleDesignation.OpenParenToken.SpanStart)); diagnostics.Add(ErrorCode.ERR_WrongNumberOfSubpatterns, location, operandType.TupleElementTypes, elementTypes.Length, tupleDesignation.Variables.Count); hasErrors = true; } @@ -532,7 +540,7 @@ private BoundPattern BindVarDesignation(VarPatternSyntax node, VariableDesignati // It is not a tuple type. Seek an appropriate Deconstruct method. var inputPlaceholder = new BoundImplicitReceiver(node, operandType); // A fake receiver expression to permit us to reuse binding logic BoundExpression deconstruct = MakeDeconstructInvocationExpression( - tupleDesignation.Variables.Count, inputPlaceholder, node, diagnostics, out ImmutableArray outPlaceholders, requireTwoOrMoreElements: false); + tupleDesignation.Variables.Count, inputPlaceholder, node, diagnostics, outPlaceholders: out ImmutableArray outPlaceholders); deconstructMethod = deconstruct.ExpressionSymbol as MethodSymbol; // PROTOTYPE(patterns2): Set and check the deconstructMethod @@ -561,7 +569,7 @@ private BoundPattern BindVarDesignation(VarPatternSyntax node, VariableDesignati private BoundPattern BindPropertyPattern(PropertyPatternSyntax node, TypeSymbol operandType, bool hasErrors, DiagnosticBag diagnostics) { TypeSyntax typeSyntax = node.Type; - TypeSymbol declType = BindRecursivePatternType(typeSyntax, operandType, ref hasErrors, out BoundTypeExpression boundDeclType, diagnostics); + TypeSymbol declType = BindRecursivePatternType(typeSyntax, operandType, diagnostics, ref hasErrors, out BoundTypeExpression boundDeclType); ImmutableArray<(Symbol property, BoundPattern pattern)> propertiesOpt = BindPropertySubpattern(node.PropertySubpattern, declType, diagnostics, ref hasErrors); BindPatternDesignation(node, node.Designation, declType, typeSyntax, diagnostics, ref hasErrors, out Symbol variableSymbol, out BoundExpression variableAccess); return new BoundRecursivePattern( @@ -594,7 +602,7 @@ private BoundPattern BindPropertyPattern(PropertyPatternSyntax node, TypeSymbol } else { - member = LookupMemberForPropertyPattern(inputType, name, out memberType, ref hasErrors, diagnostics); + member = LookupMemberForPropertyPattern(inputType, name, diagnostics, ref hasErrors, out memberType); } BoundPattern boundPattern = BindPattern(pattern, memberType, hasErrors, diagnostics); @@ -604,7 +612,8 @@ private BoundPattern BindPropertyPattern(PropertyPatternSyntax node, TypeSymbol return builder.ToImmutableAndFree(); } - private Symbol LookupMemberForPropertyPattern(TypeSymbol inputType, IdentifierNameSyntax name, out TypeSymbol memberType, ref bool hasErrors, DiagnosticBag diagnostics) + private Symbol LookupMemberForPropertyPattern( + TypeSymbol inputType, IdentifierNameSyntax name, DiagnosticBag diagnostics, ref bool hasErrors, out TypeSymbol memberType) { Symbol symbol = BindPropertyPatternMember(inputType, name, ref hasErrors, diagnostics); @@ -682,7 +691,8 @@ private Symbol LookupMemberForPropertyPattern(TypeSymbol inputType, IdentifierNa return null; } - if (hasErrors || !CheckValueKind(memberName.Parent, boundMember, BindValueKind.RValue, false, diagnostics)) + if (hasErrors || !CheckValueKind(node: memberName.Parent, expr: boundMember, valueKind: BindValueKind.RValue, + checkingReceiver: false, diagnostics: diagnostics)) { return null; } diff --git a/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs b/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs index ea6388f03be42078dc6934a9bfea40ee701c7e43..650e1d24c3f7017dab74007f685be403c23e039c 100644 --- a/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/BuckStopsHereBinder.cs @@ -176,7 +176,7 @@ internal override void BindPatternSwitchLabelForInference(CasePatternSwitchLabel throw ExceptionUtilities.Unreachable; } - internal override BoundSwitchExpressionCase BindSwitchExpressionArm(SwitchExpressionArmSyntax node, DiagnosticBag diagnostics) + internal override BoundSwitchExpressionArm BindSwitchExpressionArm(SwitchExpressionArmSyntax node, DiagnosticBag diagnostics) { // There's supposed to be an overrider of this method (e.g. SwitchExpressionArmBinder) for the arm in the chain. throw ExceptionUtilities.Unreachable; diff --git a/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs b/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs index 5f4f38dd646a5eeeba811d110535369102b82141..6b00f37a52df03cc2f7cb85fbb8d09958a73866c 100644 --- a/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs +++ b/src/Compilers/CSharp/Portable/Binder/DecisionDagBuilder.cs @@ -26,7 +26,7 @@ internal DecisionDagBuilder(CSharpCompilation compilation) } /// - /// Used to translate the pattern of an is-pattern expression. + /// Used to translate the pattern of an is-pattern expression. Returns the BoundDagTemp used to represent the root (input). /// public BoundDagTemp TranslatePattern( BoundExpression input, diff --git a/src/Compilers/CSharp/Portable/Binder/ExpressionVariableFinder.cs b/src/Compilers/CSharp/Portable/Binder/ExpressionVariableFinder.cs index 5d7ce8b714bb1fe6bc5088c908a7485179e6cf8a..4a30541c993e3dbd11cf288207909cd4cd85fbf1 100644 --- a/src/Compilers/CSharp/Portable/Binder/ExpressionVariableFinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/ExpressionVariableFinder.cs @@ -644,7 +644,7 @@ internal class ExpressionFieldFinder : ExpressionVariableFinder protected override Symbol MakePatternVariable(TypeSyntax type, SingleVariableDesignationSyntax designation, SyntaxNode nodeToBind) { - return GlobalExpressionVariable.Create( + return designation == null ? null : GlobalExpressionVariable.Create( _containingType, _modifiers, type, designation.Identifier.ValueText, designation, designation.GetLocation(), _containingFieldOpt, nodeToBind); @@ -652,30 +652,12 @@ protected override Symbol MakePatternVariable(TypeSyntax type, SingleVariableDes protected override Symbol MakePatternVariable(DeconstructionPatternSyntax node, SyntaxNode nodeToBind) { - var designation = node.Designation as SingleVariableDesignationSyntax; - if (designation == null) - { - return null; - } - - return GlobalExpressionVariable.Create( - _containingType, _modifiers, node.Type, - designation.Identifier.ValueText, designation, designation.GetLocation(), - _containingFieldOpt, nodeToBind); + return MakePatternVariable(node.Type, node.Designation as SingleVariableDesignationSyntax, nodeToBind); } protected override Symbol MakePatternVariable(PropertyPatternSyntax node, SyntaxNode nodeToBind) { - var designation = node.Designation as SingleVariableDesignationSyntax; - if (designation == null) - { - return null; - } - - return GlobalExpressionVariable.Create( - _containingType, _modifiers, node.Type, - designation.Identifier.ValueText, designation, designation.GetLocation(), - _containingFieldOpt, nodeToBind); + return MakePatternVariable(node.Type, node.Designation as SingleVariableDesignationSyntax, nodeToBind); } protected override Symbol MakeDeclarationExpressionVariable(DeclarationExpressionSyntax node, SingleVariableDesignationSyntax designation, BaseArgumentListSyntax argumentListSyntaxOpt, SyntaxNode nodeToBind) diff --git a/src/Compilers/CSharp/Portable/Binder/SwitchExpressionArmBinder.cs b/src/Compilers/CSharp/Portable/Binder/SwitchExpressionArmBinder.cs index 033c4f3d24796b527a809f87470c176cc91acd89..c31b4b68b0f90565160a837d959f7885c27a2648 100644 --- a/src/Compilers/CSharp/Portable/Binder/SwitchExpressionArmBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/SwitchExpressionArmBinder.cs @@ -13,6 +13,10 @@ namespace Microsoft.CodeAnalysis.CSharp { + /// + /// Binder for one of the arms of a switch expression. For example, in the one-armed switch expression + /// "e switch { p when c => v }", this could be the binder for the arm "p when c => v". + /// internal class SwitchExpressionArmBinder : Binder { private readonly SwitchExpressionArmSyntax _arm; @@ -26,7 +30,7 @@ public SwitchExpressionArmBinder(SwitchExpressionArmSyntax arm, ExpressionVariab this._switchExpressionBinder = switchExpressionBinder; } - internal override BoundSwitchExpressionCase BindSwitchExpressionArm(SwitchExpressionArmSyntax node, DiagnosticBag diagnostics) + internal override BoundSwitchExpressionArm BindSwitchExpressionArm(SwitchExpressionArmSyntax node, DiagnosticBag diagnostics) { Debug.Assert(node == _arm); var caseBinder = this.GetBinder(node); @@ -37,7 +41,7 @@ internal override BoundSwitchExpressionCase BindSwitchExpressionArm(SwitchExpres ? caseBinder.BindBooleanExpression(node.WhenClause.Condition, diagnostics) : null; var result = caseBinder.BindValue(node.Expression, diagnostics, BindValueKind.RValue); - return new BoundSwitchExpressionCase(node, locals, pattern, guard, result, hasErrors); + return new BoundSwitchExpressionArm(node, locals, pattern, guard, result, hasErrors); } } } diff --git a/src/Compilers/CSharp/Portable/Binder/SwitchExpressionBinder.cs b/src/Compilers/CSharp/Portable/Binder/SwitchExpressionBinder.cs index 747df46ee4c08e8de6d31c12e86f3d1082b96ced..1ea296a8df2ec15cf20f5d8e91027876ee5df016 100644 --- a/src/Compilers/CSharp/Portable/Binder/SwitchExpressionBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/SwitchExpressionBinder.cs @@ -31,7 +31,7 @@ internal override BoundExpression BindSwitchExpressionCore(SwitchExpressionSynta // Bind switch expression and set the switch governing type. var boundSwitchGoverningExpression = SwitchGoverningExpression; diagnostics.AddRange(SwitchGoverningDiagnostics); - ImmutableArray switchCases = BindSwitchExpressionCases(node, originalBinder, diagnostics); + ImmutableArray switchCases = BindSwitchExpressionCases(node, originalBinder, diagnostics); bool hasErrors = false; TypeSymbol resultType = InferResultType(switchCases, diagnostics); switchCases = AddConversionsToCases(switchCases, resultType, diagnostics); @@ -43,7 +43,7 @@ internal override BoundExpression BindSwitchExpressionCore(SwitchExpressionSynta /// /// Infer the result type of the switch expression by looking for a common type. /// - private TypeSymbol InferResultType(ImmutableArray switchCases, DiagnosticBag diagnostics) + private TypeSymbol InferResultType(ImmutableArray switchCases, DiagnosticBag diagnostics) { var seenTypes = PooledHashSet.GetInstance(); var typesInOrder = ArrayBuilder.GetInstance(); @@ -72,25 +72,25 @@ private TypeSymbol InferResultType(ImmutableArray swi /// /// Rewrite the expressions in the switch expression cases to add a conversion to the result (common) type. /// - private ImmutableArray AddConversionsToCases(ImmutableArray switchCases, TypeSymbol resultType, DiagnosticBag diagnostics) + private ImmutableArray AddConversionsToCases(ImmutableArray switchCases, TypeSymbol resultType, DiagnosticBag diagnostics) { - var builder = ArrayBuilder.GetInstance(); + var builder = ArrayBuilder.GetInstance(); foreach (var oldCase in switchCases) { var oldValue = oldCase.Value; var newValue = GenerateConversionForAssignment(resultType, oldValue, diagnostics); var newCase = (oldValue == newValue) ? oldCase : - new BoundSwitchExpressionCase(oldCase.Syntax, oldCase.Locals, oldCase.Pattern, oldCase.Guard, newValue, oldCase.HasErrors); + new BoundSwitchExpressionArm(oldCase.Syntax, oldCase.Locals, oldCase.Pattern, oldCase.Guard, newValue, oldCase.HasErrors); builder.Add(newCase); } return builder.ToImmutableAndFree(); } - private ImmutableArray BindSwitchExpressionCases(SwitchExpressionSyntax node, Binder originalBinder, DiagnosticBag diagnostics) + private ImmutableArray BindSwitchExpressionCases(SwitchExpressionSyntax node, Binder originalBinder, DiagnosticBag diagnostics) { bool hasErrors = SwitchGoverningExpression.HasErrors; - var builder = ArrayBuilder.GetInstance(); + var builder = ArrayBuilder.GetInstance(); foreach (var arm in node.Arms) { var armBinder = originalBinder.GetBinder(arm); @@ -105,11 +105,7 @@ internal BoundExpression SwitchGoverningExpression { get { - if (_switchGoverningExpression == null) - { - EnsureSwitchGoverningExpressionAndDiagnosticsBound(); - } - + EnsureSwitchGoverningExpressionAndDiagnosticsBound(); Debug.Assert(_switchGoverningExpression != null); return _switchGoverningExpression; } @@ -122,16 +118,20 @@ protected DiagnosticBag SwitchGoverningDiagnostics get { EnsureSwitchGoverningExpressionAndDiagnosticsBound(); + Debug.Assert(_switchGoverningDiagnostics != null); return _switchGoverningDiagnostics; } } private void EnsureSwitchGoverningExpressionAndDiagnosticsBound() { - var switchGoverningDiagnostics = new DiagnosticBag(); - var boundSwitchGoverningExpression = BindSwitchGoverningExpression(switchGoverningDiagnostics); - _switchGoverningDiagnostics = switchGoverningDiagnostics; - Interlocked.CompareExchange(ref _switchGoverningExpression, boundSwitchGoverningExpression, null); + if (_switchGoverningExpression == null) + { + var switchGoverningDiagnostics = new DiagnosticBag(); + var boundSwitchGoverningExpression = BindSwitchGoverningExpression(switchGoverningDiagnostics); + _switchGoverningDiagnostics = switchGoverningDiagnostics; + Interlocked.CompareExchange(ref _switchGoverningExpression, boundSwitchGoverningExpression, null); + } } private BoundExpression BindSwitchGoverningExpression(DiagnosticBag diagnostics) diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml index 2f33630da6c27fb82fc9334d74a97a310338ee7b..33f142c357aa5dd9e46a86dff863399e8310e407 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml @@ -823,10 +823,10 @@ - + - + diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 2c2b0a262bdc12fafe6790a65efeb4852fab0592..757376ab5224bff0b381b59cf76ffa46d0c3356e 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -8981,11 +8981,11 @@ internal class CSharpResources { } /// - /// Looks up a localized string similar to A single-element deconstruct pattern is ambiguous with a parenthesized pattern; add '{}' after the close paren to disambiguate.. + /// Looks up a localized string similar to A single-element deconstruct pattern requires a type before the open parenthesis.. /// - internal static string ERR_SingleElementPositionalPattern { + internal static string ERR_SingleElementPositionalPatternRequiresType { get { - return ResourceManager.GetString("ERR_SingleElementPositionalPattern", resourceCulture); + return ResourceManager.GetString("ERR_SingleElementPositionalPatternRequiresType", resourceCulture); } } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index d5614f38a0fed0f261320c7f07c6de7409165e1b..8a5ec10859ee206bf012964488eb7b42879f2144 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -5271,8 +5271,8 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ No best type was found for the switch expression. - - A single-element deconstruct pattern is ambiguous with a parenthesized pattern; add '{}' after the close paren to disambiguate. + + A single-element deconstruct pattern requires a type before the open parenthesis. The syntax 'var' for a pattern is not permitted to bind to a type, but it binds to '{0}' here. diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 0dbc24fa1a6aa9862255ee45f60a5f2637e66b58..b31a54e232d615c85590b627b8bf09c5770809a2 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1566,7 +1566,7 @@ internal enum ErrorCode //ERR_FeatureIsUnimplemented = 8404, ERR_DefaultPattern = 8405, ERR_SwitchExpressionNoBestType = 8406, - ERR_SingleElementPositionalPattern = 8407, + ERR_SingleElementPositionalPatternRequiresType = 8407, ERR_VarMayNotBindToType = 8408, #endregion diagnostics introduced for recursive patterns diff --git a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs index 8e1f2b430e8018967c374fc6829ae15e42d98aaf..cd347f504aafecc7b55a73240ce497abacb204ac 100644 --- a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs @@ -91,7 +91,7 @@ internal enum BoundKind: byte PatternSwitchStatement, PatternSwitchStatement2, SwitchExpression, - SwitchExpressionCase, + SwitchExpressionArm, EvaluationPoint, DecisionPoint, WhereClause, @@ -2934,7 +2934,7 @@ public BoundPatternSwitchStatement2 Update(BoundExpression expression, Immutable internal sealed partial class BoundSwitchExpression : BoundExpression { - public BoundSwitchExpression(SyntaxNode syntax, BoundExpression governingExpression, ImmutableArray switchSections, TypeSymbol type, bool hasErrors = false) + public BoundSwitchExpression(SyntaxNode syntax, BoundExpression governingExpression, ImmutableArray switchSections, TypeSymbol type, bool hasErrors = false) : base(BoundKind.SwitchExpression, syntax, type, hasErrors || governingExpression.HasErrors() || switchSections.HasErrors()) { @@ -2948,14 +2948,14 @@ public BoundSwitchExpression(SyntaxNode syntax, BoundExpression governingExpress public BoundExpression GoverningExpression { get; } - public ImmutableArray SwitchSections { get; } + public ImmutableArray SwitchSections { get; } public override BoundNode Accept(BoundTreeVisitor visitor) { return visitor.VisitSwitchExpression(this); } - public BoundSwitchExpression Update(BoundExpression governingExpression, ImmutableArray switchSections, TypeSymbol type) + public BoundSwitchExpression Update(BoundExpression governingExpression, ImmutableArray switchSections, TypeSymbol type) { if (governingExpression != this.GoverningExpression || switchSections != this.SwitchSections || type != this.Type) { @@ -2967,10 +2967,10 @@ public BoundSwitchExpression Update(BoundExpression governingExpression, Immutab } } - internal sealed partial class BoundSwitchExpressionCase : BoundNode + internal sealed partial class BoundSwitchExpressionArm : BoundNode { - public BoundSwitchExpressionCase(SyntaxNode syntax, ImmutableArray locals, BoundPattern pattern, BoundExpression guard, BoundExpression value, bool hasErrors = false) - : base(BoundKind.SwitchExpressionCase, syntax, hasErrors || pattern.HasErrors() || guard.HasErrors() || value.HasErrors()) + public BoundSwitchExpressionArm(SyntaxNode syntax, ImmutableArray locals, BoundPattern pattern, BoundExpression guard, BoundExpression value, bool hasErrors = false) + : base(BoundKind.SwitchExpressionArm, syntax, hasErrors || pattern.HasErrors() || guard.HasErrors() || value.HasErrors()) { Debug.Assert(!locals.IsDefault, "Field 'locals' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); @@ -2994,14 +2994,14 @@ public BoundSwitchExpressionCase(SyntaxNode syntax, ImmutableArray public override BoundNode Accept(BoundTreeVisitor visitor) { - return visitor.VisitSwitchExpressionCase(this); + return visitor.VisitSwitchExpressionArm(this); } - public BoundSwitchExpressionCase Update(ImmutableArray locals, BoundPattern pattern, BoundExpression guard, BoundExpression value) + public BoundSwitchExpressionArm Update(ImmutableArray locals, BoundPattern pattern, BoundExpression guard, BoundExpression value) { if (locals != this.Locals || pattern != this.Pattern || guard != this.Guard || value != this.Value) { - var result = new BoundSwitchExpressionCase(this.Syntax, locals, pattern, guard, value, this.HasErrors); + var result = new BoundSwitchExpressionArm(this.Syntax, locals, pattern, guard, value, this.HasErrors); result.WasCompilerGenerated = this.WasCompilerGenerated; return result; } @@ -6939,8 +6939,8 @@ internal R VisitInternal(BoundNode node, A arg) return VisitPatternSwitchStatement2(node as BoundPatternSwitchStatement2, arg); case BoundKind.SwitchExpression: return VisitSwitchExpression(node as BoundSwitchExpression, arg); - case BoundKind.SwitchExpressionCase: - return VisitSwitchExpressionCase(node as BoundSwitchExpressionCase, arg); + case BoundKind.SwitchExpressionArm: + return VisitSwitchExpressionArm(node as BoundSwitchExpressionArm, arg); case BoundKind.EvaluationPoint: return VisitEvaluationPoint(node as BoundEvaluationPoint, arg); case BoundKind.DecisionPoint: @@ -7421,7 +7421,7 @@ public virtual R VisitSwitchExpression(BoundSwitchExpression node, A arg) { return this.DefaultVisit(node, arg); } - public virtual R VisitSwitchExpressionCase(BoundSwitchExpressionCase node, A arg) + public virtual R VisitSwitchExpressionArm(BoundSwitchExpressionArm node, A arg) { return this.DefaultVisit(node, arg); } @@ -8089,7 +8089,7 @@ public virtual BoundNode VisitSwitchExpression(BoundSwitchExpression node) { return this.DefaultVisit(node); } - public virtual BoundNode VisitSwitchExpressionCase(BoundSwitchExpressionCase node) + public virtual BoundNode VisitSwitchExpressionArm(BoundSwitchExpressionArm node) { return this.DefaultVisit(node); } @@ -8834,7 +8834,7 @@ public override BoundNode VisitSwitchExpression(BoundSwitchExpression node) this.VisitList(node.SwitchSections); return null; } - public override BoundNode VisitSwitchExpressionCase(BoundSwitchExpressionCase node) + public override BoundNode VisitSwitchExpressionArm(BoundSwitchExpressionArm node) { this.Visit(node.Pattern); this.Visit(node.Guard); @@ -9744,11 +9744,11 @@ public override BoundNode VisitPatternSwitchStatement2(BoundPatternSwitchStateme public override BoundNode VisitSwitchExpression(BoundSwitchExpression node) { BoundExpression governingExpression = (BoundExpression)this.Visit(node.GoverningExpression); - ImmutableArray switchSections = (ImmutableArray)this.VisitList(node.SwitchSections); + ImmutableArray switchSections = (ImmutableArray)this.VisitList(node.SwitchSections); TypeSymbol type = this.VisitType(node.Type); return node.Update(governingExpression, switchSections, type); } - public override BoundNode VisitSwitchExpressionCase(BoundSwitchExpressionCase node) + public override BoundNode VisitSwitchExpressionArm(BoundSwitchExpressionArm node) { BoundPattern pattern = (BoundPattern)this.Visit(node.Pattern); BoundExpression guard = (BoundExpression)this.Visit(node.Guard); @@ -11039,9 +11039,9 @@ public override TreeDumperNode VisitSwitchExpression(BoundSwitchExpression node, } ); } - public override TreeDumperNode VisitSwitchExpressionCase(BoundSwitchExpressionCase node, object arg) + public override TreeDumperNode VisitSwitchExpressionArm(BoundSwitchExpressionArm node, object arg) { - return new TreeDumperNode("switchExpressionCase", null, new TreeDumperNode[] + return new TreeDumperNode("switchExpressionArm", null, new TreeDumperNode[] { new TreeDumperNode("locals", node.Locals, null), new TreeDumperNode("pattern", null, new TreeDumperNode[] { Visit(node.Pattern, null) }), diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IsOperator.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IsOperator.cs index e0e1918731503ba96d3bcdcc85d77f3893095bf9..d16e9c77910bb0692c02413a33d4ea62ccee23fc 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IsOperator.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IsOperator.cs @@ -62,20 +62,6 @@ public override BoundNode VisitIsOperator(BoundIsOperator node) { // operand is a reference type with bound identity or implicit conversion // We can replace the "is" instruction with a null check - - Debug.Assert((object)operandType != null); - if (operandType.TypeKind == TypeKind.TypeParameter) - { - // We need to box the type parameter even if it is a known - // reference type to ensure there are no verifier errors - rewrittenOperand = MakeConversionNode( - syntax: rewrittenOperand.Syntax, - rewrittenOperand: rewrittenOperand, - conversion: Conversion.Boxing, - rewrittenType: _compilation.GetSpecialType(SpecialType.System_Object), - @checked: false); - } - return MakeNullCheck(syntax, rewrittenOperand, BinaryOperatorKind.NotEqual); } } diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs index 297608ef477984bfa631ff949299dd8784f11758..c96b3ee3be5a8e6895c23b267650f8ef22b42363 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Patterns.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.CSharp { internal sealed partial class LocalRewriter { - private struct IsPatternExpressionLocalRewriter : IDisposable + private struct IsPatternExpressionLocalRewriter { private readonly LocalRewriter _localRewriter; private readonly SyntheticBoundNodeFactory _factory; @@ -45,14 +45,14 @@ public IsPatternExpressionLocalRewriter(LocalRewriter localRewriter, BoundExpres this._sideEffectBuilder = ArrayBuilder.GetInstance(); } - public void Dispose() + public void Free() { _conjunctBuilder.Free(); _sideEffectBuilder.Free(); - _tempAllocator.Dispose(); + _tempAllocator.Free(); } - public class DagTempAllocator : IDisposable + public class DagTempAllocator { private readonly SyntheticBoundNodeFactory _factory; private readonly PooledDictionary _map = PooledDictionary.GetInstance(); @@ -63,7 +63,7 @@ public DagTempAllocator(SyntheticBoundNodeFactory factory) this._factory = factory; } - public void Dispose() + public void Free() { _temps.Free(); _map.Free(); @@ -289,15 +289,16 @@ public BoundExpression LowerIsPattern(BoundPattern pattern, CSharpCompilation co result = (result == null) ? conjunct : _factory.LogicalAnd(result, conjunct); } - var bindingsBuilder = ArrayBuilder.GetInstance(); + var bindingsBuilder = ArrayBuilder.GetInstance(bindings.Length); foreach ((BoundExpression left, BoundDagTemp right) in bindings) { bindingsBuilder.Add(_factory.AssignmentExpression(left, _tempAllocator.GetTemp(right))); } - if (bindingsBuilder.Count > 0) + var bindingAssignments = bindingsBuilder.ToImmutableAndFree(); + if (bindingAssignments.Length > 0) { - BoundSequence c = _factory.Sequence(ImmutableArray.Empty, bindingsBuilder.ToImmutableAndFree(), _factory.Literal(true)); + BoundSequence c = _factory.Sequence(ImmutableArray.Empty, bindingAssignments, _factory.Literal(true)); result = (result == null) ? c : (BoundExpression)_factory.LogicalAnd(result, c); } else if (result == null) @@ -374,10 +375,10 @@ public override BoundNode VisitIsPatternExpression(BoundIsPatternExpression node { BoundExpression loweredExpression = VisitExpression(node.Expression); BoundPattern loweredPattern = LowerPattern(node.Pattern); - using (var x = new IsPatternExpressionLocalRewriter(this, loweredExpression)) - { - return x.LowerIsPattern(loweredPattern, this._compilation); - } + var isPatternRewriter = new IsPatternExpressionLocalRewriter(this, loweredExpression); + BoundExpression result = isPatternRewriter.LowerIsPattern(loweredPattern, this._compilation); + isPatternRewriter.Free(); + return result; } BoundPattern LowerPattern(BoundPattern pattern) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs index aed40056f80468405bc4dee369edf7d45c42582e..f7c28bafe872dcb266ea3dba941e7e633093e68c 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser_Patterns.cs @@ -424,7 +424,7 @@ bool looksLikeCast() { // PROTOTYPE(patterns2): we parse it as a declaration pattern when we have simple designation, for compatibility. // PROTOTYPE(patterns2): can we change it to use a var pattern in all cases? - //return _syntaxFactory.VarPattern(varIdentifier, varDesignation); + // PROTOTYPE(patterns2): For example: return _syntaxFactory.VarPattern(varIdentifier, varDesignation); return _syntaxFactory.DeclarationPattern(_syntaxFactory.IdentifierName(typeIdentifierToken), varDesignation); } } @@ -454,21 +454,18 @@ bool looksLikeCast() { // There is an ambiguity between a deconstruction pattern `(` pattern `)` // and a constant expression pattern that happens to be parenthesized. - // We treat such syntax as a parenthesized expression always. + // Per 2017-11-20 LDM we treat such syntax as a parenthesized expression always. return _syntaxFactory.ConstantPattern(_syntaxFactory.ParenthesizedExpression(openParenToken, cp.Expression, closeParenToken)); } - - // 2017-11-20 LDM decision is to disallow a deconstruction pattern that contains just a - // single subpattern but for which the type is omitted. We'll look at other ways of disambiguating later, - // such as perhaps permitting `var` to infer the type, or a trailing comma. This also keeps the design - // space open for using parens for grouping patterns in the future, e.g. if we introduce `or` and - // `and` patterns. - - var result = _syntaxFactory.DeconstructionPattern(type, openParenToken, subPatterns, closeParenToken, propertySubpattern0, designation0); - return this.AddError(result, ErrorCode.ERR_SingleElementPositionalPattern); } - return _syntaxFactory.DeconstructionPattern(type, openParenToken, subPatterns, closeParenToken, propertySubpattern0, designation0); + var result = _syntaxFactory.DeconstructionPattern(type, openParenToken, subPatterns, closeParenToken, propertySubpattern0, designation0); + + // 2017-11-20 LDM decision is to disallow a deconstruction pattern that contains just a + // single subpattern but for which the type is omitted. + // This keeps the design space open for using parentheses for grouping patterns in the future, e.g. if we introduce `or` and + // `and` patterns. We may add other ways to disambiguate later (e.g. a property subpattern or a trailing comma inside the parens). + return (type == null && subPatterns.Count == 1) ? this.AddError(result, ErrorCode.ERR_SingleElementPositionalPatternRequiresType) : result; } if (parsePropertySubpattern(out PropertySubpatternSyntax propertySubpattern)) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs index dc20d77f33f4990cc7adba71331dffeae8eec2fb..ff7e3252fda31b28f27fb54bcb92b6d3f645209f 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests.cs @@ -43,7 +43,7 @@ public static void Main() public Vec(int x) {} } "; - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular6).VerifyDiagnostics( + CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular6).VerifyDiagnostics( // (7,18): error CS8059: Feature 'binary literals' is not available in C# 6. Please use language version 7.0 or greater. // int i1 = 0b001010; // binary literals Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "").WithArguments("binary literals", "7.0").WithLocation(7, 18), @@ -68,7 +68,7 @@ public static void Main() ); // enables binary literals, digit separators, local functions, ref locals, pattern matching - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe).VerifyDiagnostics( + CreateStandardCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( // (8,13): warning CS0219: The variable 'i2' is assigned but its value is never used // int i2 = 23_554; // digit separators Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "i2").WithArguments("i2").WithLocation(8, 13), @@ -107,7 +107,7 @@ 3. 12 4. 12 5. 7. True"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // warning CS0184: The given expression is never of the provided ('bool') type // Console.WriteLine("7. {0}", (x is bool is bool)); @@ -136,7 +136,7 @@ public static void T(object x) if (x is Nullable y) Console.WriteLine($""expression {x} is Nullable y""); } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (11,18): error CS8105: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead. // if (x is Nullable y) Console.WriteLine($"expression {x} is Nullable y"); @@ -170,7 +170,7 @@ public static void Test(object x) Console.WriteLine($""expression {x} is not {typeof(T).Name}""); } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( ); using (new EnsureInvariantCulture()) @@ -207,7 +207,7 @@ public static void Main() if (b is 1000) { } // error: cannot convert 1000 to byte } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (10,13): error CS8117: Invalid operand for pattern match; value required, but found ''. // if (null is dynamic t) { } // null not allowed @@ -250,7 +250,7 @@ class D public D(bool b) { Console.WriteLine(b); } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); #if ALLOW_IN_CONSTRUCTOR_INITIALIZER compilation.VerifyDiagnostics( ); @@ -298,7 +298,7 @@ private static void M(object o) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); using (new EnsureInvariantCulture()) { @@ -333,7 +333,7 @@ private static bool M(object o, bool result) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); #if ALLOW_IN_FIELD_INITIALIZER compilation.VerifyDiagnostics(); using (new EnsureInvariantCulture()) @@ -383,7 +383,7 @@ private static bool M(object o, bool result) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); using (new EnsureInvariantCulture()) { @@ -419,7 +419,7 @@ private static bool M(object o, bool result) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); using (new EnsureInvariantCulture()) { @@ -457,7 +457,7 @@ private static bool M(object o, bool result) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); using (new EnsureInvariantCulture()) { @@ -485,7 +485,7 @@ private static void M(string p = """" is object o ? o.ToString() : """") } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (2,11): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // [Obsolete("" is string s ? s : "")] @@ -531,7 +531,7 @@ private static bool M(object o, bool result) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); using (new EnsureInvariantCulture()) { @@ -584,7 +584,7 @@ public static void Main() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); using (new EnsureInvariantCulture()) { @@ -626,7 +626,7 @@ public static void Main() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (8,45): error CS0165: Use of unassigned local variable 'x2' // if (!(o is X x2)) Console.WriteLine(x2); @@ -660,7 +660,7 @@ public static void Main() public static void M2(out int x) { x = 1; } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( ); } @@ -701,7 +701,7 @@ static bool Dummy(bool x, object y, object z) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"1 true @@ -751,7 +751,7 @@ static bool Dummy(bool x, object y, object z) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"1 3"); @@ -792,7 +792,7 @@ static bool Dummy(int x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"1 True"); @@ -844,7 +844,7 @@ static bool Print(object x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (14,47): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. // from x2 in new[] { 2 is var y2 && Print(y2) ? 1 : 0} @@ -938,7 +938,7 @@ static bool Print(object x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"1 @@ -973,7 +973,7 @@ static bool Dummy(int x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"1 True"); } @@ -1002,7 +1002,7 @@ static bool Dummy(int x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"2 True 1 @@ -1030,7 +1030,7 @@ static bool Dummy(int x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); #if ALLOW_IN_FIELD_INITIALIZER CompileAndVerify(compilation, expectedOutput: @"1 True"); @@ -1070,7 +1070,7 @@ static bool Dummy(System.Func x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); #if ALLOW_IN_FIELD_INITIALIZER CompileAndVerify(compilation, expectedOutput: @"1 True @@ -1110,7 +1110,7 @@ static bool Dummy(int x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"1 True"); } @@ -1136,7 +1136,7 @@ static bool Dummy(int x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); #if ALLOW_IN_FIELD_INITIALIZER CompileAndVerify(compilation, expectedOutput: @"1 True"); @@ -1171,7 +1171,7 @@ static bool Dummy(int x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"1 True"); } @@ -1215,7 +1215,7 @@ public C(object b) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); #if ALLOW_IN_CONSTRUCTOR_INITIALIZER CompileAndVerify(compilation, expectedOutput: @"1 @@ -1274,7 +1274,7 @@ public C(System.Func b) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"2 True @@ -1314,7 +1314,7 @@ static void Test1(int val) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"Test1 case 0 Test1 {0} @@ -1360,7 +1360,7 @@ static bool Dummy(bool x, object y, object z) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"1 3"); @@ -1423,7 +1423,7 @@ public override string ToString() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"a b @@ -1473,7 +1473,7 @@ public override string ToString() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"b d @@ -1527,7 +1527,7 @@ public override string ToString() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"b"); var tree = compilation.SyntaxTrees.Single(); @@ -1579,7 +1579,7 @@ public override string ToString() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + var compilation = CreateStandardCompilation(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"b @@ -1636,7 +1636,7 @@ public override string ToString() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + var compilation = CreateStandardCompilation(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"b"); @@ -1694,7 +1694,7 @@ public override string ToString() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + var compilation = CreateStandardCompilation(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"b @@ -1772,7 +1772,7 @@ public override string ToString() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + var compilation = CreateStandardCompilation(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"b @@ -1832,7 +1832,7 @@ static bool Dummy(bool x, object y, object z) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"1 1 @@ -1877,7 +1877,7 @@ static bool Dummy(bool x, object y, object z) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"1 3"); @@ -1926,7 +1926,7 @@ static bool Dummy(bool x, object y, object z) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"1 2 @@ -1979,7 +1979,7 @@ static bool Dummy(bool x, object y, object z, System.Collections.Generic.List'. // if (null is 1) {} Diagnostic(ErrorCode.ERR_BadPatternExpression, "null").WithArguments("").WithLocation(6, 13), @@ -3745,7 +3745,7 @@ public static void Main() } } "; - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe).VerifyDiagnostics( + CreateStandardCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( // (6,13): error CS8179: Predefined type 'System.ValueTuple`2' is not defined or imported // if ((1, null) is Program) {} Diagnostic(ErrorCode.ERR_PredefinedValueTupleTypeNotFound, "(1, null)").WithArguments("System.ValueTuple`2").WithLocation(6, 13), @@ -3904,7 +3904,7 @@ static int Ver(string s) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: @@ -3937,7 +3937,7 @@ static int M(int? data) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: @@ -3970,7 +3970,7 @@ static string M(object data) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: @@ -4049,7 +4049,7 @@ public static void Main(string[] args) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: @@ -4086,7 +4086,7 @@ class MyException : Exception } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: @@ -4124,7 +4124,7 @@ class B public static int operator +(bool left, B right) => 8; } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular6).VerifyDiagnostics( // (15,27): error CS8059: Feature 'pattern matching' is not available in C# 6. Please use language version 7.0 or greater. // Console.WriteLine(3 is One + 2); // should print True @@ -4139,7 +4139,7 @@ class B 7 True True"; - compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: expectedOutput); } @@ -4186,7 +4186,7 @@ class D {} no True yes"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: expectedOutput); } @@ -4217,7 +4217,7 @@ class D {} var expectedOutput = @"True B"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: expectedOutput); @@ -4268,7 +4268,7 @@ class nameof { } False False True"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: expectedOutput); } @@ -4595,7 +4595,7 @@ override public bool Equals(object other) override public int GetHashCode() => 0; } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: @"False False @@ -4622,7 +4622,7 @@ public static void Main() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: "True"); } @@ -4652,7 +4652,7 @@ public class Color public const string Constant = ""abc""; } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: "True"); } @@ -4721,7 +4721,7 @@ public static void Main(string[] args) } private static object M() => null; }"; - CreateCompilationWithMscorlib45(program).VerifyDiagnostics( + CreateStandardCompilation(program).VerifyDiagnostics( // (6,17): error CS8119: The switch expression must be a value; found 'lambda expression'. // switch ((() => 1)) Diagnostic(ErrorCode.ERR_SwitchExpressionValueExpected, "(() => 1)").WithArguments("lambda expression").WithLocation(6, 17), @@ -4751,7 +4751,7 @@ public static void Main(string[] args) } private static object M() => null; }"; - CreateCompilationWithMscorlib45(program).VerifyDiagnostics( + CreateStandardCompilation(program).VerifyDiagnostics( // (6,17): error CS8119: The switch expression must be a value; found 'lambda expression'. // switch ((() => 1)) Diagnostic(ErrorCode.ERR_SwitchExpressionValueExpected, "(() => 1)").WithArguments("lambda expression").WithLocation(6, 17), @@ -4774,7 +4774,7 @@ public static void Main(string[] args) } private static object M() => null; }"; - CreateCompilationWithMscorlib45(program).VerifyDiagnostics( + CreateStandardCompilation(program).VerifyDiagnostics( // (6,13): error CS8117: Invalid operand for pattern match; value required, but found ''. // if (null is M) {} Diagnostic(ErrorCode.ERR_BadPatternExpression, "null").WithArguments("").WithLocation(6, 13), @@ -4807,7 +4807,7 @@ public static void Main(string[] args) } private static object M() => null; }"; - CreateCompilationWithMscorlib45(program).VerifyDiagnostics( + CreateStandardCompilation(program).VerifyDiagnostics( // (10,18): error CS0266: Cannot implicitly convert type 'double' to 'int?'. An explicit conversion exists (are you missing a cast?) // case double.NaN: Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "double.NaN").WithArguments("double", "int?").WithLocation(10, 18), @@ -4837,7 +4837,7 @@ public static void Main(object o) } private static object M() => null; }"; - var compilation = CreateCompilationWithMscorlib45(program).VerifyDiagnostics( + var compilation = CreateStandardCompilation(program).VerifyDiagnostics( // (9,32): error CS1525: Invalid expression term 'break' // case Color? Color2: Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("break").WithLocation(9, 32), @@ -4879,7 +4879,7 @@ public static void Main(string[] args) } private static object M() => null; }"; - var compilation = CreateCompilationWithMscorlib45(program).VerifyDiagnostics( + var compilation = CreateStandardCompilation(program).VerifyDiagnostics( // (9,18): error CS0150: A constant value is expected // case true ? x3 : 4: Diagnostic(ErrorCode.ERR_ConstantExpected, "true ? x3 : 4").WithLocation(9, 18) @@ -4989,7 +4989,7 @@ public static void Main(string[] args) throw null; } var program = string.Format(body, dt, statement); - CreateCompilationWithMscorlib45(program).GetDiagnostics(); + CreateStandardCompilation(program).GetDiagnostics(); } [Fact, WorkItem(16671, "https://github.com/dotnet/roslyn/issues/16671")] @@ -5034,7 +5034,7 @@ class Derived : Base { } "; - var compilation = CreateCompilationWithMscorlib45(program, options: TestOptions.DebugExe).VerifyDiagnostics( + var compilation = CreateStandardCompilation(program, options: TestOptions.DebugExe).VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: @"TBase TDerived @@ -5077,7 +5077,7 @@ class Derived : Base { } "; - var compilation = CreateCompilationWithMscorlib45(program).VerifyDiagnostics( + var compilation = CreateStandardCompilation(program).VerifyDiagnostics( // (12,18): error CS8120: The switch case has already been handled by a previous case. // case TDerived td: Diagnostic(ErrorCode.ERR_PatternIsSubsumed, "TDerived td").WithLocation(12, 18), @@ -5106,7 +5106,7 @@ public class Program } } "; - var compilation = CreateCompilationWithMscorlib45(program).VerifyDiagnostics( + var compilation = CreateStandardCompilation(program).VerifyDiagnostics( // (11,18): error CS8120: The switch case has already been handled by a previous case. // case IEnumerable s: Diagnostic(ErrorCode.ERR_PatternIsSubsumed, "IEnumerable s").WithLocation(11, 18), @@ -5161,7 +5161,7 @@ public static void Main(string[] args) } } "; - var compilation = CreateCompilationWithMscorlib45(program, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(program, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: @"1 @@ -5240,7 +5240,7 @@ public static void Main() False True False"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: expectedOutput); @@ -5260,7 +5260,7 @@ public static void Main() Console.WriteLine(1 is null); } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (7,32): error CS0266: Cannot implicitly convert type 'long' to 'byte'. An explicit conversion exists (are you missing a cast?) // Console.WriteLine(b is 12L); @@ -5539,7 +5539,7 @@ void M15() M14a M15a "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: expectedOutput); @@ -5613,7 +5613,7 @@ static void M1(object o) } } "; - var compilation = CreateCompilationWithMscorlib45(source); + var compilation = CreateStandardCompilation(source); compilation.VerifyDiagnostics( // (9,13): error CS0152: The switch statement contains multiple cases with the label value 'default' // default: @@ -5651,7 +5651,7 @@ static void M2(object o) } } "; - var compilation = CreateCompilationWithMscorlib45(source); + var compilation = CreateStandardCompilation(source); compilation.VerifyDiagnostics( // (9,13): error CS8120: The switch case has already been handled by a previous case. // case 2: @@ -5713,7 +5713,7 @@ public static void Main(string[] args) } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe); var comp = CompileAndVerify(compilation, expectedOutput: "roslyn"); } @@ -5746,7 +5746,7 @@ public static void Main(string[] args) } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7); + var compilation = CreateStandardCompilation(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7); compilation.VerifyDiagnostics( // (13,28): error CS9003: An expression of type 'T' cannot be handled by a pattern of type 'Derived' in C# 7.0. Please use language version 7.1 or greater. // Console.Write(x is Derived b0); @@ -5755,7 +5755,7 @@ public static void Main(string[] args) // case Derived b1: Diagnostic(ErrorCode.ERR_PatternWrongGenericTypeInVersion, "Derived").WithArguments("T", "Derived", "7.0", "7.1").WithLocation(16, 18) ); - compilation = CreateCompilationWithMscorlib45(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7_1); + compilation = CreateStandardCompilation(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7_1); compilation.VerifyDiagnostics(); CompileAndVerify(compilation, expectedOutput: "True1False0"); } @@ -5789,7 +5789,7 @@ public static void M(Base x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7); + var compilation = CreateStandardCompilation(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7); compilation.VerifyDiagnostics( // (13,28): error CS9003: An expression of type 'Base' cannot be handled by a pattern of type 'T' in C# 7.0. Please use language version 7.1 or greater. // Console.Write(x is T b0); @@ -5798,7 +5798,7 @@ public static void M(Base x) // case T b1: Diagnostic(ErrorCode.ERR_PatternWrongGenericTypeInVersion, "T").WithArguments("Base", "T", "7.0", "7.1") ); - compilation = CreateCompilationWithMscorlib45(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7_1); + compilation = CreateStandardCompilation(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7_1); compilation.VerifyDiagnostics(); CompileAndVerify(compilation, expectedOutput: "True1False0"); } @@ -5832,7 +5832,7 @@ public static void Main(string[] args) } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7); + var compilation = CreateStandardCompilation(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7); compilation.VerifyDiagnostics( // (13,28): error CS9003: An expression of type 'T' cannot be handled by a pattern of type 'Derived' in C# 7.0. Please use language version 7.1 or greater. // Console.Write(x is Derived b0); @@ -5841,7 +5841,7 @@ public static void Main(string[] args) // case Derived b1: Diagnostic(ErrorCode.ERR_PatternWrongGenericTypeInVersion, "Derived").WithArguments("T", "Derived", "7.0", "7.1").WithLocation(16, 18) ); - compilation = CreateCompilationWithMscorlib45(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7_1); + compilation = CreateStandardCompilation(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7_1); compilation.VerifyDiagnostics(); CompileAndVerify(compilation, expectedOutput: "True1False0"); } @@ -5878,7 +5878,7 @@ public static void Main(string[] args) } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7); + var compilation = CreateStandardCompilation(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7); compilation.VerifyDiagnostics( // (16,28): error CS9003: An expression of type 'T' cannot be handled by a pattern of type 'Container.Derived' in C# 7.0. Please use language version 7.1 or greater. // Console.Write(x is Container.Derived b0); @@ -5887,7 +5887,7 @@ public static void Main(string[] args) // case Container.Derived b1: Diagnostic(ErrorCode.ERR_PatternWrongGenericTypeInVersion, "Container.Derived").WithArguments("T", "Container.Derived", "7.0", "7.1").WithLocation(19, 18) ); - compilation = CreateCompilationWithMscorlib45(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7_1); + compilation = CreateStandardCompilation(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7_1); compilation.VerifyDiagnostics(); CompileAndVerify(compilation, expectedOutput: "True1False0"); } @@ -5924,7 +5924,7 @@ public static void Main(string[] args) } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7); + var compilation = CreateStandardCompilation(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7); compilation.VerifyDiagnostics( // (16,28): error CS9003: An expression of type 'T[]' cannot be handled by a pattern of type 'Container.Derived[]' in C# 7.0. Please use language version 7.1 or greater. // Console.Write(x is Container.Derived[] b0); @@ -5933,7 +5933,7 @@ public static void Main(string[] args) // case Container.Derived[] b1: Diagnostic(ErrorCode.ERR_PatternWrongGenericTypeInVersion, "Container.Derived[]").WithArguments("T[]", "Container.Derived[]", "7.0", "7.1").WithLocation(19, 18) ); - compilation = CreateCompilationWithMscorlib45(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7_1); + compilation = CreateStandardCompilation(source, references: new MetadataReference[] { CSharpRef, SystemCoreRef }, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7_1); compilation.VerifyDiagnostics(); CompileAndVerify(compilation, expectedOutput: "True1False0"); } @@ -6410,7 +6410,7 @@ private static void Main() } "; var expectedOutput = @"Exception"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: expectedOutput); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests2.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests2.cs index b8e012bc46294bcc5c2b56d57db090a43bb7a869..1cc19be28fcde551d65c4d97dacb2ebcf3e7e497 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests2.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests2.cs @@ -16,6 +16,11 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests [CompilerTrait(CompilerFeature.Patterns)] public class PatternMatchingTests2 : PatternMatchingTestBase { + CSharpCompilation CreatePatternCompilation(string source) + { + return CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); + } + [Fact] public void Patterns2_00() { @@ -30,7 +35,7 @@ public static void Main() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); + var compilation = CreatePatternCompilation(source); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: @"1"); @@ -72,7 +77,7 @@ public void Deconstruct(out int X, out int Y) public int Length => 5; } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); + var compilation = CreatePatternCompilation(source); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: ""); @@ -117,6 +122,7 @@ public static void Deconstruct(this Point p, out int X, out int Y) } } "; + // We use a compilation profile that provides System.Runtime.CompilerServices.ExtensionAttribute needed for this test var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); compilation.VerifyDiagnostics( ); @@ -163,7 +169,7 @@ public ValueTuple(T1 item1, T2 item2) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); + var compilation = CreatePatternCompilation(source); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: ""); @@ -205,7 +211,7 @@ public void Deconstruct(out int X, out int Y) public int Length => 5; } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); + var compilation = CreatePatternCompilation(source); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: ""); @@ -248,7 +254,7 @@ public ValueTuple(T1 item1, T2 item2) void testErrorCase(string s1, string s2, string s3) { var source = string.Format(sourceTemplate, s1, s2, s3); - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); + var compilation = CreatePatternCompilation(source); compilation.VerifyDiagnostics( // (12,13): error CS8120: The switch case has already been handled by a previous case. // case (_, _): // error - subsumed @@ -258,7 +264,7 @@ void testErrorCase(string s1, string s2, string s3) void testGoodCase(string s1, string s2) { var source = string.Format(sourceTemplate, s1, s2, string.Empty); - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); + var compilation = CreatePatternCompilation(source); compilation.VerifyDiagnostics( ); } @@ -310,7 +316,7 @@ public void Deconstruct(out int X, out int Y) public int Length => 5; } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); + var compilation = CreatePatternCompilation(source); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: "True"); @@ -346,7 +352,7 @@ public ValueTuple(T1 item1, T2 item2) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); + var compilation = CreatePatternCompilation(source); compilation.VerifyDiagnostics( // (6,18): error CS8405: A default literal 'default' is not valid as a pattern. Use another literal (e.g. '0' or 'null') as appropriate. To match everything, use a discard pattern '_'. // if (i is default) {} // error 1 @@ -378,7 +384,7 @@ public static void Main() var r = 1 switch { _ => 0 }; } }"; - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe).VerifyDiagnostics( + CreateStandardCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( // (5,17): error CS8058: Feature 'recursive patterns' is experimental and unsupported; use '/features:patterns2' to enable. // var r = 1 switch ( _ => 0 ); Diagnostic(ErrorCode.ERR_FeatureIsExperimental, "1 switch { _ => 0 }").WithArguments("recursive patterns", "patterns2").WithLocation(5, 17) @@ -413,7 +419,7 @@ public ValueTuple(T1 item1, T2 item2) } } }"; - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns).VerifyDiagnostics( + CreatePatternCompilation(source).VerifyDiagnostics( // (5,18): error CS8117: Invalid operand for pattern match; value required, but found '(int, )'. // var r1 = (1, null) switch ( _ => 0 ); Diagnostic(ErrorCode.ERR_BadPatternExpression, "(1, null)").WithArguments("(int, )").WithLocation(5, 18), @@ -440,7 +446,7 @@ public static void Main() }"; // PROTOTYPE(patterns2): This is admittedly poor syntax error recovery (for the line declaring r2), // but this test demonstrates that it is a syntax error. - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns).VerifyDiagnostics( + CreatePatternCompilation(source).VerifyDiagnostics( // (6,34): error CS1003: Syntax error, '=>' expected // var r1 = b switch { true ? true : true => true, false => false }; Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments("=>", "?").WithLocation(6, 34), @@ -515,7 +521,7 @@ public ValueTuple(T1 item1, T2 item2) } } }"; - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns).VerifyDiagnostics( + CreatePatternCompilation(source).VerifyDiagnostics( ); } @@ -531,7 +537,7 @@ public static void Main() var x = 1 switch { 1 => 1, _ => throw null }; } }"; - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns).VerifyDiagnostics( + CreatePatternCompilation(source).VerifyDiagnostics( ); } @@ -550,7 +556,7 @@ public static void Main() public static void M() {} public delegate void D(); }"; - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns).VerifyDiagnostics( + CreatePatternCompilation(source).VerifyDiagnostics( ); } @@ -569,7 +575,7 @@ public static void Main() System.Console.WriteLine(u); } }"; - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns).VerifyDiagnostics( + CreatePatternCompilation(source).VerifyDiagnostics( ); } @@ -589,7 +595,7 @@ public static void Main() } static int M(int i) => i; }"; - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns).VerifyDiagnostics( + CreatePatternCompilation(source).VerifyDiagnostics( // (8,34): error CS0165: Use of unassigned local variable 'u' // System.Console.WriteLine(u); Diagnostic(ErrorCode.ERR_UseDefViolation, "u").WithArguments("u").WithLocation(8, 34) @@ -612,7 +618,7 @@ public static void Main() } static int M(int i) => i; }"; - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns).VerifyDiagnostics( + CreatePatternCompilation(source).VerifyDiagnostics( // (7,47): error CS0165: Use of unassigned local variable 'u' // var x = q switch { 0 => u=0, 1 => u=M(u), _ => u=2 }; Diagnostic(ErrorCode.ERR_UseDefViolation, "u").WithArguments("u").WithLocation(7, 47) @@ -637,7 +643,7 @@ public static void Main() } static int M(int i) => i; }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); + var compilation = CreatePatternCompilation(source); compilation.VerifyDiagnostics( ); var names = new[] { "x1", "x2", "x3", "x4", "x5" }; @@ -670,7 +676,7 @@ public static void Main() if (a is _) { } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); + var compilation = CreatePatternCompilation(source); compilation.VerifyDiagnostics( // (6,18): error CS0246: The type or namespace name '_' could not be found (are you missing a using directive or an assembly reference?) // if (a is _) { } @@ -693,10 +699,10 @@ public static void Main() if (t is (int x)) { } // error 1 switch (t) { case (_): break; } // error 2 var u = t switch { (int y) => y, _ => 2 }; // error 3 - if (t is (int z1) _) { } // ok - if (t is (Item1: int z2)) { } // ok - if (t is (int z3) { }) { } // ok - if (t is ValueTuple(int z4)) { } // ok + if (t is (int z1) _) { } // error 4 + if (t is (Item1: int z2)) { } // error 5 + if (t is (int z3) { }) { } // error 6 + if (t is ValueTuple(int z4)) { } // ok } private static bool Check(T expected, T actual) { @@ -715,18 +721,27 @@ public ValueTuple(T item1) this.Item1 = item1; } } -}"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); +}";; + var compilation = CreatePatternCompilation(source); compilation.VerifyDiagnostics( - // (8,18): error CS8407: A single-element deconstruct pattern is ambiguous with a parenthesized pattern; add '{}' after the close paren to disambiguate. + // (8,18): error CS8407: A single-element deconstruct pattern requires a type before the open parenthesis. // if (t is (int x)) { } // error 1 - Diagnostic(ErrorCode.ERR_SingleElementPositionalPattern, "(int x)").WithLocation(8, 18), - // (9,27): error CS8407: A single-element deconstruct pattern is ambiguous with a parenthesized pattern; add '{}' after the close paren to disambiguate. + Diagnostic(ErrorCode.ERR_SingleElementPositionalPatternRequiresType, "(int x)").WithLocation(8, 18), + // (9,27): error CS8407: A single-element deconstruct pattern requires a type before the open parenthesis. // switch (t) { case (_): break; } // error 2 - Diagnostic(ErrorCode.ERR_SingleElementPositionalPattern, "(_)").WithLocation(9, 27), - // (10,28): error CS8407: A single-element deconstruct pattern is ambiguous with a parenthesized pattern; add '{}' after the close paren to disambiguate. + Diagnostic(ErrorCode.ERR_SingleElementPositionalPatternRequiresType, "(_)").WithLocation(9, 27), + // (10,28): error CS8407: A single-element deconstruct pattern requires a type before the open parenthesis. // var u = t switch { (int y) => y, _ => 2 }; // error 3 - Diagnostic(ErrorCode.ERR_SingleElementPositionalPattern, "(int y)").WithLocation(10, 28) + Diagnostic(ErrorCode.ERR_SingleElementPositionalPatternRequiresType, "(int y)").WithLocation(10, 28), + // (11,18): error CS8407: A single-element deconstruct pattern requires a type before the open parenthesis. + // if (t is (int z1) _) { } // error 4 + Diagnostic(ErrorCode.ERR_SingleElementPositionalPatternRequiresType, "(int z1) _").WithLocation(11, 18), + // (12,18): error CS8407: A single-element deconstruct pattern requires a type before the open parenthesis. + // if (t is (Item1: int z2)) { } // error 5 + Diagnostic(ErrorCode.ERR_SingleElementPositionalPatternRequiresType, "(Item1: int z2)").WithLocation(12, 18), + // (13,18): error CS8407: A single-element deconstruct pattern requires a type before the open parenthesis. + // if (t is (int z3) { }) { } // error 6 + Diagnostic(ErrorCode.ERR_SingleElementPositionalPatternRequiresType, "(int z3) { }").WithLocation(13, 18) ); } @@ -766,7 +781,7 @@ public ValueTuple(T1 item1, T2 item2) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); + var compilation = CreatePatternCompilation(source); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: @""); @@ -811,7 +826,7 @@ public ValueTuple(T1 item1, T2 item2) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns); + var compilation = CreatePatternCompilation(source); compilation.VerifyDiagnostics( // (9,21): error CS0029: Cannot implicitly convert type '(int, int)' to 'N.var' // var t = (1, 2); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Scope.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Scope.cs index c4e8c499a9d7becf2a526592bf4e8ef4203e2b42..46febabf3e8ed7cf86c855a8b0931a0b65c6cd8e 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Scope.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_Scope.cs @@ -59,7 +59,7 @@ static bool TakeOutParam(T y, out T x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( // (14,52): error CS0136: A local or parameter named 'x14' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter @@ -163,7 +163,7 @@ void Test12() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (14,31): error CS0136: A local or parameter named 'x1' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter @@ -355,7 +355,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (15,9): error CS0103: The name 'x1' does not exist in the current context @@ -391,7 +391,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -434,7 +434,7 @@ void Test1(object o1, object o2) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (13,25): error CS0128: A local variable named 'i' is already defined in this scope @@ -539,7 +539,7 @@ object Test12() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (14,38): error CS0136: A local or parameter named 'x1' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter @@ -660,7 +660,7 @@ int Test1(bool val) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (15,9): error CS0103: The name 'x1' does not exist in the current context @@ -696,7 +696,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -812,7 +812,7 @@ void Test12() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (14,37): error CS0136: A local or parameter named 'x1' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter @@ -929,7 +929,7 @@ void Test1(bool val) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (15,9): error CS0103: The name 'x1' does not exist in the current context @@ -965,7 +965,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -1111,7 +1111,7 @@ void Test12() //} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (110,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var y12 = 12; @@ -1234,7 +1234,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (17,9): error CS0103: The name 'x1' does not exist in the current context // x1++; @@ -1269,7 +1269,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -1383,7 +1383,7 @@ void Test12() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (12,27): error CS1002: ; expected // return (o) => let x1 = o; @@ -1659,7 +1659,7 @@ void Test11() } } "; - var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (23,48): error CS8201: Out variable and pattern variable declarations are not allowed within a query clause. // from x2 in new[] { x1 is var z2 ? z2 : 0, z2, y2} @@ -2006,7 +2006,7 @@ into g } } "; - var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (18,35): error CS0103: The name 'v4' does not exist in the current context // v4 @@ -2154,7 +2154,7 @@ into s } } "; - var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (16,47): error CS0128: A local variable or function named 'y1' is already defined in this scope // var res = from x1 in new[] { 1 is var y1 ? y1 : 0} @@ -2310,7 +2310,7 @@ into s } } "; - var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (26,47): error CS0128: A local variable or function named 'y1' is already defined in this scope // from x1 in new[] { 1 is var y1 ? y1 : 0} @@ -2438,7 +2438,7 @@ into x1 } } "; - var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (18,47): error CS0128: A local variable named 'y3' is already defined in this scope // join x3 in new[] { 3 is var y3 ? y3 : 0} @@ -2492,7 +2492,7 @@ into y4 } } "; - var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (19,24): error CS1931: The range variable 'y1' conflicts with a previous declaration of 'y1' // from y1 in new[] { 1 } @@ -2559,7 +2559,7 @@ into x2 } } "; - var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (14,24): error CS1931: The range variable 'y1' conflicts with a previous declaration of 'y1' // var res = from y1 in new[] { 0 } @@ -2698,7 +2698,7 @@ void Test10() } } "; - var compilation = CreateCompilationWithMscorlib45(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, new[] { SystemCoreRef }, options: TestOptions.DebugExe); // error CS0412 is misleading and reported due to preexisting bug https://github.com/dotnet/roslyn/issues/12052 compilation.VerifyDiagnostics( @@ -2886,7 +2886,7 @@ System.Action Test13() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (12,33): error CS1002: ; expected // void f(object o) => let x1 = o; @@ -3011,7 +3011,7 @@ static bool Dummy(int x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); CompileAndVerify(compilation, expectedOutput: @"1 True"); } @@ -3052,7 +3052,7 @@ public static void Main() bool Dummy(params object[] x) {return true;} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (9,33): error CS1002: ; expected // void Test1(object o) => let x1 = o; @@ -3182,7 +3182,7 @@ public static void Main() bool Dummy(params object[] x) {return true;} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (9,23): error CS1002: ; expected // bool Test1 => let x1 = 11; @@ -3289,7 +3289,7 @@ public static void Main() bool Dummy(params object[] x) {return true;} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (8,23): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. // bool Test3 = 3 is int x3 && x3 > 0; @@ -3379,7 +3379,7 @@ public enum X Test72 = x7, } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugDll); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugDll); compilation.VerifyDiagnostics( // (6,13): error CS0841: Cannot use local variable 'x4' before it is declared // Test4 = x4 && 4 is int x4 ? 1 : 0, @@ -3484,7 +3484,7 @@ public static void Main() bool Dummy(params object[] x) {return true;} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (8,29): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. // const bool Test3 = 3 is int x3 && x3 > 0; @@ -3593,7 +3593,7 @@ public static void Main() bool Dummy(params object[] x) {return true;} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (8,30): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. // bool Test3 {get;} = 3 is int x3 && x3 > 0; @@ -3699,7 +3699,7 @@ void Test72(bool p = x7 > 2) bool Dummy(params object[] x) {return true;} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (8,25): error CS1736: Default parameter value for 'p' must be a compile-time constant // void Test3(bool p = 3 is int x3 && x3 > 0) @@ -3790,7 +3790,7 @@ class Test : System.Attribute public bool p2 {get; set;} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (8,15): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // [Test(p = 3 is int x3 && x3 > 0)] @@ -3880,7 +3880,7 @@ class Test : System.Attribute public Test(bool p1, bool p2) {} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (8,11): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type // [Test(3 is int x3 && x3 > 0)] @@ -3978,7 +3978,7 @@ public static void Main() bool Dummy(params object[] x) {return true;} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (9,21): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. // : this(3 is int x3 && x3 > 0) @@ -4095,7 +4095,7 @@ public class Y public Y(params object[] x) {} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (9,21): error CS8200: Out variable and pattern variable declarations are not allowed within constructor initializers, field initializers, or property initializers. // : base(3 is int x3 && x3 > 0) @@ -4191,7 +4191,7 @@ public D(object o) : this(o is int x && x >= 5) public D(bool b) { Console.WriteLine(b); } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (15,27): error CS0103: The name 'x' does not exist in the current context // Console.WriteLine(x); @@ -4229,7 +4229,7 @@ class C public C(bool b) { Console.WriteLine(b); } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (15,27): error CS0103: The name 'x' does not exist in the current context // Console.WriteLine(x); @@ -4448,7 +4448,7 @@ void Test15(int val) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (30,31): error CS0841: Cannot use local variable 'x2' before it is declared @@ -4833,7 +4833,7 @@ void Test17(object val) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (30,31): error CS0841: Cannot use local variable 'x2' before it is declared @@ -5170,7 +5170,7 @@ void Test15(int val) //} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (27,26): error CS0128: A local variable or function named 'x4' is already defined in this scope // switch (4 is var x4 ? x4 : 0) @@ -5299,7 +5299,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (19,15): error CS0103: The name 'x1' does not exist in the current context // Dummy(x1, 1); @@ -5334,7 +5334,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -5467,7 +5467,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (87,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var y12 = 12; @@ -5674,7 +5674,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (87,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var y12 = 12; @@ -5881,7 +5881,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (87,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var y12 = 12; @@ -6008,7 +6008,7 @@ void Test2() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (12,43): error CS0128: A local variable named 'x1' is already defined in this scope // using (var x1 = Dummy(true is var x1, x1)) @@ -6095,7 +6095,7 @@ void Test4() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (13,35): error CS0128: A local variable named 'x1' is already defined in this scope // x1 = Dummy(x1)) @@ -6178,7 +6178,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (19,35): error CS0128: A local variable named 'x4' is already defined in this scope // var d = Dummy(true is var x4, x4); @@ -6265,7 +6265,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (19,38): error CS0128: A local variable named 'x4' is already defined in this scope // object d = Dummy(true is var x4, x4); @@ -6336,7 +6336,7 @@ void Test2() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (13,36): error CS0128: A local variable named 'x1' is already defined in this scope // Dummy(true is var x1, x1); @@ -6412,7 +6412,7 @@ void Test4() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (13,16): error CS0128: A local variable named 'x1' is already defined in this scope // x1 = Dummy(x1); @@ -6470,7 +6470,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -6515,7 +6515,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (11,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var d = true is var x1; @@ -6582,7 +6582,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + var compilation = CreateStandardCompilation(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( // (19,37): error CS0128: A local variable named 'x4' is already defined in this scope @@ -6671,7 +6671,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + var compilation = CreateStandardCompilation(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( // (19,47): error CS0128: A local variable named 'x4' is already defined in this scope @@ -6744,7 +6744,7 @@ void Test2() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + var compilation = CreateStandardCompilation(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( // (13,37): error CS0128: A local variable named 'x1' is already defined in this scope @@ -6822,7 +6822,7 @@ void Test4() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + var compilation = CreateStandardCompilation(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( // (12,53): error CS0128: A local variable named 'x1' is already defined in this scope @@ -6886,7 +6886,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + var compilation = CreateStandardCompilation(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); var tree = compilation.SyntaxTrees.Single(); @@ -6931,7 +6931,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, + var compilation = CreateStandardCompilation(source, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( // (13,9): error CS0103: The name 'x1' does not exist in the current context @@ -7062,7 +7062,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (87,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var y12 = 12; @@ -7179,7 +7179,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (17,9): error CS0103: The name 'x1' does not exist in the current context // x1++; @@ -7214,7 +7214,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -7360,7 +7360,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (97,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var y12 = 12; @@ -7502,7 +7502,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (18,9): error CS0103: The name 'x1' does not exist in the current context // x1++; @@ -7537,7 +7537,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -7696,7 +7696,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (109,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var y12 = 12; @@ -7928,7 +7928,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (109,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var y12 = 12; @@ -8157,7 +8157,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (109,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var y12 = 12; @@ -8415,7 +8415,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (109,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var y12 = 12; @@ -8647,7 +8647,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (109,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var y12 = 12; @@ -8885,7 +8885,7 @@ void Test15() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (13,32): error CS0128: A local variable or function named 'x1' is already defined in this scope // Dummy(true is var x1 && x1) @@ -9136,7 +9136,7 @@ void Test2() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( // (13,20): error CS0841: Cannot use local variable 'x1' before it is declared // Dummy(x1), @@ -9281,7 +9281,7 @@ void Test15() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (87,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var y12 = 12; @@ -9493,7 +9493,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (87,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var y12 = 12; @@ -9611,7 +9611,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (17,9): error CS0103: The name 'x1' does not exist in the current context // x1++; @@ -9646,7 +9646,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -9779,7 +9779,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe.WithAllowUnsafe(true)); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe.WithAllowUnsafe(true)); compilation.VerifyDiagnostics( // (87,13): error CS1023: Embedded statement cannot be a declaration or labeled statement // var y12 = 12; @@ -9923,7 +9923,7 @@ void Test4() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe.WithAllowUnsafe(true)); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe.WithAllowUnsafe(true)); compilation.VerifyDiagnostics( // (14,44): error CS0128: A local variable named 'x1' is already defined in this scope // Dummy(true is var x1 && x1)) @@ -10058,7 +10058,7 @@ IEnumerable Test12() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (16,44): error CS0136: A local or parameter named 'x1' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter @@ -10170,7 +10170,7 @@ IEnumerable Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (17,9): error CS0103: The name 'x1' does not exist in the current context @@ -10209,7 +10209,7 @@ IEnumerable Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -10352,7 +10352,7 @@ void Test15() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (25,33): error CS0136: A local or parameter named 'x4' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter // catch when (true is var x4 && x4) @@ -10531,7 +10531,7 @@ void Test12() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (65,1): error CS1023: Embedded statement cannot be a declaration or labeled statement @@ -10684,7 +10684,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (13,1): error CS1023: Embedded statement cannot be a declaration or labeled statement @@ -10726,7 +10726,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -10959,7 +10959,7 @@ void Test15(int val) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( // (32,31): error CS0841: Cannot use local variable 'x2' before it is declared @@ -11141,7 +11141,7 @@ static bool Dummy(params object[] trash) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"2").VerifyDiagnostics(); @@ -11189,7 +11189,7 @@ static bool Dummy(params object[] data) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"2").VerifyDiagnostics(); @@ -11239,7 +11239,7 @@ static bool Dummy(params object[] data) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"2").VerifyDiagnostics(); @@ -11282,7 +11282,7 @@ static bool Dummy(params object[] data) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"2").VerifyDiagnostics(); @@ -11325,7 +11325,7 @@ static bool Dummy(params object[] data) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"2").VerifyDiagnostics(); @@ -11371,7 +11371,7 @@ static bool Dummy(params object[] data) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"2").VerifyDiagnostics(); @@ -11414,7 +11414,7 @@ static bool Dummy(params object[] data) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"2").VerifyDiagnostics(); @@ -11458,7 +11458,7 @@ static bool Dummy(params object[] data) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"2 @@ -11505,7 +11505,7 @@ static bool Dummy(params object[] data) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"2 True").VerifyDiagnostics(); @@ -11555,7 +11555,7 @@ static bool Dummy(params object[] data) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: "True").VerifyDiagnostics( // (17,17): warning CS0162: Unreachable code detected @@ -11617,7 +11617,7 @@ static System.Exception Dummy(params object[] data) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation, expectedOutput: @"123 True").VerifyDiagnostics( @@ -11670,8 +11670,8 @@ static bool Dummy(params object[] data) } } "; - var compilation = CreateCompilationWithMscorlib45( - source: source, + var compilation = CreateStandardCompilation( + text: source, options: TestOptions.DebugExe, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular); @@ -11730,8 +11730,8 @@ static bool Dummy(params object[] data) } } "; - var compilation = CreateCompilationWithMscorlib45( - source: source, + var compilation = CreateStandardCompilation( + text: source, options: TestOptions.DebugExe, references: new[] { ValueTupleRef, SystemRuntimeFacadeRef }, parseOptions: TestOptions.Regular); @@ -11801,7 +11801,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_BadVarDecl, (int)ErrorCode.ERR_SyntaxError, (int)ErrorCode.WRN_UnreferencedVar @@ -11892,7 +11892,7 @@ void Test3() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_BadVarDecl, (int)ErrorCode.ERR_SyntaxError, (int)ErrorCode.WRN_UnreferencedVar @@ -11986,7 +11986,7 @@ void Test4() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_BadVarDecl, (int)ErrorCode.ERR_SyntaxError, (int)ErrorCode.WRN_UnreferencedVar, @@ -12077,7 +12077,7 @@ void Test4() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_BadVarDecl, (int)ErrorCode.ERR_SyntaxError, (int)ErrorCode.ERR_UnexpectedToken, @@ -12155,7 +12155,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -12201,7 +12201,7 @@ void Test1() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_BadVarDecl, (int)ErrorCode.ERR_SyntaxError, (int)ErrorCode.WRN_UnreferencedVar @@ -12261,7 +12261,7 @@ static void Test(int val) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); @@ -12414,7 +12414,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_BadVarDecl, (int)ErrorCode.ERR_SyntaxError, (int)ErrorCode.ERR_UnexpectedToken, @@ -12573,7 +12573,7 @@ void Test9() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_BadVarDecl, (int)ErrorCode.ERR_SyntaxError, (int)ErrorCode.ERR_UnexpectedToken, @@ -12757,7 +12757,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_BadVarDecl, (int)ErrorCode.ERR_SyntaxError, (int)ErrorCode.ERR_UnexpectedToken, @@ -12903,7 +12903,7 @@ void Test2() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_BadVarDecl, (int)ErrorCode.ERR_SyntaxError, (int)ErrorCode.WRN_UnreferencedVar, @@ -12992,7 +12992,7 @@ void Test4() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_BadVarDecl, (int)ErrorCode.ERR_SyntaxError, (int)ErrorCode.ERR_UnexpectedToken, @@ -13154,7 +13154,7 @@ void Test14() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe.WithAllowUnsafe(true), parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe.WithAllowUnsafe(true), parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_BadVarDecl, (int)ErrorCode.ERR_SyntaxError, (int)ErrorCode.ERR_UnexpectedToken, @@ -13314,7 +13314,7 @@ void Test4() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe.WithAllowUnsafe(true), parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe.WithAllowUnsafe(true), parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_BadVarDecl, (int)ErrorCode.ERR_SyntaxError, (int)ErrorCode.ERR_UnexpectedToken, @@ -13401,7 +13401,7 @@ public static void Main() bool Dummy(params object[] x) {return true;} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_CStyleArray, (int)ErrorCode.ERR_ArraySizeInDeclaration, (int)ErrorCode.WRN_UnreferencedField @@ -13479,7 +13479,7 @@ public static void Main() bool Dummy(params object[] x) {return true;} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe.WithAllowUnsafe(true), parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe.WithAllowUnsafe(true), parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_CStyleArray, (int)ErrorCode.ERR_ArraySizeInDeclaration, (int)ErrorCode.WRN_UnreferencedField, @@ -13567,7 +13567,7 @@ public static void Main() bool Dummy(params object[] x) {return true;} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_CStyleArray, (int)ErrorCode.ERR_ArraySizeInDeclaration }; @@ -13644,7 +13644,7 @@ public static void Main() bool Dummy(params object[] x) {return true;} } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_CStyleArray, (int)ErrorCode.ERR_ArraySizeInDeclaration, (int)ErrorCode.ERR_EventNotDelegate, @@ -13708,7 +13708,7 @@ public static void Main() fixed bool d[2], Test3 (string.Empty is var x3); } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe.WithAllowUnsafe(true), parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe.WithAllowUnsafe(true), parseOptions: TestOptions.Regular); int[] exclude = new int[] { (int)ErrorCode.ERR_BadVarDecl, }; @@ -13746,7 +13746,7 @@ public static void Main() fixed bool Test3[string.Empty is var x3]; } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe.WithAllowUnsafe(true), parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe.WithAllowUnsafe(true), parseOptions: TestOptions.Regular); compilation.VerifyDiagnostics( // (8,22): error CS0029: Cannot implicitly convert type 'bool' to 'int' diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternSwitchTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternSwitchTests.cs index 285ecfcddf7fb9cf2ab17b1fc921222c072a1b45..34fe951375a9f79e6c2af8d5c96ed69a5d5266de 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PatternSwitchTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PatternSwitchTests.cs @@ -31,7 +31,7 @@ public static void Main() } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); Assert.True(compilation.GetDiagnostics().HasAnyErrors()); compilation.VerifyDiagnostics( // (11,13): error CS0152: The switch statement contains multiple cases with the label value '1' @@ -63,7 +63,7 @@ public static void Main(string[] args) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); Assert.True(compilation.GetDiagnostics().HasAnyErrors()); compilation.VerifyDiagnostics( // (9,18): error CS8120: The switch case has already been handled by a previous case. @@ -94,7 +94,7 @@ public static void Main() } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (11,13): error CS8120: The switch case has already been handled by a previous case. // case 1: // error: handled previously @@ -126,7 +126,7 @@ public static void Main() } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); Assert.True(compilation.GetDiagnostics().HasAnyErrors()); compilation.VerifyDiagnostics( // (10,13): error CS8120: The switch case has already been handled by a previous case. @@ -156,7 +156,7 @@ public static void Main() } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); Assert.True(compilation.GetDiagnostics().HasAnyErrors()); compilation.VerifyDiagnostics( // (10,18): error CS0029: Cannot implicitly convert type 'string' to 'bool' @@ -187,7 +187,7 @@ public static void Main() } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); Assert.True(compilation.GetDiagnostics().HasAnyErrors()); compilation.VerifyDiagnostics( // (11,18): error CS8120: The switch case has already been handled by a previous case. @@ -280,7 +280,7 @@ public static void Main() } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (11,18): error CS8120: The switch case has already been handled by a previous case. // case var x: // error: subsumed @@ -310,7 +310,7 @@ public static void Main() } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (11,18): error CS8120: The switch case has already been handled by a previous case. // case var x: // error: subsumed by previous cases @@ -340,7 +340,7 @@ public static void Main() } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( ); } @@ -361,7 +361,7 @@ public static void Main() } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (8,18): error CS8121: An expression of type 'string' cannot be handled by a pattern of type 'int'. // case int i: // error: type mismatch. @@ -415,7 +415,7 @@ public static void M(bool? b) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var expectedOutput = @"True @@ -442,7 +442,7 @@ public static void Main() } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (10,18): error CS0037: Cannot convert null to 'bool' because it is a non-nullable value type // case null: // error: impossible given the type @@ -468,7 +468,7 @@ public static void Main() } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (10,18): error CS0029: Cannot implicitly convert type 'int' to 'bool' // case 3: // error: impossible given the type @@ -494,7 +494,7 @@ public static void Main() } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (10,18): error CS0031: Constant value '1000' cannot be converted to a 'byte' // case 1000: // error: impossible given the type @@ -522,7 +522,7 @@ public static void Main(string[] args) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (9,13): error CS8120: The switch case has already been handled by a previous case. // case 11: // error: subsumed @@ -553,7 +553,7 @@ public static void Main(string[] args) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (10,18): error CS8120: The switch case has already been handled by a previous case. // case bool b: // error: subsumed @@ -582,7 +582,7 @@ public static void Main(string[] args) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (8,17): warning CS0162: Unreachable code detected // break; // unreachable @@ -605,7 +605,7 @@ public static void Main(string[] args) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (8,17): warning CS0162: Unreachable code detected // break; // unreachable @@ -628,7 +628,7 @@ public static void Main(string[] args) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (8,17): warning CS0162: Unreachable code detected // break; // unreachable @@ -651,7 +651,7 @@ public static void Main(string[] args) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (8,17): warning CS0162: Unreachable code detected // break; // unreachable @@ -674,7 +674,7 @@ public static void Main(string[] args) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( ); } @@ -694,7 +694,7 @@ public static void Main(string[] args) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( ); } @@ -716,7 +716,7 @@ public static void Main(string[] args) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (9,13): error CS8120: The switch case has already been handled by a previous case. // case null: @@ -748,7 +748,7 @@ public static void Main() } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( ); } @@ -772,17 +772,17 @@ public static void Main() } } }"; - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular6).VerifyDiagnostics( + CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular6).VerifyDiagnostics( // (10,18): error CS0029: Cannot implicitly convert type 'string' to 'bool' // case "goo": // wrong type Diagnostic(ErrorCode.ERR_NoImplicitConv, @"""goo""").WithArguments("string", "bool").WithLocation(11, 18) ); - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular6WithV7SwitchBinder).VerifyDiagnostics( + CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular6WithV7SwitchBinder).VerifyDiagnostics( // (11,18): error CS0029: Cannot implicitly convert type 'string' to 'bool' // case "goo": // wrong type Diagnostic(ErrorCode.ERR_NoImplicitConv, @"""goo""").WithArguments("string", "bool").WithLocation(11, 18) ); - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe).VerifyDiagnostics( + CreateStandardCompilation(source, options: TestOptions.DebugExe).VerifyDiagnostics( // (10,18): error CS0029: Cannot implicitly convert type 'string' to 'bool' // case "goo": // wrong type Diagnostic(ErrorCode.ERR_NoImplicitConv, @"""goo""").WithArguments("string", "bool").WithLocation(11, 18) @@ -815,7 +815,7 @@ public static void Main() } } }"; - CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular6).VerifyDiagnostics( + CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular6).VerifyDiagnostics( // (18,13): error CS8059: Feature 'pattern matching' is not available in C# 6. Please use language version 7.0 or greater. // case Color x when false: Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion6, "case Color x when false:").WithArguments("pattern matching", "7.0").WithLocation(18, 13), @@ -832,7 +832,7 @@ public static void Main() // goto case 3; // warning CS0469: The 'goto case' value is not implicitly convertible to type 'Color' Diagnostic(ErrorCode.ERR_LabelNotFound, "goto case 3;").WithArguments("case 3:").WithLocation(15, 17) ); - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (11,17): warning CS0469: The 'goto case' value is not implicitly convertible to type 'Color' // goto case 1; // warning CS0469: The 'goto case' value is not implicitly convertible to type 'Color' @@ -878,7 +878,7 @@ public static void Main() } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (17,17): warning CS0469: The 'goto case' value is not implicitly convertible to type 'Color' // goto case 1; @@ -925,7 +925,7 @@ public static void M(object o) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var expectedOutput = @"1 @@ -1016,7 +1016,7 @@ public static void M(object o) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var expectedOutput = $@"0.0d ! @@ -1146,7 +1146,7 @@ public static void M(decimal d) } } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (13,13): error CS0152: The switch statement contains multiple cases with the label value '1.01' // case 1.01: // duplicate @@ -1214,7 +1214,7 @@ public static double MakeNaN(int x) return BitConverter.Int64BitsToDouble(BitConverter.DoubleToInt64Bits(double.NaN) ^ x); } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var expectedOutput = @"zero @@ -1271,7 +1271,7 @@ public enum EnumA ValueC } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var expectedOutput = @"0 @@ -1305,7 +1305,7 @@ public static void Main() } } "; - var compilation = CreateCompilationWithMscorlib45(source); + var compilation = CreateStandardCompilation(source); var tree = compilation.SyntaxTrees.Single(); var model = compilation.GetSemanticModel(tree); var sRef = tree.GetCompilationUnitRoot().DescendantNodes().OfType().Where(n => n.ToString() == "s").Single(); @@ -1351,7 +1351,7 @@ public static bool IsB(char value) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var expectedOutput = @"True"; @@ -1381,7 +1381,7 @@ public static bool IsB(char value) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics( // (11,18): error CS8120: The switch case has already been handled by a previous case. // case bool b: ; // error: bool already handled by previous cases. @@ -1430,7 +1430,7 @@ public static void Main(string[] args) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); CompileAndVerify(compilation, expectedOutput: "13"); } @@ -1495,7 +1495,7 @@ static void M(object o) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugDll); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugDll); compilation.VerifyDiagnostics( // (21,18): error CS8058: Feature 'recursive patterns' is experimental and unsupported; use '/features:patterns2' to enable. // case (int, int): @@ -1754,7 +1754,7 @@ public static void Main(string[] args) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); CompileAndVerify(compilation, expectedOutput: "12"); } @@ -1777,7 +1777,7 @@ static void Main(string[] args) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); // The point of this test is that it should not crash. compilation.VerifyDiagnostics( // (8,18): error CS0150: A constant value is expected @@ -1812,7 +1812,7 @@ static void Main(string[] args) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); // The point of this test is that it should not crash. compilation.VerifyDiagnostics( // (7,18): error CS1525: Invalid expression term 'is' @@ -1858,7 +1858,7 @@ bool Local(object o2) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var expectedOutput = @"True @@ -1898,7 +1898,7 @@ static bool BP(bool b, int print) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics(); var expectedOutput = @"2 @@ -1941,7 +1941,7 @@ class Rectangle public Rectangle(int x, int y) { Height = x; Length = y; } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); CompileAndVerify(compilation, expectedOutput: @"other S 1 @@ -1972,7 +1972,7 @@ static void Main() Test(null); } }"; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); CompileAndVerify(compilation, expectedOutput: @"not null @@ -2001,7 +2001,7 @@ static void Main(string[] args) class A{} "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var expectedOutput = "A"; var comp = CompileAndVerify(compilation, expectedOutput: expectedOutput); @@ -2048,7 +2048,7 @@ static void Main(string[] args) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: @"case 1: 1 @@ -2110,7 +2110,7 @@ static System.Collections.Generic.IEnumerable Test() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: @"case 1: 1 @@ -2166,7 +2166,7 @@ static System.Collections.Generic.IEnumerable Test() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: @"case 1: 1 @@ -2224,7 +2224,7 @@ static System.Collections.Generic.IEnumerable Test() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: @"case 1: 1 @@ -2273,7 +2273,7 @@ static bool TakeOutVar(out int x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: @"case: 3 @@ -2336,6 +2336,7 @@ static async Task GetTask(string val) } } "; + // Use a compilation profile that supports Task. var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: @@ -2400,6 +2401,7 @@ static async Task GetTask(string val) } } "; + // Use a compilation profile that supports Task. var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: @@ -2459,6 +2461,7 @@ static async Task Test() } } "; + // Use a compilation profile that supports Task. var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: @@ -2514,6 +2517,7 @@ static async Task GetTask(string val) } } "; + // Use a compilation profile that supports Task. var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: @@ -2550,6 +2554,7 @@ public static async Task SendMessageAsync(object response) } } "; + // Use a compilation profile that supports Task. var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics( // (12,38): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. @@ -2593,7 +2598,7 @@ public static string SendMessage(object input) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: @"T @@ -2635,7 +2640,7 @@ public static System.Collections.Generic.IEnumerable SendMessage(obje } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics(); var comp = CompileAndVerify(compilation, expectedOutput: @"T @@ -2665,7 +2670,7 @@ static void Main() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: s_valueTupleRefs, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, references: s_valueTupleRefs, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics( // (13,18): error CS8120: The switch case has already been handled by a previous case. // case List<(int z, int w)> list2: // subsumed @@ -2699,7 +2704,7 @@ static void Main() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: s_valueTupleRefs, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, references: s_valueTupleRefs, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: @"pass"); @@ -2727,7 +2732,7 @@ static void Main() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: s_valueTupleRefs, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, references: s_valueTupleRefs, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: @"pass"); @@ -2755,7 +2760,7 @@ static void Main() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: s_valueTupleRefs, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, references: s_valueTupleRefs, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: @"1"); @@ -2784,7 +2789,7 @@ static void Main() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: s_valueTupleRefs, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, references: s_valueTupleRefs, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics( // (13,18): error CS8120: The switch case has already been handled by a previous case. // case var x: @@ -2818,7 +2823,7 @@ static void Main() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: s_valueTupleRefs, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, references: s_valueTupleRefs, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics( // (13,18): error CS8120: The switch case has already been handled by a previous case. // case List list2: // subsumed @@ -2852,7 +2857,7 @@ static void Main() } } "; - var compilation = CreateCompilationWithMscorlib45(source, references: s_valueTupleRefs, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, references: s_valueTupleRefs, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics( ); var comp = CompileAndVerify(compilation, expectedOutput: @"pass"); @@ -2883,7 +2888,7 @@ static void Main() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics( // (9,18): error CS8330: It is not legal to use the type 'dynamic' in a pattern. // case dynamic x: // error 1 @@ -2949,7 +2954,7 @@ static void Main() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics( // (11,18): error CS8120: The switch case has already been handled by a previous case. // case var z: // error: subsumed @@ -2996,7 +3001,7 @@ static void Main(string[] args) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.ReleaseExe); + var compilation = CreateStandardCompilation(source, options: TestOptions.ReleaseExe); compilation.VerifyDiagnostics( // (12,13): error CS8120: The switch case has already been handled by a previous case. // case 2: // error: subsumed @@ -3113,6 +3118,7 @@ public static async Task SwitchWithAwaitInPatternFails(Task self, T defaul } } "; + // Use a compilation profile that supports Task. var compilation = CreateCompilationWithMscorlib45( source, options: TestOptions.ReleaseDll.WithOptimizationLevel(OptimizationLevel.Release), references: new[] { SystemCoreRef, CSharpRef }); compilation.VerifyDiagnostics(); diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests.cs index 27ed49370b3ab40e7f5143d4a81822d89262a145..aa5c2dc983ad7a1d50bd4fc26d03baaa75271d82 100644 --- a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetSemanticInfoTests.cs @@ -6715,10 +6715,6 @@ static int Main() "; var semanticInfo = GetSemanticInfoForTest(sourceCode); Assert.Null(semanticInfo.Type); - //Assert.Equal("int[]", semanticInfo.Type.ToString()); - //Assert.Equal("int[]", semanticInfo.ConvertedType.ToString()); - //Assert.Equal(ConversionKind.Identity, semanticInfo.ImplicitConversion.Kind); - //Assert.True(semanticInfo.IsCompileTimeConstant); } [Fact] @@ -8894,23 +8890,6 @@ public static int Main(string[] args) // case /**/()=>3/**/: Diagnostic(ErrorCode.ERR_MissingDeconstruct, "()").WithArguments("string", "0").WithLocation(12, 28) ); - - // Due to language changes to support recursive patterns, the parser will no longer treat this syntax as a lambda. - - //var semanticInfo = GetSemanticInfoForTest(sourceCode); - - //Assert.Null(semanticInfo.Type); - //Assert.Equal("System.String", semanticInfo.ConvertedType.ToTestDisplayString()); - //Assert.Equal(TypeKind.Class, semanticInfo.ConvertedType.TypeKind); - //Assert.Equal(ConversionKind.NoConversion, semanticInfo.ImplicitConversion.Kind); - - //Assert.Equal("lambda expression", semanticInfo.Symbol.ToTestDisplayString()); - //Assert.Equal(SymbolKind.Method, semanticInfo.Symbol.Kind); - //Assert.Equal(0, semanticInfo.CandidateSymbols.Length); - - //Assert.Equal(0, semanticInfo.MethodGroup.Length); - - //Assert.False(semanticInfo.IsCompileTimeConstant); } [Fact] @@ -8952,22 +8931,6 @@ public static int Main(string[] args) // case /**/()=>/**/: Diagnostic(ErrorCode.ERR_MissingDeconstruct, "()").WithArguments("string", "0").WithLocation(13, 28) ); - - // Due to language changes to support recursive patterns, the parser will no longer treat this syntax as a lambda. - //var semanticInfo = GetSemanticInfoForTest(sourceCode); - - //Assert.Null(semanticInfo.Type); - //Assert.Equal("System.String", semanticInfo.ConvertedType.ToTestDisplayString()); - //Assert.Equal(TypeKind.Class, semanticInfo.ConvertedType.TypeKind); - //Assert.Equal(ConversionKind.NoConversion, semanticInfo.ImplicitConversion.Kind); - - //Assert.Equal("lambda expression", semanticInfo.Symbol.ToTestDisplayString()); - //Assert.Equal(SymbolKind.Method, semanticInfo.Symbol.Kind); - //Assert.Equal(0, semanticInfo.CandidateSymbols.Length); - - //Assert.Equal(0, semanticInfo.MethodGroup.Length); - - //Assert.False(semanticInfo.IsCompileTimeConstant); } [Fact] diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs index 2aeb9b5f8368a72494b1facdd8d0daba8e8b2897..d884aa239d05108b8a2db0f304f10ababea9dd48 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/PatternParsingTests.cs @@ -1832,6 +1832,9 @@ public void ParenthesizedExpression_02() public void ParenthesizedExpression_03() { UsingStatement(@"switch (e) { case (x: ((3))): ; }", + // (1,19): error CS8407: A single-element deconstruct pattern requires a type before the open parenthesis. + // switch (e) { case (x: ((3))): ; } + Diagnostic(ErrorCode.ERR_SingleElementPositionalPatternRequiresType, "(x: ((3)))").WithLocation(1, 19), // (1,19): error CS8058: Feature 'recursive patterns' is experimental and unsupported; use '/features:patterns2' to enable. // switch (e) { case (x: ((3))): ; } Diagnostic(ErrorCode.ERR_FeatureIsExperimental, "(x: ((3)))").WithArguments("recursive patterns", "patterns2").WithLocation(1, 19) @@ -1900,15 +1903,18 @@ public void ParenthesizedExpression_03() public void ParenthesizedExpression_04() { UsingStatement(@"switch (e) { case (((x: 3))): ; }", - // (1,19): error CS8407: A single-element deconstruct pattern is ambiguous with a parenthesized pattern; add '{}' after the close paren to disambiguate. + // (1,19): error CS8407: A single-element deconstruct pattern requires a type before the open parenthesis. // switch (e) { case (((x: 3))): ; } - Diagnostic(ErrorCode.ERR_SingleElementPositionalPattern, "(((x: 3)))").WithLocation(1, 19), + Diagnostic(ErrorCode.ERR_SingleElementPositionalPatternRequiresType, "(((x: 3)))").WithLocation(1, 19), // (1,19): error CS8058: Feature 'recursive patterns' is experimental and unsupported; use '/features:patterns2' to enable. // switch (e) { case (((x: 3))): ; } Diagnostic(ErrorCode.ERR_FeatureIsExperimental, "(((x: 3)))").WithArguments("recursive patterns", "patterns2").WithLocation(1, 19), - // (1,20): error CS8407: A single-element deconstruct pattern is ambiguous with a parenthesized pattern; add '{}' after the close paren to disambiguate. + // (1,20): error CS8407: A single-element deconstruct pattern requires a type before the open parenthesis. + // switch (e) { case (((x: 3))): ; } + Diagnostic(ErrorCode.ERR_SingleElementPositionalPatternRequiresType, "((x: 3))").WithLocation(1, 20), + // (1,21): error CS8407: A single-element deconstruct pattern requires a type before the open parenthesis. // switch (e) { case (((x: 3))): ; } - Diagnostic(ErrorCode.ERR_SingleElementPositionalPattern, "((x: 3))").WithLocation(1, 20) + Diagnostic(ErrorCode.ERR_SingleElementPositionalPatternRequiresType, "(x: 3)").WithLocation(1, 21) ); N(SyntaxKind.SwitchStatement); { @@ -2208,6 +2214,9 @@ public void BrokenPattern_08() public void ParenthesizedExpression_05() { UsingStatement(@"switch (e) { case (x: ): ; }", + // (1,19): error CS8407: A single-element deconstruct pattern requires a type before the open parenthesis. + // switch (e) { case (x: ): ; } + Diagnostic(ErrorCode.ERR_SingleElementPositionalPatternRequiresType, "(x: )").WithLocation(1, 19), // (1,19): error CS8058: Feature 'recursive patterns' is experimental and unsupported; use '/features:patterns2' to enable. // switch (e) { case (x: ): ; } Diagnostic(ErrorCode.ERR_FeatureIsExperimental, "(x: )").WithArguments("recursive patterns", "patterns2").WithLocation(1, 19),