Closed gafter closed 7 years ago
I noticed you omitted the generic indexers request. Was that intentional, or perhaps it is missing because I didn't submit a complete proposal?
Language support for tuples might benefit from CLR unification across assemblies; see #347.
Just to add, other uses are function types and ASP.NET's [AssemblyNeutral]. Would it be useful for you if I outlined a design suggestion? And if I do, should it go here or to https://github.com/dotnet/coreclr ?
A de-facto Option(Of T).
@sharwell Can you please point me to the indexers issue you're talking about?
@ashmind Language suggestions belong here. CLR suggestions belong there. I'll add function types to the list of language features that would benefit from unification.
@AdamSpeight2008 I don't know what you're suggesting that would benefit from CLR support.
&
and |
work but ~
sometimes requires a conversion that cannot be expressed in IL.@mikedn Added to the list (as something we probably would not do).
@gafter It's the first comment in #166. The motivating example is currently in one of my Stack Overflow answers, but if you feel it merits further discussion I can write the proposal separately here.
Rather than do #161, which seems like a big change to the language for minimal benefit, I'd like to see the C# and CLR teams work together to come up with a non-garbage collected option for .NET development. This is probably outside the C# 7.0 timeframe though.
@sharwell If you could collect the most relevant bits into an issue/proposal that would be great.
Structural typing and intersection/union types. Right now structural typing is de facto supported in the compiler (foreach and await), but it could be elevated into either anonymous checks or into capabilities (implicitly implemented interfaces).
Intersection types would be useful for those cases when you need to work with objects that implement more than one interface. Of course, if you had capabilities, you could use them instead.
Union types are less useful at this stage, since existing libraries don't use them.
@orthoxerox Structural typing is already number 6 on the list.
Hi,
Serialization/Deserialization to express on IL level would have huge benefits in through-puts, and interop between IL/None-IL-Languages.
There is already a project from Microsoft: https://github.com/Microsoft/bond which is dealing with it, but it is just on language level.
@biqas I don't know enough about what you're suggesting to add it to the list. Can you please create a new issue describing what you're suggesting in more detail, and link to it in this thread?
@gafter
hope it is little bit more info's Binary layout schemas and transformations on IL-Level https://github.com/dotnet/roslyn/issues/526
@biqas #526 doesn't propose anything for C# of VB. It is a CLR/IL change proposal. This is a list of language changes.
@gafter yes you are right it was not proposing anything for C#, so you can remove it from here (sorry got the topic wrong:-) ). Maybe there will be or is already a something similiar for only CLR/IL, if so it would be fit there.
Generic indexers would be incredibly useful for Perspex. We use indexers to allow binding in initialization lists which means at the moment we have to forego compile-time checking. See https://github.com/grokys/Perspex/blob/master/Docs/intro.md#attached-properties-and-binding-pt-2 for an example.
@gafter I'd like to make a proposal regarding StackOverflowException
. Where would be the most appropriate place to put that?
@sharwell I have no idea because I don't know what you have in mind. If you want to propose a library/API change then you want https://github.com/dotnet/coreclr/
I like the concept of "CLR unification across assemblies", assuming it means structural type unification. I have written about the pain of the fact that Predicate<T>
is different from Func<T,bool>
and that an IList<T>
is not a IReadOnlyList<T>
(although the latter problem is obviously harder to solve in the runtime). There are lots of stupid thorny scenarios where it would be nice to be able to efficiently cast a value between two identical types that are not explicitly related.
The CLR was supposed to be a "common language runtime", so I think any features which allow more languages to be supported should be prioritized. To that end, I would like to see things like references that can point to managed or unmanaged memory (as required by D), dynamic interfaces via fat pointers (required by Go and Rust), efficiently growable slices (D again), covariant return types (any well-thought-out language), and union/intersection types (Ceylon, although this feature can be simulated without CLR support). Any forms of structural type equivalency might also help support new programming languages.
But among the easy-to-implement CLR changes, I like default interface implementations the most.
Tuples are already in the BCL, so why would we need to change the CLR? It would be nice to have a mutable value type version for optimization purposes though - MTuple<A,B,C>
?
I already implemented slices as a value type in my Loyc.Core library - CLR support could make them more efficient, but they need not be prioritized as you can write a slice type already, and you should be able to add slices to the CLR later in a backward-compatible way. Note that read-only slices could benefit from CLR support for covariant structs.
Here's a meaningful CLR feature related to slices: allow classes and structs to contain a fixed-length array of any type (not just unmanaged types). A reference to that array would be a slice. This is sometimes useful for implementing "exotic" data structures efficiently (another useful feature for exotic data structures: define IntRef<T>
, a union of an IntPtr
with a managed reference, which is treated as an IntPtr when the low bit is set to 1 and a reference to T otherwise. This feature is feasible only if it can be shown not to slow down the garbage collector).
I can understand if it's hard to allow System.Void itself to be a normal value for backward compatibility reasons, but why not add a new System.@void
or System.Empty
value to the BCL? The CLR could improve support for this type by allowing zero-size structures. That way, for example, Dictionary<T, @void>
would be no less efficient than HashSet<T>
.
Here are other features I would like to see in the CLR:
void Foo<T>(T? t)
with no constraint on T
). You could kill two birds with one stone: allow generic types and methods to have a prioritized sequence of implementations (i.e. constraints need not be disjoint). Then, the C# compiler could auto-generate a duplicate copy of Foo
, one for (T? t) where T : struct
and again for (T t) where T: class
. This would also make the generics system fundamentally more powerful. Allow generic types to have not just specializations of the entire type, but of individual methods and fields of the type, or arbitrary "sections" of the type (possibly-nested groups of methods and fields).Thread.Created
event that provides subscribers with a handle to the parent thread (I would also suggest supporting TLV inheritance, except that the damn PTO gave Sun a patent for that.)virtual
setter and a non-virtual getter.P.S. It seems like some people suggesting features are unaware that the terminology they have chosen has already been used with different meaning in academic papers and existing programming languages. The so-called "templates or structural interfaces" feature is not like any template feature I'm familiar with (nor is it like what I would expect structural interfaces to mean - interfaces identified by their structure, not by their name). I don't know why traits were grouped with this. "Virtual extension methods" are an awful name. "extension method" implies that a third party can create one, but "virtual extension methods" are not proposed to have this property. They should be called default interface implementations.
"not do...union types"
That's a real shame. There's significant room for improvement in the representation and handling of closed union types on .NET. With C# 7 getting pattern matching the logical progression is to union types. Maybe even an option type to replace null! :-)
Union types is the thing I miss most when I have to do C#. I realise that without the pattern matching to go with it, it is pretty much useless, like tuples. Closed union types can not be overstated.
@rojepp The Cω language from Microsoft Research included support for this:
choice {int; Button;} x = new Button();
choice {int; Button;} y = 1;
if (x is Button) { ... } // true
if (x is int) { ... } // false
@jdh30 @rojepp In the current pattern matching proposal discriminated unions are encoded in the same way as in Scala — with inheritance and case classes.
@apskim: Fine by me. Any representation of unions and pattern matching in C# would make the language infinitely more usable for me as I basically don't use C# because it lacks these features.
Support for higher kinds. Support for an effect system. SMT solver plug in for types -- Code contracts built in, extended. Pex functionality built in for declaring laws.
"Closed" union types? Isn't that a synonym for Algebraic Data Types? I prefer the strictly more powerful concept of open union types, as in Ceylon. Anyway, yes, pattern matching and ADTs don't need CLR changes.
P.S. I do wonder where one is supposed to propose CLR changes. Under Roslyn doesn't seem right.
@qwertie closed union types enable the compiler to prove a set of options (cases) is complete. Having said that, the existing "records" proposal is open union types.
@gafter I take it you aren't familiar with Ceylon's union & intersection types. If you were, you'd know that the compiler knows what cases are possible in any given situation and can check whether all cases have been handled. AFAICT, Ceylon's union type system is strictly more flexible than (closed) ADTs and doesn't sacrifice anything (except possibly type inference, which is not relevant when we're talking about CLR features, not compiler features. In the interest of full honesty, Ceylon-style union types are sort-of incompatible with Rust-style closed-union value types, but that's not really an issue since the CLR does doesn't support the latter anyway.)
Shouldn't there be a CLR-change
label? #4505
I dig "function types", isn't it under consideration, @gafter?
Nobody on the language design team is championing function types.
Covariance and contravariance for classes (see #171)
?If not, i'd like to see those on the list. Thanks!
Note: i'm only interested in these features if they can be backfilled over what existing stuff we have, and not if they require totally new APIs to be build. i.e. if we added variadic generics, but couldn't replace the existing Func/Action goop with it, then I don't see it actually being that useful. Same with structural delegates. I don't want to have to rewrite APIs or produce a new set of delegate types. I want a way for our existing delegates to gain structural semantics in the runtime, and to able to use that and work with that from C#.
Thanks!
@CyrusNajmabadi Covariance for method return types (#357) would use bridge methods and does not require CLR changes. There is no proposal for contravariance of methods.
There is no proposal for structural function types (which I find somewhat surprising). I gather you mean a shorthand notation for the platform types named Func and Action. I think it would be nice to be able to write int=>int as a shorthand for Func<int, int>, though there are likely to be interesting issues finding an unambiguous syntax. If that is what do, no CLR changes are required.
The two proposals possibly related to varadic generics (#5058 and #2212) aren't detailed enough to be evaluated as proposed language features. Both probably require CLR changes. I believe F# is hoping to get CLR support for higher-kinded generics.
@gafter
Predicate<string>
and Func<string,bool>
to be the same. I don't want to have to write ConditionalWeakTable<Blah, Fooby>.CreateValueCallback
when I could just say Func<Blah,Fooby>
. I find it so annoying that there are nominal semantics here and that I can't interchange any of these guys.@CyrusNajmabadi
Predicate<string>
and Func<string, bool>
be the same type would be a breaking change.Making
Predicate<string>
andFunc<string, bool>
be the same type would be a breaking change.
Wouldn't this possibly make function types more likely to happen? I think having a T => bool
implicitly convertible to both would address the compatibility issue.
I don't see why something being a breaking change matters. I'm all for breaking changes if the value is high enough. Not doing so leads to stagnation. TS, for example, was will to take on breaking changes with the latest release because the value was felt to be high enough.
Effectively, all of our features we do at any version were simply "not worth doing" the version before. And yet we still got around to them. That's what backlogs are for :)
_: Heck, we changed how "foreach variable capture" worked. That was a breaking change, but the value was there. And, indeed, I would say that we reallllllly_ should have made "comparing value to null is an error" even though it was a breaking change.
Breaking changes are a consideration with language changes. But they are not, in and of themselves, a blocker of them.
Would be nice if the CLR could at least make it very inexpensive to convert between structurally-equivalent delegate types rather than having to incur the double-invoke penalty. Then C# could potentially permit implicit conversion between them. I think that would largely satisfy these requests.
@CyrusNajmabadi TS has never taken a binary incompatible change. That would be like changing the semantics of the existing JS language (TS's equivalent to our "CLR support") in a way that changes the behavior of existing code. Making an incompatible CLR change is unlikely to be considered beyond this discussion.
@HaloFour I think the current implementation of CLR can already invoke structurally compatible delegates if you tell it to in CIL, since the function pointers are the same in the end. However, it's an unsupported feature of this specific implementation. Would be nice to obtain a guarantee that this will continue to work.
@orthoxerox Yes, but you'll still get an exception if you attempt to combine them with another delegate instance.
I would add "Unmanaged generic type constraint + generic pointers" to this list, as per https://github.com/dotnet/coreclr/issues/2322
In what sense are structural delegates a breaking change at the CLR level? It seems to me like all you have to do is let the verifier succeed in doing assignments and calls where otherwise it would fail.
Here's another item for my wish list: the ceq
opcode should be allowed to bitwise compare two arbitrary value types (and create an mscorlib function for invoking this opcode from C#). The fact that I can't do this decreases the efficiency of my VList
's SmartSelect
method and I'm sure other people must be affected by this too.
Now being tracked at https://github.com/dotnet/csharplang/issues/317
If we were to plan for one language feature that requires a revision of the CLR, then we might as well do as many of them at the same time as make sense. What changes would we consider for C# 7 and VB 15 that would benefit from CLR support? See #166 for related discussion. This is a pared-down list for us to select from.
Those that we would likely not do in this timeframe include