-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: Statically resolved type parameters #8986
Comments
Also this could resolve and remove any typeof tests for the specific types as it does for value types https://gist.github.com/benaadams/c6c109982f50c6f69af2#file-generictypeof-cs-L695-L738 |
How would this work across assembly boundaries (assuming no specific type constraints)? Also, I think the syntax for constraints is confusing. For example, currently |
I'm thinking that this shouldn't be allowed for PS: I've updated the opening post to address those ambiguities. |
That sounds similar to my trait/typeclass proposal. However, I think that restricting compile-time generics to a single assembly greatly limits their usefulness. I am personally willing to wait until CLR can support them natively. Or perhaps something weird like an unusable class could be used to expose traits to external assemblies? [Trait]
public abstract class TAddable
{
public static TAddable Zero()
{
throw new InvalidOperationException();
}
public static TAddable Add(TAddable left, TAddable Right)
{
throw new InvalidOperationException();
}
private TAddable()
{
throw new InvalidOperationException();
}
} On second thought, this is a remarkably ugly declaration. |
@orthoxerox Abstraction on top of primitives like what you suggest doesn't really fit into C# stack as a managed language. Rust or Haskell on the other hand, have a nice abstraction on top of primitives and you can define and expose your abstraction with zero overhead because a lot of things get inlined and everything. Personally I like the idea but I don't see it as useful in C#. For example take my example for As for exposing traits, if interfaces could contain operators, static members, etc, there is no reason to introduce |
@alrz Except that's not what you're doing. By explicitly enumerating all allowed types you are simply producing a better T4 template, since you cannot reuse your method for any other suitable type. Yes, if interfaces could contain non-virtual members they would be as good as traits, if a bit more cumbersome to write. You could write (I replaced your public interface IAddable<T>
where T : IAddable<T>
{
static T operator+(T left, T right);
static T Zero { get; }
}
public T Sum<static T>(this IEnumerable<T> source)
where T : IAddable<T>
{
T sum = T.Zero;
foreach (var item in source) {
sum += item;
}
return sum;
} |
@orthoxerox This proposal doesn't need CLR changes. Whereas, I have no idea how would your example work. Also, you pub trait Add<RHS = Self> {
type Output = Self;
fn add(self, rhs: RHS) -> Self::Output;
} Because there is no guarantee that rhs also be of type I'll note that F# falls back to reflection beyond assembly boundaries. Which, in my opinion, is horrible. |
@alrz My proposal is yours. If no CLR changes can be done, interfaces with static members are destroyed when the assembly is built and can only be used to constrain statically resolved generic parameters. If CLR is modified to support non-virtual interface members, then interfaces with static members are part of the API and can be used by any language that bothers to support them. |
@orthoxerox Yeah, there are proposals for operators and static members in interfaces. I don't know if that is a reliable option anytime soon. But here I just assumed zero CLR changes. That's it. |
We are now taking language feature discussion on https://github.com/dotnet/csharplang for C# specific issues, https://github.com/dotnet/vblang for VB-specific features, and https://github.com/dotnet/csharplang for features that affect both languages. |
Statically resolved type parameters
Considering that standard generic type parameters are mapped to CLR generics and have some limitations, statically resolved type parameters can be useful in conjunction with constraints that don't have a corresponding CLR representation, e.g. (static) member constraints, generic numeric code, etc.
Statically resolved type parameters are indicated by a caret symbol like
^T
and can infer members and operator constraints. Although, constraint inference is only allowed for non-public methods because otherwise it's like we're inferring public contract from usage which will be hard to reason about.For more complex members, we can define interface-like types that only exist at compile-time (similar to TypeScript interfaces).
Every distinct usage of the function
F
causes to generate a distinct overload with the type parameter^T
replaced with the actual type in use. And because of that, we can define rather complex constraints that are not dependant on CLR compatibilities and use them with arbitrary types. Note that constraint definitions cannot bepublic
and IVT has no effect because they don't exist beyond assembly boundaries, and also they only shall be used as a constraint for statically resolved type parameters.To safely expose the generated methods we can constraint them to specific types (#3255) — to be generated in the resultant assembly. For example,
Generates two overloads for each of these types, namely
int
anddouble
. The method body must be valid for each of those types in place. Constraint types are not allowed to be used in this context.Using both kind of type parameters can become tricky but also can be useful to be able to use member constraints and take advantage of runtime generics as well. Statically resolved type parameters must be defined after any standard type parameter because they will be erased at compile-time.
Using statically resolved type parameters in classes probably needs generating distinct classes with different names which can result in unpleasant side effects; Type erasure (read Java generics) can be another option though but I'm not proposing anything in this regard.
PS: This is somehow related to #154 but it seems that it is just a list of nice-to-haves.
The text was updated successfully, but these errors were encountered: