# C# Language Design Meeting for Feb 22nd, 2021

## Agenda

1. [Global `using`s](#global-usings)
2. [`using` alias improvements](#using-alias-improvements)

## Quote of the Day

* "You're muted" "I wanted to be muted"

## Discussion 

### Global `using`s

https://github.com/dotnet/csharplang/blob/master/proposals/GlobalUsingDirective.md

Today we discussed the proposed syntax and restrictions on the current feature specification. As checked in today, the proposal
puts `global` after the `using` directive, which could be potentially ambiguous and require complicated parsing logic, as `global`
is a valid namespace identifier today. For example, this is valid code:

```cs
// Is this a global using alias, or a top-level using variable declaration?
using global myVar = Test.AGlobal;

class Test
{
    public static global AGlobal = new global();
}

class global : IDisposable { public void Dispose() {} }
```

We could potentially resolve this in the same way we did for the `record` keyword, which is to forbid types be named `global` in
C# 10. We haven't gotten pushback on this approach for `record` as a type name so far, which is positive. However, aside from the
ambiguity, there are other reasons to view `global`-first as a good thing. `global` here is a modifier on the `using`, which C#
generally puts before the declaration, not after. We also considered 2 separate but related questions:

1. Is `static` a similar modifier? Should it be allowed to come before the `using` as well?
    * After discussion, we don't believe so. `static` isn't a modifier on the `using`, it fundamentally changes what the meaning
    of the using is about.
2. We already have existing modifiers for C# scopes: should we use `internal` as the keyword here?
    * Using `internal` begs the followup question: what does `public` on one of these `using`s mean? What about `private`? We're
    uncomfortable with the idea of treating these more like types than like macros. This starts to get into a very slippery slope
    of how we export aliases publicly, can additional constraints be added to aliases, and how does that interact with roles?

Finally, we discussed the proposed restrictions on the feature. We like them overall: if `global` and non-`global` `using`s can
be interspersed, it could lead to user confusion as to whether regular `using` directives can affect `global` ones. It also helps
set up a clearly-defined set of scopes. We add a new `global` scope that comes before all top-level `using` statements today, and
their interactions mirror the interactions of regular `using`s statements with those nested in a namespace.

#### Conclusion

We put `global` before `using`, but the proposal is otherwise accepted as is.

### `using` alias improvements

https://github.com/dotnet/csharplang/pull/4452

Continuing with the theme of `using` improvements, we also discussed generalized improvements to `using` aliases to address a
number of reoccuring complaints over the years with limitations in today's approach. Specifically, `using` directives today
cannot reference predefined names like `string`, they can't have generic type arguments, they can't use tuple syntax, or use
pointer types (including the C# 9 function pointer syntax). The current proposal allows all of these things, including aliases
for partially-bound type parameters such as `using MyDictionary<T> = System.Collections.Generic.Dictionary<int, T>;`. When
combined with the previous `global using` feature, enabling this would allow compilation-unit type aliases. Our remaining open
questions here focus again on how we want to push `using`s forward in the future:

1. If we want to push `using` aliases as real types, then they need to have the ability to expression the same things all other
types can, including constraints and variance. If we go this route, we could potentially have a future where you can introduce
an alias that adds a _new_ constraint onto an existing type, such as an invariant `IEnumerable<T>` alias, or a dictionary that
is constrained to only `struct`-type values.
2. If we want to push `using` aliases as more macro-expansion, then the ability to expression constraints and variance is a
confusing detriment. The type parameter will be substituted at expansion site and we'll error at that point if an illegal
substitution is made.

Approach 1 has many followup questions that quickly start to slide into roles territory. Aliases can be used in public API, for
example, so how would we advertise them publicly if the alias has added new constraints? Is it possible for users to introduce
an opaque alias, such as aliasing `int` to `CustomerId` in such a way as there's no implicit conversion between them? Ultimately,
we think that these problems are better solved by a discrete language feature such as roles, rather than as an expansion on
`using` aliases.

#### Conclusion

`using` aliases will be treated more as macro expansions than as real types. We'll check substitutions for concrete types where
we can (such as erroring in the alias itself for `using MyList = System.Collections.Generic.List<int*>;`), but for things we
cannot check at the declaration site, we will error at the use site. There is no way to add constraints to a `using` alias.
