Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the result of `Regex::new` cannot be assigned to a constant?

Tags:

rust

I have many repeated constants in the form of:

pub const FOO_REGEX: Regex = Regex::new(r"foo.*").unwrap();
pub const BAR_REGEX: Regex = Regex::new(r"bar.*").unwrap();

I'd like to simply this by using a macro_rules! macro.

I tried:

macro_rules! pattern {
    ($value:literal) => {
        Regex::new($value).unwrap()
    }
}

pub const FOO_REGEX: Regex = pattern!(r"foo.*");

But the compiler complains with:

error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
  --> lib.rs:7:9
   |
7  |         Regex::new($value).unwrap()
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
11 | pub const FOO_REGEX: Regex = pattern!(r"foo.*");
   |                              ------------------ in this macro invocation

Per this guide I tried many of the available designators options, like expr, ident, but I'm still not able to get macro to compile.

Why does the literal designator not work for this macro expression?


1 Answers

This has nothing to do with macros: you get the same error if you write the code directly (playground). The problem here is that calling Regex::new is not a literal (1) and cannot be evaluated at compile-time (yet?). You will need to use something like the lazy_static crate to ensure that Regex::new is called at run-time to compile the regular expression:

use regex::Regex;
use lazy_static::lazy_static;

lazy_static!{
   pub static ref FOO_REGEX: Regex = Regex::new(r"foo.*").unwrap();
}

Playground


(1) Quoting from this answer:

A literal is a value written as-is in the code: true, 1, "hello"; the result of an expression [like Regex::new] cannot be a literal (by definition). The resulting types may look similar (or even be identical) but types are irrelevant here.

like image 108
Jmb Avatar answered Sep 19 '25 18:09

Jmb