Quick Thought: const{} blocks


#1

Looking at async fn+async{} and unsafe fn+unsafe{} made me think, what about const{}?

As an example, (function-level) static_assert!(N == M) could just be const { assert_eq!(N, M) } (Ref Idea: Static assertions & RFC #2345 Allow panicking in constants)

I could also imagine something like match x { 0..N => ..., N..const{2*N} => ..., _ => ... }.

You could think of this as const { A } => (const || { A })(), like with async – not that const closures exist today.


#2

What are the proposed semantics of such a block construct?

  1. Can you mention any variables from outside the construct? (for example const generic parameters to a function?)
  2. Should use of const { .. } be linted / allowed inside const fn and indeed nested uses of const { .. }?
  3. Are the contents of const { .. } always evaluated at compile time?

#3
  1. Ideally yes, like with async{} and unsafe{}, once const generics exist. But as a first step it could follow const item rules, and thus would only be able to reference other const items.
  2. Yes, same as with nested unsafe{}
  3. That’s what I was picturing, yes. Like expressions used in the length of an array.

#4

It never occurred to me to try this – but TIL.

I think this idea is worthwhile and your answers all seem reasonable.


#5

I like this too :slight_smile:

I think this might involve the same “errors at monomorphization time” problem, though.

There would also definitely need to be a lint for redundant usage. For example

const FOO: usize = const { 4 };

#6

I’m guessing that any errors that occur evaluating the code in a const block become compiler time errors?


#7

I might be crazy, but my first thought on seeing this topic title was “oh neat, we’ll get lazy_static built into the language”. I don’t know how related that would be to your idea, just food for thought.

(My main use case is just const HashMaps or the like.)


#8

That would then need to be a const pattern (?). Not sure this particular addition would be worth the complexity, one could simply calculate a separate constant and use this instead, which may be more desirable for documentation purposes, anyway.

const MAX = 2 * N;
match x { 0..N => ..., N..MAX => ..., _ => ... }

:+1: to the rest, though! :slight_smile: