macros: simpler expansion for intern!
This commit is contained in:
parent
2769963536
commit
261c0c5f56
|
@ -1,5 +1,5 @@
|
||||||
//! A write-once cell mediated by the Python GIL.
|
//! A write-once cell mediated by the Python GIL.
|
||||||
use crate::Python;
|
use crate::{types::PyString, Py, Python};
|
||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
|
|
||||||
/// A write-once cell similar to [`once_cell::OnceCell`](https://docs.rs/once_cell/1.4.0/once_cell/).
|
/// A write-once cell similar to [`once_cell::OnceCell`](https://docs.rs/once_cell/1.4.0/once_cell/).
|
||||||
|
@ -151,24 +151,28 @@ impl<T> GILOnceCell<T> {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! intern {
|
macro_rules! intern {
|
||||||
($py: expr, $text: expr) => {{
|
($py: expr, $text: expr) => {{
|
||||||
fn isolate_from_dyn_env(py: $crate::Python<'_>) -> &$crate::types::PyString {
|
static INTERNED: $crate::once_cell::Interned = $crate::once_cell::Interned::new($text);
|
||||||
static INTERNED: $crate::once_cell::GILOnceCell<$crate::Py<$crate::types::PyString>> =
|
INTERNED.get($py)
|
||||||
$crate::once_cell::GILOnceCell::new();
|
|
||||||
|
|
||||||
INTERNED
|
|
||||||
.get_or_init(py, || {
|
|
||||||
$crate::conversion::IntoPy::into_py(
|
|
||||||
$crate::types::PyString::intern(py, $text),
|
|
||||||
py,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.as_ref(py)
|
|
||||||
}
|
|
||||||
|
|
||||||
isolate_from_dyn_env($py)
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Implementation detail for `intern!` macro.
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub struct Interned(&'static str, GILOnceCell<Py<PyString>>);
|
||||||
|
|
||||||
|
impl Interned {
|
||||||
|
pub const fn new(value: &'static str) -> Self {
|
||||||
|
Interned(value, GILOnceCell::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn get<'py>(&'py self, py: Python<'py>) -> &'py PyString {
|
||||||
|
self.1
|
||||||
|
.get_or_init(py, || PyString::intern(py, self.0).into())
|
||||||
|
.as_ref(py)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -94,6 +94,7 @@ fn _test_compile_errors() {
|
||||||
|
|
||||||
#[rustversion::since(1.60)]
|
#[rustversion::since(1.60)]
|
||||||
fn tests_rust_1_60(t: &trybuild::TestCases) {
|
fn tests_rust_1_60(t: &trybuild::TestCases) {
|
||||||
|
t.compile_fail("tests/ui/invalid_intern_arg.rs");
|
||||||
t.compile_fail("tests/ui/invalid_immutable_pyclass_borrow.rs");
|
t.compile_fail("tests/ui/invalid_immutable_pyclass_borrow.rs");
|
||||||
t.compile_fail("tests/ui/invalid_pymethod_receiver.rs");
|
t.compile_fail("tests/ui/invalid_pymethod_receiver.rs");
|
||||||
t.compile_fail("tests/ui/missing_intopy.rs");
|
t.compile_fail("tests/ui/missing_intopy.rs");
|
||||||
|
|
6
tests/ui/invalid_intern_arg.rs
Normal file
6
tests/ui/invalid_intern_arg.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
use pyo3::Python;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let foo = if true { "foo" } else { "bar" };
|
||||||
|
Python::with_gil(|py| py.import(pyo3::intern!(py, foo)).unwrap());
|
||||||
|
}
|
8
tests/ui/invalid_intern_arg.stderr
Normal file
8
tests/ui/invalid_intern_arg.stderr
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
error[E0435]: attempt to use a non-constant value in a constant
|
||||||
|
--> tests/ui/invalid_intern_arg.rs:5:55
|
||||||
|
|
|
||||||
|
5 | Python::with_gil(|py| py.import(pyo3::intern!(py, foo)).unwrap());
|
||||||
|
| ------------------^^^-
|
||||||
|
| | |
|
||||||
|
| | non-constant value
|
||||||
|
| help: consider using `let` instead of `static`: `let INTERNED`
|
Loading…
Reference in a new issue