What does `~const` mean?

Hi All, I find ~const as generic bounds in Rust's source:

I know it is an unstable feature and sometimes can be ignored. But I still wondering what is the purpose of ~const here. Can someone give a clue?

To use methods in traits as const fns in const contexts. The design is here

Update: note the experimental ~const syntax seems to not appear in nightly Rust any more. Instead follow the latest keyword generics initiative (design) if you have more interests in it:


I have just been doing exactly what's been described behind some of those links: duplicating code for async & non-async (particularly duplicating code that's using rayon to become optionally async instead). In my case, this didn't only affect functions or methods, but also closures.

The new approach to be generic over "keywords" seems to be like some sort of "workaround" (or ?patch) for limitations in Rust's type system, without overhauling the system entirely. As answered in the accouncement:

Q: Are you building an effect system?

The short answer is: kind of, but not really. "Effect systems" or "algebraic effect systems" generally have a lot of surface area. A common example of what effects allow you to do is implement your own try/catch mechanism. What we're working on is intentionally limited to built-in keywords only, and wouldn't allow you to implement anything like that at all.

What we do share with effect systems is that we're integrating modifier keywords more directly into the type system. Modifier keywords like async are often referred to as "effects", so being able to be conditional over them in composable ways effectively gives us an "effect algebra". But that's very different from "generalized effect systems" in other languages.

I'm curious how this will work out, and I suspect it's not an easy problem to tackle. I assume it would take a while until this becomes stable, so duplicating code will be required for now.

Async closures has their own stories:

I don't know if keyword generics would come true, but just to share what Graydon said about it:

In addition to the syntax being far too bitter a pill to swallow, I think this adds too much cognitive load for too little gain (and there's much more load ahead as details are worked out). Users reading and writing code are already too close (or often way beyond) their cognitive limits to add another degree of polymorphism.

Const, fallibility, and async are all very different from one another in Rust; making an analogy over them is misguided. Async implementations use fundamentally different code (separate data structures and system calls) than sync, whereas const is a strict subset of non-const and can always be called transparently from a runtime context. And a different (though livable) solution to fallibility has already spread all through the ecosystem with Result and having maybe-fallible methods define themselves with Result<T, Self::Error>, with actually-infallible traits defining type Error = Infallible. This works today (you could finish stabilizing ! but otherwise .. it works).

IMO this whole effort, while well-meaning, is an unwise direction. Writing two different copies of things when they are as fundamentally different as sync and async versions of a function is not bad. Trying to avoid the few cases that are just block_on wrappers aren't worth the cost to everyone else by pursuing this sort of genericity. At some point adding more degrees of genericity is worse than partially-duplicated but actually-different bodies of code. This initiative greatly overshoots that point.

Please reflect on how many times Rust usage surveys have come back with "difficulty learning" as a top problem. That is a very clear message: don't add more cognitive load. Really, Rust needs to stop adding cognitive load. It's important. "Being more Haskell like" is not a feature. Haskell's ecosystem of hyper-generic libraries reduces the set of potential users dramatically because of the cognitive load. That's not clever and cool, it's a serious design failure.

1 Like

Yeah, it's horrible. Besides completely missing the point (it's really not about keywords but types, yikes!), it seems exactly like the "pile of complexity" that badly-designed languages accumulate over time. "Let's shove these two features together and call it a third one!" is an empirically bad way of designing language features.


To be updated again