diff --git a/extendr-api/src/lib.rs b/extendr-api/src/lib.rs index 04f99650b1..eef61eb622 100644 --- a/extendr-api/src/lib.rs +++ b/extendr-api/src/lib.rs @@ -418,8 +418,10 @@ pub const NA_STRING: Option<&str> = None; pub const NA_LOGICAL: Rbool = Rbool::na_value(); thread_local! { - pub static R_FACTOR_STRING: once_cell::unsync::Lazy = once_cell::unsync::Lazy::new(||{ - "factor".into_robj() + #[allow(non_upper_case_globals)] + pub static R_FactorSymbol: once_cell::unsync::Lazy = once_cell::unsync::Lazy::new(||{ + let factor_c_string = CString::new("factor").unwrap(); + unsafe { libR_sys::Rf_install(factor_c_string.as_ptr()) } }); } diff --git a/extendr-macros/src/extendr_enum.rs b/extendr-macros/src/extendr_enum.rs index 6d2a4e5d21..caab64422b 100644 --- a/extendr-macros/src/extendr_enum.rs +++ b/extendr-macros/src/extendr_enum.rs @@ -110,9 +110,12 @@ pub(crate) fn extendr_enum(item_enum: syn::ItemEnum) -> proc_macro::TokenStream let strings_enum = once_cell::unsync::Lazy::force(strings_enum); libR_sys::Rf_setAttrib(robj.get(), libR_sys::R_LevelsSymbol, strings_enum.get()); }); - extendr_api::R_FACTOR_STRING.with(|factor_class| { + extendr_api::R_FactorSymbol.with(|factor_class| { let factor_class = once_cell::unsync::Lazy::force(factor_class); - libR_sys::Rf_setAttrib(robj.get(), libR_sys::R_ClassSymbol, factor_class.get()); + // a symbol is permanent, so no need to protect it + // printname is CHARSXP, and we need a STRSXP, hence `Rf_ScalarString` + // doesn't need protection, because it gets inserted into a protected `SEXP` immediately + libR_sys::Rf_setAttrib(robj.get(), libR_sys::R_ClassSymbol, libR_sys::Rf_ScalarString(libR_sys::PRINTNAME(*factor_class))); }); } Ok(robj)