diff --git a/meetings/2020/LDM-2020-09-14.md b/meetings/2020/LDM-2020-09-14.md new file mode 100644 index 00000000..bc5173c5 --- /dev/null +++ b/meetings/2020/LDM-2020-09-14.md @@ -0,0 +1,111 @@ +# C# Language Design Meeting for September 14th, 2020 + +## Agenda + +1. [Partial method signature matching](#partial-method-signature-matching) +2. [Null-conditional handling of the nullable suppression operator](#null-conditional-handling-of-the-nullable-suppression-operator) +3. [Annotating IEnumerable.Cast](#annotating-ienumerable.cast) +4. [Nullability warnings in user-written record code](#nullability-warnings-in-user-written-record-code) +5. [Tuple deconstruction mixed assignment and declaration](#tuple-deconstruction-mixed-assignment-and-declaration) + +## Quote of the Day + +- "Now with warning waves it's a foam-covered baseball bat to hit people with" + +## Discussion + +### Partial method signature matching + +https://github.com/dotnet/roslyn/issues/45519 + +There is a question about what amount of signature matching is required for method signatures, both as part of the expanded partial methods in C# 9 +and for the new `nint` feature in C# 9. Currently, our rules around what has to match and what does not are confusing: tuple names must match, +`dynamic`/`object` do not have to match, we warn when there are unsafe nullability conversions, and other differences are allowed (including parameter +names). We could lean on a warning wave here and make our implementation more consistent with the following general rules: + +1. If there are differences in the CLR signature, we error (as we cannot emit code at all!) +2. If there are differences in the syntactic signature, we warn (even for safe nullability changes). + +While we like this proposal in general, we have a couple of concerns around compatibility. Tuple names erroring is existing behavior, and if we loosen +that to a general warning that would need to be gated behind language version, as you could write code with a newer compiler in C# 8 mode that does not +compile with the C# 8 compiler. This complicates implementation, and to make it simple we lean towards just leaving tuple name differences as an error. +We also want to make sure that nullability is able to differ by obliviousness: a common case for generators is that either the original signature or the +implementation will be unaware of nullable, and we don't want to break this scenario such that either both the user and generator must be nullable aware, +or the must both be nullable unaware. + +We also considered an extension to these rules where we make the new rules always apply to the new enhanced partial methods, regardless of warning level. +However, we believe that this would result in a complicated user experience and would make the mental model harder to understand. + +#### Conclusion + +1. We will keep the existing error that tuple names must match. +2. We will keep the existing warnings about unsafe nullability differences. +3. We will add a new warning wave warning for all other syntactic differences between partial method implementations. + a. This includes differences like parameter names and `dynamic`/`object` + b. This includes nullability differences where both contexts are nullable enabled, even if the difference is supposedly "safe" (accepting `null` + where it is not accepted today). + c. If nullability differs by enabled state (one part is enabled, the other part is disabled), this will be allowed without warning. + +### Null-conditional handling of the nullable suppression operator + +https://github.com/dotnet/csharplang/issues/3393 + +This is a spec bug that shipped with C# 8, where the `!` operator does not behave as a user would expect. Members of the LDT believe that this is broken +on the same level as the `for` iterator variable behavior that was changed in C# 5, and we believe that we should take a similar breaking change to fix +the behavior here. We have made a grammatical proposal for adjusting how null-conditional statements are parsed, and there was general agreement that this +proposal is where we want to go. The only comment is that `null_conditional_operations_no_suppression` should be renamed to avoid confusion, as there can +be a null suppression inside the term, just not at the end. A better name would be `null_conditional_operations_no_final_suppression`. + +#### Conclusion + +Accepted, with the above rename. Will get a compiler developer assigned to implement this ASAP. + +### Annotating IEnumerable.Cast + +https://github.com/dotnet/runtime/issues/40518 + +In .NET 5, the `Cast` method was annotated on the return to return `IEnumerable`, which means that regardless of whether the input +enumerable can contain `null` elements, the returned enumerable would be considered to contain `null`s. This resulted in some spurious warnings when +upgrading roslyn to use a newer version of .NET 5. However, the C# in general lacks the ability to properly annotate this method for a combination of +reasons: + +1. There is no way to express that the nullability of one type parameter depends on the nullability of another type parameter. +2. Even if there was a way to express 1, `Cast` is an extension method on `IEnumerable`, not `IEnumerable`, because C# does not have partial type + inference to make writing code in this scenario better. + +Given this, we have a few options: + +1. Leave the method as is, and possibly enhance the compiler/language to know about this particular method. This is analogous to the changes we're + considering with `Where`, but it feels like a bad solution as it's not generalizable. +2. Make the method return `TResult`, unannotated. The issue with this is that it effectively means the method might actually lie: there is no way to + ensure that the method actually returns a non-null result if a non-null `TResult` is provided as a type, given that nullability is erased in the + implementation. We're concerned that this could make the docs appear to lie, which we think would also give a bad experience. +3. Convert `Cast` back to being unannotated. This seems to be compromise that both sides can agree on: analyzers can flag use of the unannotated API + to help users, and spurious warnings get suppressed. It also matches the behavior of `IEnumerator.Current`, and means that the behavior of `foreach` + loops over such a list behave in a consistent manner. + +#### Conclusion + +The BCL will make `Cast` and a few related APIs an oblivious API. + +### Nullability warnings in user-written record code + +The question here is on whether we should warn users when manually-implemented methods and properties for well-known members in a `record` should warn +when nullability is different. For example, if their `Equals(R other)` does not accept `null`. There was no debate on this. + +#### Conclusion + +we'll check user-defined `EqualityContract`, `Equals`, `Deconstruct`, ... methods on records for nullability safety issues in their declaration. For +example, `EqualityContract` should not return Type?. + +### Tuple deconstruction mixed assignment and declaration + +https://github.com/dotnet/csharplang/issues/125 + +We've discussed this feature in the past (https://github.com/dotnet/csharplang/blob/master/meetings/2016/LDM-2016-11-30.md#mixed-deconstruction), and +we liked it then but didn't think it would fit into C# 7. It's been in Any Time since, and now we have a community PR. We have no concerns with +moving forward with the feature. + +#### Conclusion + +Let's try and get this into C# 10. diff --git a/meetings/2020/README.md b/meetings/2020/README.md index 546bf432..85a4df22 100644 --- a/meetings/2020/README.md +++ b/meetings/2020/README.md @@ -30,15 +30,6 @@ - Required properties (Fred) - Triage for C# 10 continued (Mads) -## Sep 14, 2020 - -- C# 9.0: [Interaction between null-conditional operators and the suppression operator](https://github.com/dotnet/csharplang/issues/3393) (Rikki, Julien, Mads) -- C# 9.0: [Require partial method declaration and definition signatures to match](https://github.com/dotnet/roslyn/issues/45519) (Chuck, Rikki, Julien, Mads) -- how to annotate `IEnumerable Cast(this IEnumerable)` and mitigate annoying warnings? ([issue](https://github.com/dotnet/runtime/issues/40518)) (Stephen/Julien) -- nullability expectations for `bool Equals(R? other)` and `Type EqualityContract { get; }` and `R? $()` and `void Deconstruct(out string? NotNullableStringProperty)`. (Julien) -- Allow mixed declaration and assignment in deconstruction (Julien, community [PR](https://github.com/dotnet/roslyn/pull/44476)) -- Triage for C# 10 continued (Mads) - ## Jun 3, 2020 - allow suppression on `return someBoolValue!;` (issue https://github.com/dotnet/roslyn/issues/44080, Julien) @@ -72,6 +63,16 @@ Overview of meetings and agendas for 2020 +## Sep 14, 2020 + +[C# Language Design Notes for September 14th, 2020](https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-14.md) + +- Partial method signature matching +- Null-conditional handling of the nullable suppression operator +- Annotating IEnumerable.Cast +- Nullability warnings in user-written record code +- Tuple deconstruction mixed assignment and declaration + ## Sep 9, 2020 [C# Language Design Notes for September 9th, 2020](https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-09.md) @@ -192,7 +193,7 @@ Record: ## Jun 10, 2020 -[C# Language Design Notes for June 15, 2020](https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-06-15.md) +[C# Language Design Notes for June 10, 2020](https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-06-10.md) - https://github.com/dotnet/csharplang/issues/1711 Roles and extensions