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;