# C# Language Design Meeting for March 15th, 2021

## Agenda

1. [Interpolated string improvements](#interpolated-string-improvements)
2. [Global usings](#global-usings)

## Quote of the Day

- "Need is a strong word... I'm just teasing, I'm just lobbing in a joke"

## Discussion

### Interpolated string improvements

https://github.com/dotnet/csharplang/issues/4487

We looked at the open question around argument passing today. In the current form, the proposal treats the receiver specially, even
for reduced extension methods where the receiver is just sugar for the first argument. This special treatment of the receiver is
very limiting, as many API patterns exist today where destinations are conveyed as arguments to a method, not as the receiver of the
method, and we would like APIs to be able to continue having their same shapes. It's also inconsistent with how we treat extension
methods in the rest of the language: they're a sugar, and there is no semantic difference between calling them in reduced form or not.

To address this, we looked at a couple of possible solutions:

1. Don't pass anything. No receiver, no arguments. This is clean, but is not really an improvement on how it works today. It means that
the builder type would need to support storage of an arbitrary number of arguments of arbitrary types, and would preclude working with
ref structs and other types that can't be in generics today.
2. Require methods to have a `PrepFormat` or similar signature that is isomorphic to the original signature, with the builder parameters
as `out` variables instead. This would allow us to simply call that signature, and there would be no fancy mapping to consider. However,
this is pretty messy from a public API standpoint. We can apply `EditorDisplay` to such methods, but they'll still exist, need to be
documented, and generally get in the way. It also means that every method will need to have a second method, which possibly limits code
sharing abilities.
3. Put an attribute on either individual parameters or on the builder type, specifying that these parameters should be passed to the
builder creation method. The former version was proposed in the open questions section, but the latter came up in discussion and seems
like a better approach. It gives a central location, handles multiple potential builders in a method signature, and allows including the
receiver type as either a magic name like `this` or as a boolean flag.

#### Conclusion

We'll look at the attribute on the builder type solution. The next question we need to answer is around out-of-order execution for
arguments passed to builders.

### Global usings

https://github.com/dotnet/csharplang/issues/3428

Next, we looked at 2 open issues in global usings: the scope of the global using statements, and how name lookup treats these usings
with respect to regular using directives. Both of these questions really hinge on the overall view we want to take on how global usings
are represented. There are 2 views here:

1. Global usings are effectively copy/pasted into the top of every file. They're just like regular `using` directives, and all the same
rules that apply to regular `using` directives at the top level apply to global usings as well.
    * This has the advantage that, at the top level, a regular `using` directive will _never_ be changed by a global using directive.
    Users can't introduce namespace ambiguities at the top level by introducing a global using directive that has a nested namespace with
    the same name as a top-level namespace.
    * It aligns with our prior art: both CSX and VB.NET work this way.
    * This version has the disadvantage that, at the top level, global aliases could not be reused in a file-scoped using alias. They could
    be used in an alias nested inside a namespace declaration, but not at the top level. While this is a niche scenario, it is likely that
    someone will hit it at some point.
    * If a name is imported in both a global `using` directive and a file-scoped `using` directive, that name is ambiguous.
2. Global usings are a new scope, that exists _above_ regular `using` directives at the top of a file. They are to file-scoped `using`
directives what file-scoped `using` directives are to `using` directives nested in a namespace.
    * This would allow globally-defined aliases to be used in file-scoped directives.
    * We would need to rationalize how these rules work for CSX. Do global using directives imported from a `#load` directive change the
    meaning of `using` directives in the current file, or files that are subsequently `#load`ed?
    * Name lookup would prefer the file-scoped `using` directives, only going to global directives if a name wasn't found.
    * Has a bigger implementation cost: some PDB changes might be required in order to ensure that names mean the correct things and diverges
    heavily from existing implementations.

We think both worldviews here are consistent and reasonable, and would be fine with either mental model as an explanation to consumers of how
the feature works. However, worldview 1 is more consistent with past decisions and has less implementation concerns.

#### Conclusion

We'll go with worldview 1. The decisions for scoping and name lookup fall out from this.
