mz_sql/session/vars/
polyfill.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! The types in this module exist to overcome limitations of the Rust compiler, namely limitations
11//! in const generics.
12
13use super::Value;
14
15/// Trait that helps us convert a `fn() -> &'static impl Value` to a `fn() -> &'static dyn Value`.
16///
17/// For creating a type that implements [`LazyValueFn`] see the [`lazy_value`] macro.
18///
19/// Note: Ideally we could use const generics to pass a function pointer directly to
20/// [`VarDefinition::new`], but Rust doesn't currently support this.
21///
22/// [`VarDefinition::new`]: crate::session::vars::VarDefinition::new
23pub trait LazyValueFn<V: Value>: Copy {
24    const LAZY_VALUE_FN: fn() -> &'static dyn Value = || {
25        let dyn_val: &'static dyn Value = Self::generate_value();
26        dyn_val
27    };
28
29    fn generate_value() -> &'static V;
30}
31
32/// Creates a temporary struct that implements [`LazyValueFn`] and returns an instance of it.
33///
34///
35macro_rules! lazy_value {
36    ($t: ty; $f: expr) => {{
37        // Note: We derive `Copy` on this type to avoid issues with `Drop` in const contexts.
38        #[derive(Copy, Clone)]
39        struct LazyFn(());
40
41        impl crate::session::vars::polyfill::LazyValueFn<$t> for LazyFn {
42            fn generate_value() -> &'static $t {
43                static MY_VALUE_LAZY: ::std::sync::LazyLock<$t> = LazyLock::new($f);
44                &*MY_VALUE_LAZY
45            }
46        }
47
48        LazyFn(())
49    }};
50}
51pub(crate) use lazy_value;
52
53/// Assigns the provided value to a `static`, and returns a reference to it.
54///
55/// Note: [`VarDefinition::new`] requires a `&'static V`, where `V: Value`. Ideally we would be
56/// able to pass the value as a const generic parameter, but Rust doesn't yet support this.
57///
58/// [`VarDefinition::new`]: crate::session::vars::VarDefinition::new
59macro_rules! value {
60    ($t: ty; $l: expr) => {{
61        static MY_STATIC: $t = $l;
62        &MY_STATIC
63    }};
64}
65pub(crate) use value;