Move tuple literals from "Lexical structure" to "Expressions" (#3205)

This commit is contained in:
Rex Jaeschke 2020-02-18 12:36:40 -05:00 committed by Bill Wagner
parent 4df9865acd
commit 5ade4ff123

View file

@ -2,27 +2,11 @@
This proposal specifies the changes required to the [C# 6.0 (draft) Language specification](../../spec/introduction.md) to support *Tuples* as a new [value type](../../spec/types.md#value-types).
## Changes to [Lexical structure](../../spec/lexical-structure.md)
## Additions to [Expressions](../../spec/expressions.md)
### Literals
> Add the following section after [xxx](xxx):
> The grammar for [Literals](../../spec/lexical-structure.md#literals) is extended to include `tuple_literal`:
```antlr
literal
: boolean_literal
| integer_literal
| real_literal
| character_literal
| string_literal
| null_literal
| tuple_literal // new
;
```
> Add the following section after [The null literal](../../spec/lexical-structure.md#The-null-literal):
#### Tuple literals
## Tuple literal expressions
A tuple literal consists of two or more tuple literal elements, each of which is optionally named.
@ -51,7 +35,7 @@ A tuple literal has a "conversion from expression" to any tuple type of the same
\[Example:
```csharp
(string name, byte age) t = (null, 5); // OK: the expressions null and 5 convert to string and byte, respectively
(string name, byte age) t = (null, 5); // OK: null and 5 convert to string and byte, respectively
```
end example\]
@ -133,7 +117,7 @@ A tuple's type can be declared explicitly. Consider the following declarations:
The type of `pair2` is `(int, string)` with unknown element names. Similarly, the type of `pair3` is `(int, string)` but this time with the element names `code` and `message`, respectively. For `pair4` and `pair5`, one element is named, the other not.
In the case of `pair6`, the second element is declared as being unanmed, and any attempt to provide a name in an initializing context shall be ignored. Likewise for any attempt to change an element's name, as in the case of `pair7`.
In the case of `pair6`, the second element is declared as being unnamed, and any attempt to provide a name in an initializing context shall be ignored. Likewise for any attempt to change an element's name, as in the case of `pair7`.
A tuple's type can be wholely inferred from the context in which it is used. Consider the following declarations:
@ -317,7 +301,7 @@ A tuple literal is implicitly typed when used in a context specifying a tuple ty
\[Example:
```csharp
(string name, byte age) t = (null, 5); // Ok: the expressions null and 5 convert to string and byte
(string name, byte age) t = (null, 5); // OK: the expressions null and 5 convert to string and byte
```
end example\]
@ -391,13 +375,17 @@ Any object may be deconstructed by providing an accessible `Deconstruct` method,
```csharp
class Name
{
public void Deconstruct(out string first, out string last) { first = First; last = Last; }
public void Deconstruct(out string first, out string last) {
first = First; last = Last;
}
...
}
// or
static class Extensions
{
public static void Deconstruct(this Name name, out string first, out string last) { first = name.First; last = name.Last; }
public static void Deconstruct(this Name name, out string first, out string last) {
first = name.First; last = name.Last;
}
}
```
@ -469,7 +457,8 @@ The extension method `M` is a candidate method, even though the tuple `t` has di
```csharp
namespace System
{
public struct ValueTuple<[NullableAttribute(2)] T1, [NullableAttribute(2)] T2> : IStructuralComparable, IStructuralEquatable, IComparable, IComparable<(T1, T2)>, IEquatable<(T1, T2)>, ITuple
public struct ValueTuple<[NullableAttribute(2)] T1, [NullableAttribute(2)] T2> : IStructuralComparable,
IStructuralEquatable, IComparable, IComparable<(T1, T2)>, IEquatable<(T1, T2)>, ITuple
{
[NullableAttribute(1)]
public T1 Item1;
@ -489,7 +478,9 @@ namespace System
namespace System
{
public struct ValueTuple<[NullableAttribute(2)] T1, [NullableAttribute(2)] T2, [NullableAttribute(2)] T3> : IStructuralComparable, IStructuralEquatable, IComparable, IComparable<(T1, T2, T3)>, IEquatable<(T1, T2, T3)>, ITuple
public struct ValueTuple<[NullableAttribute(2)] T1, [NullableAttribute(2)] T2, [NullableAttribute(2)] T3>
: IStructuralComparable, IStructuralEquatable, IComparable, IComparable<(T1, T2, T3)>,
IEquatable<(T1, T2, T3)>, ITuple
{
[NullableAttribute(1)]
public T1 Item1;
@ -513,7 +504,9 @@ namespace System
{
[NullableAttribute(0)]
[NullableContextAttribute(1)]
public struct ValueTuple<[NullableAttribute(2)] T1, [NullableAttribute(2)] T2, [NullableAttribute(2)] T3, [NullableAttribute(2)] T4> : IStructuralComparable, IStructuralEquatable, IComparable, IComparable<(T1, T2, T3, T4)>, IEquatable<(T1, T2, T3, T4)>, ITuple
public struct ValueTuple<[NullableAttribute(2)] T1, [NullableAttribute(2)] T2, [NullableAttribute(2)] T3,
[NullableAttribute(2)] T4> : IStructuralComparable, IStructuralEquatable, IComparable,
IComparable<(T1, T2, T3, T4)>, IEquatable<(T1, T2, T3, T4)>, ITuple
{
public T1 Item1;
public T2 Item2;
@ -533,7 +526,9 @@ namespace System
{
[NullableAttribute(0)]
[NullableContextAttribute(1)]
public struct ValueTuple<[NullableAttribute(2)] T1, [NullableAttribute(2)] T2, [NullableAttribute(2)] T3, [NullableAttribute(2)] T4, [NullableAttribute(2)] T5> : IStructuralComparable, IStructuralEquatable, IComparable, IComparable<(T1, T2, T3, T4, T5)>, IEquatable<(T1, T2, T3, T4, T5)>, ITuple
public struct ValueTuple<[NullableAttribute(2)] T1, [NullableAttribute(2)] T2, [NullableAttribute(2)] T3,
[NullableAttribute(2)] T4, [NullableAttribute(2)] T5> : IStructuralComparable, IStructuralEquatable,
IComparable, IComparable<(T1, T2, T3, T4, T5)>, IEquatable<(T1, T2, T3, T4, T5)>, ITuple
{
public T1 Item1;
public T2 Item2;
@ -554,7 +549,10 @@ namespace System
{
[NullableAttribute(0)]
[NullableContextAttribute(1)]
public struct ValueTuple<[NullableAttribute(2)] T1, [NullableAttribute(2)] T2, [NullableAttribute(2)] T3, [NullableAttribute(2)] T4, [NullableAttribute(2)] T5, [NullableAttribute(2)] T6> : IStructuralComparable, IStructuralEquatable, IComparable, IComparable<(T1, T2, T3, T4, T5, T6)>, IEquatable<(T1, T2, T3, T4, T5, T6)>, ITuple
public struct ValueTuple<[NullableAttribute(2)] T1, [NullableAttribute(2)] T2, [NullableAttribute(2)] T3,
[NullableAttribute(2)] T4, [NullableAttribute(2)] T5, [NullableAttribute(2)] T6> : IStructuralComparable,
IStructuralEquatable, IComparable, IComparable<(T1, T2, T3, T4, T5, T6)>,
IEquatable<(T1, T2, T3, T4, T5, T6)>, ITuple
{
public T1 Item1;
public T2 Item2;
@ -576,7 +574,10 @@ namespace System
{
[NullableAttribute(0)]
[NullableContextAttribute(1)]
public struct ValueTuple<[NullableAttribute(2)] T1, [NullableAttribute(2)] T2, [NullableAttribute(2)] T3, [NullableAttribute(2)] T4, [NullableAttribute(2)] T5, [NullableAttribute(2)] T6, [NullableAttribute(2)] T7> : IStructuralComparable, IStructuralEquatable, IComparable, IComparable<(T1, T2, T3, T4, T5, T6, T7)>, IEquatable<(T1, T2, T3, T4, T5, T6, T7)>, ITuple
public struct ValueTuple<[NullableAttribute(2)] T1, [NullableAttribute(2)] T2, [NullableAttribute(2)] T3,
[NullableAttribute(2)] T4, [NullableAttribute(2)] T5, [NullableAttribute(2)] T6, [NullableAttribute(2)] T7>
: IStructuralComparable, IStructuralEquatable, IComparable, IComparable<(T1, T2, T3, T4, T5, T6, T7)>,
IEquatable<(T1, T2, T3, T4, T5, T6, T7)>, ITuple
{
public T1 Item1;
public T2 Item2;
@ -586,10 +587,12 @@ namespace System
public T6 Item6;
public T7 Item7;
public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7);
public int CompareTo([NullableAttribute(new[] { 0, 1, 1, 1, 1, 1, 1, 1 })] (T1, T2, T3, T4, T5, T6, T7) other);
public int CompareTo([NullableAttribute(new[] { 0, 1, 1, 1, 1, 1, 1, 1 })]
(T1, T2, T3, T4, T5, T6, T7) other);
[NullableContextAttribute(2)]
public override bool Equals(object? obj);
public bool Equals([NullableAttribute(new[] { 0, 1, 1, 1, 1, 1, 1, 1 })] (T1, T2, T3, T4, T5, T6, T7) other);
public bool Equals([NullableAttribute(new[] { 0, 1, 1, 1, 1, 1, 1, 1 })]
(T1, T2, T3, T4, T5, T6, T7) other);
public override int GetHashCode();
public override string ToString();
}
@ -599,7 +602,11 @@ namespace System
{
[NullableAttribute(0)]
[NullableContextAttribute(1)]
public struct ValueTuple<[NullableAttribute(2)] T1, [NullableAttribute(2)] T2, [NullableAttribute(2)] T3, [NullableAttribute(2)] T4, [NullableAttribute(2)] T5, [NullableAttribute(2)] T6, [NullableAttribute(2)] T7, [NullableAttribute(0)] TRest> : IStructuralComparable, IStructuralEquatable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>>, IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>>, ITuple where TRest : struct
public struct ValueTuple<[NullableAttribute(2)] T1, [NullableAttribute(2)] T2, [NullableAttribute(2)] T3,
[NullableAttribute(2)] T4, [NullableAttribute(2)] T5, [NullableAttribute(2)] T6, [NullableAttribute(2)] T7,
[NullableAttribute(0)] TRest> : IStructuralComparable, IStructuralEquatable, IComparable,
IComparable<ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>>,
IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>>, ITuple where TRest : struct
{
public T1 Item1;
public T2 Item2;
@ -610,11 +617,14 @@ namespace System
public T7 Item7;
[NullableAttribute(0)]
public TRest Rest;
public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, [NullableAttribute(0)] TRest rest);
public int CompareTo([NullableAttribute(new[] { 0, 1, 1, 1, 1, 1, 1, 1, 0 })] ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest> other);
public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7,
[NullableAttribute(0)] TRest rest);
public int CompareTo([NullableAttribute(new[] { 0, 1, 1, 1, 1, 1, 1, 1, 0 })]
ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest> other);
[NullableContextAttribute(2)]
public override bool Equals(object? obj);
public bool Equals([NullableAttribute(new[] { 0, 1, 1, 1, 1, 1, 1, 1, 0 })] ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest> other);
public bool Equals([NullableAttribute(new[] { 0, 1, 1, 1, 1, 1, 1, 1, 0 })]
ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest> other);
public override int GetHashCode();
public override string ToString();
}