csharplang/meetings/2018/LDM-2018-10-24.md
2018-11-02 15:16:33 -07:00

3.5 KiB

C# Language Design Notes for Oct 24, 2018

Agenda

  1. Adding Nullable Reference Type features to Nullable Value Types
  2. Open issues with pattern matching

Discussion

Tracking null state for Nullable<T>

Note that the proposed null tracking would not warn on GetValueOrDefault, which is legal on null values.

Q: Do we want to prohibit ! on assigning to a Nullable<T>?

Nullable<T> is fully type-safe and the analysis is precise. The only cases we can't prove are complicated uses/checks that the compiler can't prove. If we force the user to rewrite their code such that the compiler can prove safety, we may not need !.

Conclusion

Let's extend the tracking for nullable reference types to Nullable<T>.

For banning, !, we're worried this is too restrictive and there still may be places where you want the "easy out" of !.

Note: For the flow analysis, we will consider a value type that is accessed as though it were non-null to be non-null thereafter. There is no situation for the reverse for value types. We will never treat a non-Nullable value type as a Nullable value type, regardless of how you treat it.

Using nullable values as non-nullable values

Q: Would we regard the new uses of the underlying members as implicitly turning on nullable warnings?

A: Yes, probably.

Pros:

  • It's more convenient
  • It's safe because you'll get a warning

Cons:

  • The checking is not precise, because we allow !
  • Type analysis is less precise, but easier to understand. We adopted the flow analysis mainly because we had back compat concerns with existing null checking code for reference types. Here we don't have to deal with backwards compatibility.
  • This would also contravene the information provide the declaration site. This figures into seeing the annotation at the declaration vs the use site

Conclusion:

We're not going to do this.

Pattern matching open issues

Is a pattern permitted to match a pointer type?

You can't explicitly match a pointer because you can't write a pointer type as a pattern (* is used for multiplication in this context).

However, it would be weird to make an exception for discard and var, so it will be allowed for those use cases.

Q: What about ptr is null? Or ptr is {}?

Allow ptr is null. No ptr is {} or anything else.

ITuple vs unconstrained type parameter

Let's keep it an error for now. We may relax the restriction later.

Matching ITuple in the presence of extension Deconstruct

This has some similarities in dynamic/static lookup conflicts in GetEnumerator/IEnumerable. Currently, if we see a struct GetEnumerator that doesn't match the pattern we provide an error, even if there is a valid IEnumerable interface underneath. Here the Deconstruct is an extension method, so the analogy is not perfect.

Using the Deconstruct method seems more consistent with what we do for instance methods, although this would be different based on whether or not the extension method is in scope.

However, it seems difficult to actually implement the check for extension Deconstruct, because it's not clear whether none of the extension Deconstruct methods match because they are not meant for the given receiver, or if they were simply incorrectly written.

If we disregard Deconstruct, this would create a difference between the behavior for instance Deconstruct methods and extension Deconstruct methods.

Conclusion

None. Let's look at the implementation in more detail and come back with a proposal.