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