Skip to content

Commit

Permalink
fix build warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
BillWagner committed Apr 2, 2022
1 parent 1fe2155 commit 6b13b68
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 32 deletions.
2 changes: 2 additions & 0 deletions standard/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2936,11 +2936,13 @@ An extension method is a regular static method. In addition, where its enclosing
<!-- markdownlint-enable MD028 -->
> *Note*: Extension methods on a tuple type apply to tuples with different element names:
>
> ```csharp
> static void M(this (int x, int y) t) { ... }
> int a, int b) t = ...;
> t.M(); // OK
> ```
>
> The extension method `M` is a candidate method, even though the tuple `t` has different element names (`a` and `b`) than the formal parameter of `M` (`x` and `y`). *end note*.
### 14.6.11 Method body
Expand Down
14 changes: 12 additions & 2 deletions standard/conversions.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ In most cases, an identity conversion has no effect at runtime. However, since f
In tuple conversions, element names are immaterial. Tuples with the same arity are identity-convertible to each other or to and from corresponding underlying `ValueTuple` types, regardless of their element names.

> *Example*:
>
> ```csharp
> var t = (sum: 0, count: 1);
>
Expand All @@ -81,15 +82,18 @@ In tuple conversions, element names are immaterial. Tuples with the same arity a
>
> t2.moo = 1;
> ```
>
> *end example*
In the case in which an element name at one position on one side of a conversion, and the same name at a different position on the other side, the compiler shall issue a warning.

> *Example*:
>
> ```csharp
> (string first, string last) GetNames() { ... }
> (string last, string first) names = GetNames(); // Oops!
> ```
>
> *end example*
### 10.2.3 Implicit numeric conversions
Expand Down Expand Up @@ -129,7 +133,7 @@ A tuple conversion can be classified as a valid instance conversion or an extens

On top of the member-wise conversions implied by implicit typing, implicit conversions between tuple types themselves are allowed.

### 10.2.5 Implicit nullable conversions
### 10.2.5 Implicit interpolated string conversions

