-
Notifications
You must be signed in to change notification settings - Fork 48
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
Types as const Parameters #61
Comments
This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed. |
Zulip link above is broken; use this one instead. |
We discussed this in the 2020-10-19 lang team triage meeting. This sounds like it could be a nice simplification in the future, and the idea of reifying more of the type system into values is interesting. However, this builds on const generics, which are still ongoing. There are also still plenty of unknowns here, like how to use these values to produce items. So like we've been doing with other steps-to-variadic-generics RFCs for now, @rfcbot close (As this is a close I'll check the boxes of those who were in the meeting.) |
Team member @scottmcm has proposed to close this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
The final comment period, with a disposition to close, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. |
Per the FCP above, closing the issue. Thanks @pthariensflame! |
Project Proposal: Types as
const
ParametersSummary and problem statement
Rust’s current(ly planned) generics allow three distinct and unrelated forms of generic parameter: types, lifetimes, and
const
values. Here we propose a way to unify the three by making the first two particular cases of the third, retaining the existing separate syntax as a simple sugar over the unified form, and thus preserving full backwards compatibility. This automatically subsumes variadic generics, as well as arbitrarily more complex and expressive forms of data structures and computation over types, as ordinaryconst
Rust.Motivation, use-cases, and solution sketches
As Rust gets more and more expressive
const
computation, and unlocksconst
generics, it's become apparent that the language for working with types is noticeably less expressive than the language for working withconst
values. Some particular pain points include the ability to use data structures of values, such as slices, orOption
s, but that types have no such capabilities. Variadic generics have been proposed a number of times to address this partially, but none of these attempts have gotten far. Further, there are cases of a type constructor wanting to accept a variable number of types in a non-list-like way, which variadic generics don’t handle well if at all.Here we propose a single extension to Rust’s generics system that automatically solves both of the above problems and then some, while arguably simplifying the generics model rather than further complicating it. The idea is to treat each of types and lifetimes as just another type of
const
value, desugaring “normal” type and lifetime generic parameters toconst
generic parameters (e.g.,desugars to
, and each can be written in user code just when the other can). To accomplish this, a new standard module
{core, std}::type_level
will be introduced, and typesType
andLifetime
will be placed within it (names very bikesheddable). These two types can only appear inconst
context: as the types ofconst
values,const
generic parameters, and function parameters ofconst fn
s (list not meant to be exhaustive but only suggestive). The previous example’s declaration would then desugar from (e.g.)to
. Likewise, (non-generic) associated types in traits would desugar to associated
const
s of typeType
, and similarly for non-associated type aliases. (Making that desugaring work for the generic case naturally extends the ability to have generic parameters toconst
s of all kinds, which seems reasonable, if not particularly motivated unto itself.)What does this unification buy us? For one thing, we now have variadic generics "for free": we can just use slices of types! For example:
Tuples of
const
-computed form can be supported easily by introducing{core, std}::tuple::Tuple
with exactly the above declaration signature, and making existing tuples desugar to it.Having types and lifetimes as
const
values lets us writeconst fn
s manipulating them, and lets us put them in additional data structures besides just slices. For example:Rose<Type>
whereRose
is defined as:const
generic parameter to a type of "heterogenous trees", a.k.a. nested tuples;Option<Type>
would be usefulconst
generic parameter to an "optionally typed box", i.e., something likeBox<Any>
but where the contained type might or might not actually be specified;FSM<Type>
, where each node is associated with a type and there's a marked “current” node, is a useful generic parameter to a coroutine/generator in order to describe which possible types it canyield
when.The unification of types and lifetimes under
const
s also makes it easier (though still not immediate or automatic) to implement higher-rank constraints quantifying over types andconst
values rather than just lifetimes, since the work of dealing with lifetimes as a special case will already have been done and much of it could probably treat types and (other)const
s the same way.A third member of
{core, std}::type_level
is needed if we want to expressconst
computations around constraints:Constraint
would be the type of (fully specified) constraints, while bounds would be treated as unary type constructors of eventual typeConstraint
rather thanType
. Like its fellows,Constraint
would only be usable at typechecking/const
-evaluation time. We don't see a need to introduceConstraint
at the same time asType
andLifetime
, though; it can be added later, or not at all, and the rest of the above will still work perfectly well. HavingConstraint
would also make static assertions much easier to specify and use, as they could just take one or moreConstraint
s and check them in the standard way.Prioritization
This fits into the lang team priorities under both “Const generics and constant evaluation” and “Trait and type system extensions”, as well as to a more limited extent under “Borrow checker expressiveness and other lifetime issues”.
Links and related work
In addition to the attempts at variadic generics linked above, this also relates by its nature to HKTs and GATs, as well as
const
generics as a whole. The author is certain there are many more interested parties but doesn't know how to find or link them; help would be very appreciated here.The ideas here are of course broadly related to dependent types and the uses they've been put to; a closer analog to this exact feature are the
DataKinds
andConstraintKinds
features of GHC Haskell. To the author's knowledge, no other language has implemented something like this short of implementing full dependent types; in particular, C++ continues to maintain—and even reinforce—the distinction between types andconstexpr
values that this proposal would like to erase.Initial people involved
The author (@pthariensflame) has been privately stewing this idea over for a few months; to their knowledge no one else has yet proposed this for Rust.
The text was updated successfully, but these errors were encountered: