[HN Gopher] Rust const generics MVP hits beta
       ___________________________________________________________________
        
       Rust const generics MVP hits beta
        
       Author : mfsch
       Score  : 240 points
       Date   : 2021-02-26 16:25 UTC (6 hours ago)
        
 (HTM) web link (blog.rust-lang.org)
 (TXT) w3m dump (blog.rust-lang.org)
        
       | simias wrote:
       | This is one of my big frustration with Rust and probably the only
       | feature from C++ I rally missed (C++ templates having "non-type
       | parameters"). I'm very happy to soon see it lifted.
       | 
       | There were workarounds for some common scenarios already, but
       | it's just so much more simple and convenient to be able to write
       | `fn foo<const N: u32>()`.
       | 
       | I'll finally be able to simplify a significant portion of my
       | code.
        
         | tspiteri wrote:
         | Lucky you :) In my case the only thing I could to do was to
         | change the README of my crate from saying that I plan to
         | migrate from typenum to const generics "when they are supported
         | by the Rust compiler" to now saying "when the Rust compiler
         | support for them is powerful enough". (I need constraints on
         | which ranges are allowed, and that is a little hairier than the
         | MVP; though typenum is perfectly adequate.)
        
       | jlrubin wrote:
       | This is amazing. Kudos rust team for nearing this milestone.
       | 
       | I use rust for a (to be released -- comment with your github if
       | you want early access) Bitcoin Smart Contract embedded domain
       | specific language (edsl) that operates sort of like a circuit
       | meta-programming language. Having const generics will drastically
       | simplify my code and enable greater "structural type safety"
       | (checked at the rust level rather than as a part of my edsl).
       | 
       | They're not wrong when they say that this is the most highly
       | anticipated feature :)
        
       | iamatologist wrote:
       | It must be hard to design a zero-cost abstractions language. It
       | seems that there are more and more terms and concepts that come
       | up in order to support more directly-pragmatic PL features.[1]
       | Reminds me a bit of how Haskell comes across to me from the
       | outside with all its GHC extensions. Haskell is a research
       | language but other more specialized functional languages have the
       | luxury of being able to theorize and implement more orthogonal
       | and perhaps more "elegant" concepts and approaches. (Again,
       | merely an impression from the outside.)
       | 
       | Consider the design effort behind parametric memory allocators.
       | That seems like a pretty cutting-edge problem. And yet I bet the
       | Rust folks knew that they would want/need to do this way before
       | they started doing that work in earnest, because people from C++
       | seem to want the same thing (if they don't have it already?).
       | 
       | I idly wonder if one could, if one was in a similar position as
       | Rust was some years ago, just go ahead and design a full-on
       | unapologetic type-level programming language from the start.
       | Because you _know_ that your type-level terms will be worthy of
       | the moniker "language" eventually (and it might not be a
       | compliment as such).
       | 
       | Just a nice, high-level language that doesn't bother with the
       | "bare metal" concepts that Rust the value-level language has to
       | deal with. (Can it even be done? Don't ask the peanut gallery
       | about that.)
       | 
       | Either that or you accidentally build an emergent language that
       | Gankro can write an article about one day titled, I don't know,
       | Shitting Your Pants With Higher-Order Unsafe Unwind Type-Level
       | Allocator Escape-Suppressing Storm Cellars.
       | 
       | [1] In this case: you have more use for compile-time integers
       | than something more general like being able to describe that two
       | nat-indexed lists are of the same length, like you can in Idris.
        
         | steveklabnik wrote:
         | You might like https://without.boats/blog/revisiting-a-smaller-
         | rust/, written by someone on the language team, on this topic.
        
       | doggodaddo78 wrote:
       | Super frickn cool! I was dying for this feature.
        
       | sam0x17 wrote:
       | This is so huge that it might actually relieve enough of my
       | frustration with Rust that I would try using it again <3
       | 
       | Very needed and cool
        
       | CodesInChaos wrote:
       | I'm really happy that this finally landed. Unfortunately the
       | limitations of the MVP are severe.
       | 
       | For example you can't use associated constant as generic
       | arguments, preventing constructions like this:
       | trait HashFunction {           const OUTPUT_SIZE: usize;
       | fn hash(input: &[u8]) -> [u8; Self::OUTPUT_SIZE];       }
        
         | rmdashrfstar wrote:
         | What's the progress on supporting something like this in future
         | versions?
        
           | steveklabnik wrote:
           | https://github.com/rust-lang/rust/issues/76560 is the
           | tracking issue for this specific feature.
        
       | SuperFluffy wrote:
       | Having const generics will also permit much more elegant
       | implementations of low level linear algebra.
       | 
       | For example, when writing a `GEMM` (general matrix
       | multiplication) routine, the core building block is a so called
       | kernel, which gets moved over the matrices like a stencil. The
       | size of the kernel however depends on a) the numerical precision
       | (float, double), b) the available SIMD intrinsics, and c) the
       | architecture the code is executed on (haswell, skylake or zen
       | have different latency and throughput for different intrinsics).
       | 
       | Right now it's surprisingly painful to write an optimal kernel
       | and buffer, which is different for every architecture and which
       | you need to kind of hardcode. With const generics this should
       | become much easier.
        
         | porphyra wrote:
         | Yes!!! Linear algebra!
         | 
         | I am a huge fan of nalgebra and having const generics would
         | make the API and implementation much nicer.
         | 
         | Hopefully the robotics industry can move towards implementing
         | stuff in Rust. Having low level robotics algorithms like state
         | estimation and SLAM in Rust makes perfect sense.
        
       | est31 wrote:
       | Users of the serde-big-array crate can already opt into using
       | min_const_generics by enabling the const-generics feature. The
       | advantage: you no longer have to list a bunch of needed array
       | sizes (or rely on the builtin defaults), but can use whatever
       | size you want.
       | 
       | Serde proper needs something like const_evaluatable_checked
       | before it can offer large array support.
        
       | steveklabnik wrote:
       | I am extremely excited for this feature, especially now that I
       | live in "absolutely no allocations" embedded land.
       | 
       | But also, beyond that, this is pretty much the last major feature
       | that I've wanted in Rust. I've got some long-form writing in my
       | head about this, but previously, I would have cast it as two or
       | 2.5 features:
       | 
       | * const generics
       | 
       | * GATs
       | 
       | * specialization (this is the half)
       | 
       | However, when I've started to think about explaining these sorts
       | of things, GATs (and to some degree specialization) feel much
       | more to me like a removal of a restriction on combinations of
       | features, more than "new features" strictly speaking. I think the
       | line between these two perspectives is fascinating. On some
       | level, you can even cast const generics in this way too: what
       | it's really doing is making arrays a first-class feature of the
       | language. I think that's a bigger stretch than GATs though, so I
       | am not fully sure I'd make that argument. (The minimum feature
       | we're stabilizing now basically does only this, but we do plan on
       | going farther, so it feels true on a technicality now but not
       | later.)
       | 
       | Regardless, it's been nice to see how much we've slowed down in
       | adding major things. November of 2019 was the last time we had a
       | feature this large hit stable. 18 months between huge things
       | feels much more like the cadence of more mature languages that
       | have been around a lot longer than Rust.
       | 
       | There is still a lot of work to do removing restrictions on
       | existing features, especially const fn and const generics. But
       | Rust is really starting to feel "done" to me, personally.
        
         | thenewwazoo wrote:
         | After writing embedded Rust, loving it, and then losing that
         | job, I've gotta ask what you're up to these days (mostly so I
         | can live vicariously through you). I am _dying_ to write Rust
         | in the embedded space again. :)
        
           | cpeterso wrote:
           | Steve works at Oxide Computer and they are hiring. :)
           | 
           | https://oxide.computer/careers/software-engineering/
        
             | doggodaddo78 wrote:
             | TY, probable Moz Rustacean. :hands together emoji:
             | 
             | I've been living on savings in self-sabbatical mode while
             | catching-up on life, projects, and reading while keeping
             | current with Rust.
             | 
             | I'm soo itching to jump back into workaholism mode.
        
           | steveklabnik wrote:
           | Oh no! Hope you can get back to it soon.
           | 
           | https://oxide.computer/
           | 
           | https://news.ycombinator.com/item?id=23975445 is probably the
           | most accessible thing we've talked about publicly with what
           | we're doing. (This talk was what made me decide to apply.)
           | Still early enough the focus is on building the product
           | rather than talking about it to broad audiences like HN.
        
             | doggodaddo78 wrote:
             | Hire me! Jumps-up-and-down over-eagerly like a nerdy new
             | college grad. I'll wave around cheerleading pompoms or
             | aircraft marshaling wands until you do. ; D
             | 
             | Excessive, horn-tooting quasi- resume/cover letter in an HN
             | comment (maybe I should've compressed and uuencoded?).
             | 
             | Home: Austin downtown, via much of NorCal { Chico,
             | Sacramento, and Bay Area }, from San Jose.
             | 
             | Experience with embedded systems on many architectures and
             | different types of RT deadlines, SMT electronics (PCB
             | design and fabrication, stuffing, and repair), Rust (I sure
             | hope so!), C/C++ (autodidacted at 15), LLVM, several
             | assembly languages (ARM, X86, MIPS), microcontrollers,
             | large-scale industrial firmware development (automotive,
             | mining, & agriculture).
             | 
             | I periodically throw 3D printing and Arduino or ESP32 at
             | personal use-cases. And trinocular microscope, Siglent
             | scope, and knock-off compatible JBC solder station. The
             | Fluke 289 DMM is real though.
             | 
             | Can do everything from sales engineering, on-prem/remote
             | custom client integration, customer training, feature
             | development, tools support, customer bug forensics,
             | subgroup lead SWE, systems architecture/engineering,
             | customer solutions development. Make the office more funner
             | now and then (especially internal funny 404 pages and
             | easter eggs, tape your chair up, orbeez explosion, get your
             | wife/SO and kids in on a gaslighting long-con). 5C/ charge
             | per instance. Wooden nickels not accepted. No refunds. :)
             | 
             | Did one or two minor humblebragging things:
             | 
             | - Ported a ridiculous nuclear reactor simulator in Fortran
             | from UNIX to Windows.
             | 
             | - IBM Almaden offered me a dark matter research assistant
             | job when I was 15, but my parents weren't supportive and it
             | would've been illegal. :Y U No moon meme here:
             | 
             | - Wrote a Java-- to native MIPS (non-JIT, compile-time)
             | compiler from scratch with symmetrical implementations in
             | Java and C++.
             | 
             | - Refactored the heck out of a UDP 900 MHz packet radio
             | firmware C++ codebase and added telemetry logging with
             | error tolerance of Flash EEPROM wear beyond mfgr specs.
             | 
             | - Restoring & modding a VW camper and getting into
             | paramotoring (parachute wing and motor on your back).
        
               | steveklabnik wrote:
               | Oh hi neighbor! I also live in downtown Austin.
               | 
               | Please apply! We are hiring.
        
               | doggodaddo78 wrote:
               | Heck ya! : D I could work on embedded and datacenter gear
               | for free if I didn't have bills and a spinning circular
               | vinyl noise-makers addiction.
               | 
               | Yeah, I've been pining for highly-integrated, hyperscale
               | datacenter metal. Only Fortune 50 corporations and
               | partakers of OEMs/ODMs like Quanta QCT / Dell DCS deliver
               | somewhat okay customized gear, but not a completely-
               | integrated, managed fleet. I remember eGenera BladeFrame,
               | but it's still nothing like a hyperscale, intermodal-
               | container LEGO datacenter solution.
               | 
               | Oh hey from I-35 and 5th!
               | 
               | Here's your "I probably survived the 2021 ATX
               | Icepocalypse" tie-dyed hoodie with black light effects.
        
               | 4ad wrote:
               | > Please apply! We are hiring.
               | 
               | You certainly aren't replying to you applicants, though.
        
               | steveklabnik wrote:
               | Hm, we should be! Sorry about that. The aim is to reply
               | to literally everyone. If you wanna email me, I'm happy
               | to look into it.
               | 
               | EDIT: I decided to take a look, and it seems like you
               | applied before I joined. My apologies, it must have been
               | a mistake.
        
               | 4ad wrote:
               | > My apologies, it must have been a mistake.
               | 
               | Well that mistake seems to keep repeating itself then.
               | 
               | Oxide has been silent even after subsequent contact, and
               | even after this issue has already been raised internally
               | once.
        
         | akavel wrote:
         | For me, a feature I'd really hope for is the elusive "if not
         | let" (or however this gets named eventually), to let me escape
         | the currently unavoidable clutches of Rust's rightwards drift
         | and accruing mental context.
        
           | NobodyNada wrote:
           | Swift has had 'guard' statements since 2015, and it's the
           | biggest thing I miss when programming in Rust:
           | guard let x = ... else {             // must not fall
           | through, so a return, break, throw, non-returning function
           | call, etc. is required         }         // do something with
           | x
        
           | yazaddaruvala wrote:
           | Lol it would be kinda funny to have this:
           | let input: Option<usize> = Some(1);         if let
           | Some(value) != input {             return 0;         }
           | // use value; such that value: usize = 1
        
         | the__alchemist wrote:
         | Could you please post an example of how it helps in embedded /
         | no allocator code? I do a good deal of embedded on Rust, but am
         | having a tough time figuring out when or why to use this from
         | the abstract examples in the article.
         | 
         | Tangent: What's your take on the Rust HALs? (eg `stm32l4xx-
         | hal`) etc? I'm curious what the take is of someone outside the
         | Github and Matrix communities. They strike me as... remarkably
         | underdeveloped, but have big potential.
        
           | steveklabnik wrote:
           | > Could you please post an example of how it helps in
           | embedded / no allocator code?
           | 
           | In today's Rust, data structures often need to be a fixed
           | size, or dynamically allocate. This will let you write a data
           | structure that has a variable size, but set at compile time.
           | I knocked out a quick ringbuffer recently; I picked a size
           | that seemed fine, but that size is fixed at the moment. If I
           | had used const generics, it could have been more flexible
           | here, I could have written it more easily for any size, where
           | the size is written at compile time. This is _not_ my work
           | code, but back when I was working on a hobby x86 kernel, I
           | did this for a VGA buffer: https://github.com/intermezzOS/ker
           | nel/blob/master/vga/src/li... it's generic over "something
           | that can be converted to a slice," so that it uses a slice in
           | production, but a Vec in tests. This also leads to runtime
           | checks https://github.com/intermezzOS/kernel/blob/master/vga/
           | src/li... to make sure that the slice is the right size. This
           | would be much better written with const generics today. The
           | slice trick is neat, but awkward. (This code is also awkward
           | because it grew an internal "frame buffer," so it kinda has
           | both going on. This example needs const generics less since
           | VGA has one single size at compile time ever, but sometimes,
           | you need something where this isn't the case, and this was
           | the first example of code I personally wrote that springs to
           | mind.)
           | 
           | > What's your take on the Rust HALs?
           | 
           | I haven't used them enough. We use the layer below them, for
           | example, the stm32f4 crate rather than the stm32f4xx-hal
           | crate. That doesn't mean they're bad, I just literally have
           | not used them enough to form an opinion. The namesake of this
           | space is diversity, and so different people make different
           | tradeoffs; we don't really need what those crates are
           | offering right now.
        
         | RcouF1uZ4gsC wrote:
         | So excited about const generics. Is there any work on variadic
         | templates. That is one of the big things I miss from c++.
         | Macros can fulfill some of the needs, but not always.
        
         | glittershark wrote:
         | I think it probably falls more into the category of removing a
         | restriction rather than a new feature, but I'm still waiting on
         | HKTs - not for traits (as a former die-hard haskeller, I have
         | been gradually converted to the side of "rust doesn't need a
         | Monad trait") but for data types. There's a design pattern in
         | haskell called "Higher-Kinded-Data"[0] where you parametrize a
         | datatype on a type-constructor, and use that to generically
         | define either partial or total versions of that data type-
         | something like (in rust syntax):                   struct
         | Person<F> {             pub name: F<String>,             pub
         | age: F<u32>,         }
         | 
         | where you can then have `Person<Option>` be a person that may
         | or may not have all fields filled, and `Person<Box>` be a
         | person with all fields definitely filled. This is something I
         | find myself reaching for surprisingly frequently when writing
         | rust, and I feel like it's a missed benefit of implementing
         | higher-kinded types.
         | 
         | [0]: https://reasonablypolymorphic.com/blog/higher-kinded-data/
         | 
         | All that said, I'm really excited to have const generics land!
         | Props to all the amazing work by withoutboats and the entire
         | rust team.
        
           | adamch wrote:
           | Wow, higher-kinded data. I've never heard of that, but it
           | would absolutely be useful. E.g. for converting JSON inputs,
           | where any field might be missing, into a version of the data
           | which definitely has values for all the fields. Or a version
           | of the struct where the values are actually read from a
           | cache/database.
        
             | twic wrote:
             | I proposed using it to model lifecycles of entities:
             | 
             | https://github.com/tim-group/higher-kinded-
             | lifecycle/blob/ma...
             | 
             | (in this code, "idea" is a domain concept from the firm i
             | worked for at the time - basically a recommendation to buy
             | a stock, which is 'opened' on a certain date, and 'closed'
             | when it no longer seems like a good recommendation)
             | 
             | My collegues didn't like it, and stuck to using separate
             | types for objects in different stages of the lifecycle!
        
             | IggleSniggle wrote:
             | TypeScript (as you might expect from a lang built for
             | dealing with JS Objects), has really great tooling for this
             | kind of type narrowing these days (including on string
             | template matching now) and I miss it _so much_ now that I'm
             | writing Go.
        
             | glittershark wrote:
             | yes! once you use it you start wanting it everywhere, which
             | is a big part of why I wish I could do it in Rust
        
           | michael_j_ward wrote:
           | This might be of interest to you (this is the second article
           | in the series, and they've been good so far)
           | 
           | https://rustyyato.github.io/type/system,type/families/2021/0.
           | ..
        
           | meetups323 wrote:
           | In TS this would be flipped:                   type Person =
           | {          name: string;          age: number;         }
           | type SomeFieldsMissing = Partial<Person>;         type
           | AllFieldsRequired = Required<Person>; // No real change in
           | this case
           | 
           | Where Partial and Required are defined like:
           | type Partial<T> = { [P in keyof T]?: T[P] | undefined; }
           | type Required<T> = { [P in keyof T]-?: T[P]; }
           | 
           | What would you think of something like this ("mapped types")?
           | They can get fairly powerful:
           | https://www.typescriptlang.org/docs/handbook/2/mapped-
           | types....
        
             | glittershark wrote:
             | that seems like something that would only really work with
             | a type system that's as structural as TS (vs rust, which is
             | very nominal)
        
             | kazoomonger wrote:
             | What would happen if I wanted only some fields to be
             | required? To borrow from the GP example, something like
             | this:                   struct Person<F> {             pub
             | name: F<String>,             pub age: Option<u32>,
             | }
             | 
             | With `Person<Box>` still leaving `age` as optional.
        
               | IggleSniggle wrote:
               | Yes, you can do this in typescript, but you can also lie
               | about it in typescript. To do it provably, you would
               | construct a function that accepted the more generic
               | version and then, using type assertions (ie the
               | typescript compiler infers the type from declared runtime
               | behavior), it would return a narrowed type.
               | 
               | If one caller passes our type narrower with {age:F<u32>}
               | then the return value of the function will be narrowed to
               | that type, but a broader criteria can still be specified
               | for the generic instance.
        
               | meetups323 wrote:
               | Yeah there's going to be tradeoffs either way, the
               | question is how often they come up in the situations the
               | language is designed to target (versus random examples
               | designed to showcase some obscure corner of PLT)... In
               | this case for TS you might craft your own mappings that
               | work like AllButXOptional<Person, 'age'>, or similar. So
               | it's controlled externally versus internally, which who
               | knows if thats better or not. One benefit of the TS
               | approach is that it's a bit more composable... you can
               | imagine things like
               | OptionalIfRequiredInOther<ComplexPerson, SimplePerson>.
        
               | wizzwizz4 wrote:
               | Add an extra generic parameter.
               | 
               | (Also, it shouldn't be Box; you'd want a bog-standard
               | generic newtype for this, not an extra heap allocation.)
        
               | glittershark wrote:
               | yeah, I picked Box mostly as a pedagogical instance of
               | the identity functor that already exists in the stdlib -
               | in the real world you'd definitely want `struct
               | Identity<F>(F)` instead.
        
           | steveklabnik wrote:
           | I like and enjoy HKTs in other languages, but don't feel a
           | super strong need for them in Rust. I know some other people
           | differ. It is very unclear when, if ever, Rust will get HKTs
           | proper. GATs cover a lot of the same ground. We'll see :)
        
         | mamcx wrote:
         | I also wish for extensible enums and enum subset:
         | pub enum Expr {             Int,             Str         }
         | pub enum Expr2 : Expr{             Bool,         }
         | fn check(??)-> Expr.Int
        
           | mamcx wrote:
           | And struct extend!:                 struct Person {
           | id:i32       }            struct Customer: Person {
           | }
           | 
           | P.D: This is not subclassing, is not redefine all the same
           | attributes again and again. Is partially supported to copy
           | the values but not defining them.
        
       | proverbialbunny wrote:
       | This is a pretty big deal. One benefit it gives is it's much
       | easier to write code evaluated at compile time. Most Rust
       | libraries use generics, so if you use a library, compile time
       | support isn't usually available. By adding support for const
       | generics compile time support can become widespread.
        
       ___________________________________________________________________
       (page generated 2021-02-26 23:01 UTC)