An implicit interpolated string conversion permits an *interpolated_string_expression* ([§11.7.3](expressions.md#1173-interpolated-string-expressions)) to be converted to `System.IFormattable` or `System.FormattableString` (which implements `System.IFormattable`).
When this conversion is applied, a string value is not composed from the interpolated string. Instead an instance of `System.FormattableString` is created, as further described in [§11.7.3](expressions.md#1173-interpolated-string-expressions).
Expand Down Expand Up @@ -336,32 +340,38 @@ Anonymous functions and method groups do not have types in and of themselves, bu
A tuple literal is implicitly typed when used in a context specifying a tuple type. The tuple literal has a "conversion from expression" to any tuple type of the same arity, as long as the element expressions of the tuple literal have an implicit conversion to the corresponding element types of the tuple type.

> *Example*:
>
> ```csharp
> (string name, byte age) t = (null, 5); // OK: the expressions null and 5 convert to string and byte
> ```
>
> *end example*
A successful conversion from tuple expression to tuple type is classified as an *ImplicitTuple* conversion, unless the tuple's natural type (§tuple-types-general-new-clause) matches the target type exactly, in such case it is an *Identity* conversion.

*Example*:
> *Example*:
>
> ```csharp
> void M1((int x, int y) arg){...};
> void M1((object x, object y) arg){...};
>
> M1((1, 2)); // first overload is used. Identity conversion is better than implicit conversion.
> M1(("hi", "hello")); // second overload is used. Implicit tuple conversion is better than no conversion.
> ```
>
> *end example*
A successful conversion from tuple expression to a nullable tuple type is classified as *ImplicitNullable* conversion.

> *Example*:
>
> ```csharp
> ((int x, int y, int z)?, int t)? SpaceTime()
> {
> return ((1,2,3), 7); // valid, implicit nullable conversion
> }
> ```
>
> *end example*
## 10.3 Explicit conversions
Expand Down
63 changes: 35 additions & 28 deletions standard/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -1060,7 +1060,7 @@ Given an expression `E` and two types `T₁` and `T₂`, `T₁` is a ***better c
> ```
>
> *end example*
#### §overload-resolution-and-tuples-new-clause Overload resolution and tuples with no natural types
The exact-match rule for tuple expressions is based on the natural types (§(§tuple-types-general-new-clause) of the constituent tuple elements. The rule is mutually recursive with respect to other containing or contained expressions not in a possession of a natural type.
Expand Down Expand Up @@ -1406,7 +1406,7 @@ Then:

A tuple literal consists of two or more tuple literal elements, each of which is optionally named.

```antlr
```ANTLR
tuple_literal
: '(' ( tuple_literal_element ',' )+ tuple_literal_element ')'
;
Expand All @@ -1417,34 +1417,40 @@ tuple_literal_element

A tuple literal is implicitly typed; that is, its type is determined by the context in which it is used, referred to as the ***target***. Each element *expression* in a tuple literal shall have a value that can be converted implicitly to its corresponding target element type.

*Example*:
```csharp
var t1 = (0, 2); // infer tuple type (int, int) from values
var t2 = (sum: 0, count: 1); // infer tuple type (int sum, int count) from names and values
(int, double) t3 = (0, 2); // infer tuple type (int, double) from values; can implicitly convert int to double
(int, double) t4 = (0.0, 2); // Error: can't implicitly convert double to int
```
*end example*
> *Example*:
>
> ```csharp
> var t1 = (0, 2); // infer tuple type (int, int) from values
> var t2 = (sum: 0, count: 1); // infer tuple type (int sum, int count) from names and values
> (int, double) t3 = (0, 2); // infer tuple type (int, double) from values; can implicitly convert int to double
> (int, double) t4 = (0.0, 2); // Error: can't implicitly convert double to int
> ```
>
> *end example*
A tuple literal has a "conversion from expression" to any tuple type of the same arity, as long as each of the element expressions of the tuple literal has an implicit conversion to the type of the corresponding element of the tuple type.

*Example*:
```csharp
(string name, byte age) t = (null, 5); // OK: null and 5 convert to string and byte, respectively
```
*end example*
> *Example*:
>
> ```csharp
> (string name, byte age) t = (null, 5); // OK: null and 5 convert to string and byte, respectively
> ```
>
> *end example*
In cases where a tuple literal is not part of a conversion, the literal's type is its natural type (§tuple-types-general-new-clause), if one exists.

*Example*:
```csharp
var t = ("John", 5); // OK: the natural type is (string, int)
var t = (null, 5); // Error: null doesn't have a type
var t = (name: "John", age: 5); // OK: The natural type is (string name, int age)
```
*end example*
> *Example*:
>
> ```csharp
> var t = ("John", 5); // OK: the natural type is (string, int)
> var t = (null, 5); // Error: null doesn't have a type
> var t = (name: "John", age: 5); // OK: The natural type is (string name, int age)
> ```
>
> *end example*
A tuple literal is *not* a [constant expression](expressions.md#1220-constant-expressions).
A tuple literal is *not* a [constant expression](expressions.md#1120-constant-expressions).

For a discussion of tuple literals as tuple initializers, see §tuple-types-new-clause.

Expand Down Expand Up @@ -4245,19 +4251,20 @@ When a tuple literal ((§tuple-literal-expressions-new-clause) is used as an ope

In the nullable tuple case, additional checks for `t1.HasValue` and/or `t2.HasValue` shall be performed.

When an element-wise comparison returns a non-`bool` result, if that comparison is dynamic in a tuple equality, a dynamic invocation of the operator `false` shall be used with the result being negated to get a `bool`.
When an element-wise comparison returns a non-`bool` result, if that comparison is dynamic in a tuple equality, a dynamic invocation of the operator `false` shall be used with the result being negated to get a `bool`.

If an element-wise comparison returns some other non-`bool` type in a tuple equality, there are two cases:

- if the non-bool type converts to `bool`, that conversion is applied,
- if there is no such conversion, but the type has an operator `false`, that is used the result is negated.

In a tuple inequality, the same rules apply except that the operator `true` is used without negation.

When binding the `==` (or `!=`) operator, the usual rules are: (1) dynamic case, (2) overload resolution, and (3) fail. However, in the case of tuple comparison, a new rule is inserted between (1) and (2): if both operands of a comparison operator are tuples, the comparison is performed elementwise. This tuple equality is also lifted onto nullable tuples.
When binding the `==` (or `!=`) operator, the usual rules are: (1) dynamic case, (2) overload resolution, and (3) fail. However, in the case of tuple comparison, a new rule is inserted between (1) and (2): if both operands of a comparison operator are tuples, the comparison is performed elementwise. This tuple equality is also lifted onto nullable tuples.

> *Note*: If prior to the addition of tuple comparison to C#, a program defined `ValueTuple` types with `==` or `!=` operators, those operators would have been chosen by overload resolution. However, with the addition of comparison support and the new rule above, the comparison is handled by tuple comparison instead of the user-defined comparison. *end note*
Regarding the order of evaluation of `t1` and `t2`, `t1` is evaluated first followed by `t2`, then the element-wise comparisons going from left-to-right. Consider the following: if there is a conversion from type `A` to type `B` and a method `(A, A) GetTuple()`, the comparison
Regarding the order of evaluation of `t1` and `t2`, `t1` is evaluated first followed by `t2`, then the element-wise comparisons going from left-to-right. Consider the following: if there is a conversion from type `A` to type `B` and a method `(A, A) GetTuple()`, the comparison

```csharp
(new A(1), (new B(2), new B(3))) == (new B(4), GetTuple())
Expand Down Expand Up @@ -6351,7 +6358,7 @@ An event assignment expression does not yield a value. Thus, an event assignment

A tuple-deconstruction expression copies from a source tuple zero or more of its element values to corresponding destinations.

```antlr
```ANTLR
tuple_deconstruction_expression
: '(' destination_list ')'
;
Expand Down Expand Up @@ -6423,7 +6430,7 @@ p.Deconstruct(out byte __x, out byte __y);
(int x, int y) = (__x, __y);
```

The evaluation order of deconstruction assignment expressions is "breadth first;" that is, left-to-right. Each element is then copied as defined by [§12.18.2](expressions.md#12182-simple-assignment).
The evaluation order of deconstruction assignment expressions is "breadth first;" that is, left-to-right. Each element is then copied as defined by [§11.18.2](expressions.md#11182-simple-assignment).

> *Example*:
>
Expand Down
6 changes: 4 additions & 2 deletions standard/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ The nullable type `T?` implements no interfaces ([§17](interfaces.md#17-interfa

A tuple is declared using the following syntax:

```antlr
```ANTLR
tuple_type
: '(' tuple_type_element_list ')'
;
Expand All @@ -432,7 +432,7 @@ A tuple's ***arity*** is the combination of its element types, in lexical order;

Two tuple values are equal if they have the same arity, and the values of the elements in each corresponding element pair are equal.

An element in a tuple is accessed using the [member-access operator `.`](expressions.md#12751-general).
An element in a tuple is accessed using the member-access operator `.` ([§11.7.6](expressions.md#1176-member-access).

Given the following,

Expand Down Expand Up @@ -576,10 +576,12 @@ A tuple element name is not part of the runtime representation of a tuple of tha
In alignment with the identity conversions, a boxed tuple shall not retain the names of the elements, and shall unbox to any tuple type that has the same element types in the same order.

> *Example*:
>
> ```csharp
> object o = (a: 1, b: 2); // boxing conversion
> var t = ((int moo, int boo))o; // unboxing conversion
> ```
>
> *end example*
### 8.3.12 Boxing and unboxing
Expand Down

0 comments on commit 6b13b68

Please sign in to comment.