
# C# Language Design Notes for Oct 24, 2018

## Agenda

1. [Adding Nullable Reference Type features to Nullable Value Types](https://github.com/dotnet/csharplang/issues/1865)
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.