csharplang/meetings/2019/LDM-2019-10-30.md
2019-11-11 15:55:56 -08:00

3.8 KiB

C# Language Design Meeting Notes for Oct. 30, 2019

Agenda

  1. Function pointer syntax
  2. Enhancing Common Type Algorithm (again)

Discussion

Function pointer syntax

Proposal: https://github.com/dotnet/csharplang/issues/2917

While exploring syntax for function pointers, it turns out that parsing the previously proposed syntax, namely

func*(int, int)

can feature exponential parsing behavior in the case of nested function pointers.

An alternative is proposed using a generic-style syntax. E.g.,

func*<void>
cdecl*<int, void>

The proposed changes employ *< as being unambiguous in the language today. One suggestion is to use the same trick, but with a minor modification: func would always be the first token, and the calling convention would be the second token e.g.,

func cdecl*<int, void>

and the set of calling conventions would evolve as the set of CLR-supported calling conventions evolve.

There are a couple features which aren't mentioned, and we're not sure if we need to support them, and how we would do so.

Mainly, we don't know whether certain features, like attributes, require definitions of named function pointers, instead of anonymous function pointer types. The runtime has proposed using attributes to express configuration, like suppressing native/managed transition.

The current syntax doesn't have a place to put attributes, so if we wanted to support that design, we would have to have some definition to place attributes. This would be similar to delegate definitions, where you can define a delegate with a name and attributes, and then refer to the delegate type by name.

However, the current runtime implementation doesn't support declaring tokens for the function pointer, so there's no official mechanism to attach attributes to a function pointer. A follow-up question is to ensure that the spec allows us to put the calling convention in the signature during emit as part of the function pointer type.

We brainstormed a bunch of possible syntaxes (some more serious than others):

delegate managed *int(int, long)

delegate managed *List<T>(int, long)

delegate * List<T> managed(int, long)

delegate<managed> * List<T>(int, long)

delegate * managed List<T>(int, long)

delegate managed int *(int, long)

delegate managed*<int, long, void>

delegate *<int, long, void>

delegate* managed<int, long, void>
delegate*<int, long, void>

Conclusion

The new syntax is agreed to be unambiguous, as far as we can see. We agree on three modifications:

1. The optional calling convention should always have a prefix.
2. Putting the `*` near the prefix is better, as it makes the function pointer
   more recognizable.
3. `delegate` is a better prefix, as it is already a keyword.

Our final decision is

'delegate*' optional_calling_convention '<' type < type , ... > , return_type '>'

Enhancing Common Type Specification follow-up

Proposal: https://github.com/dotnet/csharplang/issues/2823

The previous proposal was to add target-typing as a fallback to existing features, like the conditional expression, and do no more work on enhancing the common type algorithm.

This would solve certain problems and not others. In the case where the conditional expression has a common type, but that type is not the one you want (e.g., b ? 1 : 2, but you wanted the result to be a byte), target typing would not solve this.

At the same time, not having all possible improvements doesn't seem to impact the decision for nullable, specifically. We already have special language knowledge and handling of nullable and when language algorithms fail to introspect and find the "obvious" solution, this feels worse than more general failures.

Conclusion

None today. We ran out of time and would like to talk about it more.