
# C# Language Design Meeting for September 18th, 2019

## Agenda

Triage:

1. Proposals with complete designs:

    - https://github.com/dotnet/csharplang/issues/1888 Champion "Permit attributes on local functions"
    - https://github.com/dotnet/csharplang/issues/100 Champion "Target-typed new expression"

2. Target typing and best-common-type features: 

    - https://github.com/dotnet/csharplang/issues/2473 Proposal: Target typed null coalescing (??) expression
    - https://github.com/dotnet/csharplang/issues/2460 Champion: target-typed conditional expression
    - https://github.com/dotnet/csharplang/issues/881 Permit ternary operation with int? and double operands
    - https://github.com/dotnet/csharplang/issues/33 Champion "Nullable-enhanced common type"

## Discussion

### Attributes on local functions

Issue #1888

The only major concern about the feature is whether or not the attributes are guaranteed to be emitted to
the lowered method, assuming there is a lowered method. For all current lowering strategies, there is a
specific place to put the attributes. The proposal is that we always emit attributes for our current
scenarios, but don't guarantee in the language that all attributes will survive rewriting.

There is one exception to the above, which is static local functions. Static local functions are specified
to always emit a static method with the same signature as the local function (although there are bugs about
this today). Attributes on static local function would have a similar guarantee, meaning that they are always
emitted to the lowered methods, on the exact same parameters they were applied to.

**Conclusion**

Proposal accepted, attributes will be allowed on local functions. `extern` will also be allowed on
static local functions, and will be a valid P/Invoke target.

### Target-typed new

Issue #100

We like the feature and already have a design. However, we want to do a quick review that we still like the
design, taking into account all the changes we've made to the language since it was proposed.

**Conclusion**

Accepted, pending review.

### Target-typed conditional expression and nullable-enhanced common type

Issue #2460 and issue #33

The main problem is that providing a target-typing for the switch expression
may have made issue #33 a breaking change. In general, additional target-typing
(on top of a natural type) works by calculating the target type if there is no
viable natural type. By allowing more natural types, it reduces the ability to
use target-typing, which may allow more resulting types than the natural type
inference.

Overload resolution is a good example. If you have two methods

```C#
void M(int? x) { ... }
void M(short? y) { ... }
```

and a call `M(e switch { ... => 1, ... => null })`, when we do overload resolution
we consider the target type for the `switch`, which consists of the target type
for each of the candidates. For target type, `short` is a better target for `int`.
If we improved the natural type, then the natural type of `1` would be `int`. Then,
if we improve the natural type of `e switch { ... => 1, ... => null}` to be `int?`,
then a different overload (`M(int? x)`) will be chosen.

There's also a pretty clear trade-off here. Target-typing may allow more viable
types, but it falls over in the presence of type inference or if the target is
so broad as to be useless (like if the target-type is `object`).

Additionally, the proposal for target-typing the conditional expression (`?:`) will have
different semantics from the target-typing for the switch expression, to avoid a breaking change.
It may be desirable to unify the behavior of things like `?:` and switch expression, even if that
means that the switch expression would be more limited, due to the backwards compatibility
constraints of `?:`.

**Conclusion**

Let's do some work to see if we can alter the interaction of target-typing and common type
inference to add the proposed new common types without introducing breaking changes with
target-typing. The hope is that such a rule could be general enough to apply to other potential
breaks in the future (in case we find more potential improvements to common type).

In addition, we would like to know the effect of changing switch expressions to prefer the common
type, if one exists. We hope that any difference would be uncommon in practice, but it would be
useful to know if there are common instances where this would break. This would be used to decide
if we would adjust the behavior of the switch expression to match the proposed behavior for the
conditional expression.
