meetings/2017/LDM-2017-12-04.md
Warning: These are raw notes, and still need to be cleaned up. Read at your own peril!
QOTD: "Days since working around the JIT: 0"
QOTD: "What's wrong with dangerous?"
QOTD: "If we disallowed Dangerous in method names, Dangerous Dave wouldn't compile!"
Span and ReadOnlySpan implement the foreach pattern with GetEnumerator() etc., even though they don't implement the IEnumerable<T> interface. (Interesting aside, the Current property is ref-returning, which the compiler is quite happy with.)
But it's faster to iterate them like an array, by using the Length and the indexer. We want to allow that for spans as well. We would keep the enumerable around, which also allows write access to the elements of a Span.
Interesting to consider opening up for a new Length/indexer foreach pattern, that's opted into e.g. with an attribute.
Definitely allow it as an optimization. The general case; not now, and maybe not ever. Better to limit it to compiler-known types, that are guaranteed to have equivalent semantics.
If you have overloads
void M(in DateTime d) { }
void M(DateTime d) {}
M(myDT); / ambiguity
Options in tie breaker:
How would you legitimately end up in this situation:
in, but must keep value for binary compatWe currently do 3. We should do 2. 1 is too arbitrary.
People might want to move existing calls to the in version, and we won't be helping them. But that's an analyzer.
Problem with operators. They can't use in when applied, so can't move away from val behavior. Oh well.
Go with 2. Roll out as bug fix.
Lots of types (especially new ones, like Span, Memory etc., but also string) would benefit from being fixed.
Span<T> currently has a DangerousGetPinnableReference method for this. We can make this a pattern.
It's a thin layer of syntactic sugar.
Let's do it. Extension methods are allowed (as always when we add new patterns). Let's aim for 7.3, but not super high pri.
We allow ref this but not the other way around. That's wrong! We can't disallow ref this, but we should allow and prefer this ref.
Fix it. Go out as a bug fix.
There's a bit of a mess around when captured variables in local functions are definitely assigned.
This is different from lambdas, because local functions take all calls into account.
The forthcoming ECMA spec changes the wording of these rules, so that they are not defined based on reachability.
Proposal:
We like this. It could give errors in a few cases that don't today (including the bug report).
Is this an acceptable breaking change? In order to get an error, you'd have to have:
Both are unlikely, undesirable and easily fixed. We'll check with compat council.
Needs to be defined by the language, in order to deal with long tuples, and to recursively apply == rather than Equals.
If somebody wrote their own ValueTuple with user defined equality, then this would break the use of that. That's not a supported scenario; you could get into the same kind of trouble with Nullable<T>.
For tuple literals, there is a tension between left-to-right evaluation and performance.
It seems that t1 == t2 should mean the same as t1 == (t2.Item1, t2.Item2). The upshot of the feature really is to deconstruct tuples (if they aren't already, by being tuple literals), then do point-wise comparison.
We will evaluate all operands left to right, recursively through tuple literals, and save to temps. We don't evaluate target-typed things, and we don't yet convert them.
Then we do point-wise == (or !=, in element position order, separated by && (Or for !=, ||). This may involve conversions. We are ok with those happening "late", and conditionally (won't happen if previous comparison failed), because conversions aren't usually expected to have side effects.
For dynamic we think we can allow it by just converting the result of, e.g. d == e (where d is dynamic) to bool.
Conversion from tuples matter, but not to tuples. If I have a Foo and a tuple, and Foo converts to tuple, then that won't help you.
We think we have it, but will revisit during implementation.