fn foo<T>() {
static mut x : * const T = std::ptr::null::<T>();
}
rustc complains "can't use type parameters from outer function; try using a local type parameter instead". I'm not seeing how to adapt the workarounds from --explain to this particular example. Anyone have a suggestion?
I don’t think there’s a quick workaround. What are you trying to do in the grand scheme of things? If I had to guess based on that snippet, it’s some sort of lazily initialized singleton?
Yeah, lazy allocated singleton. I know how to do the lazy allocated, but the code is kind of gross, so I wanted to templatize it and stick it in a library. Looks like I can do it w/ a macro, but I preferred non-macro since it's easier to read.
Yeah, this was a more narrow question, so I had hopes of a clever answer
The map approach was WILDLY different from what I was thinking, so that's good. Will have to think about.
statics aren’t all that great to work with in Rust (for good reason) so you may want to rethink the overall approach.
Yeah. I don't agree w/ the good reason, but it's what it's. I'm writing a framework (well, re-writing in Rust) for model checking file systems for errors. I don't want to go modify the checked file system code (it will often be someone else's code) to pass around the current callback state. It's easier to insert a couple call outs and get the state they need from a global. Ugly. But better than having to modify lots of other-people code before the tool can run (they won't like it, won't accept patches --- for good reason --- , etc).
Currently I'm just using a macro. For the real code I want a "temporary" singleton that lasts for the duration of a session so it looks a little different in that there's ways to setup/reset. It does leak storage afaik.
macro_rules! make_handle {
($name: ident, $type:tt) => {
mod $name {
use super::$type;
use std::cell::RefCell;
use std::rc::Rc;
use std::ptr::null;
type T = Rc<RefCell<$type>>;
fn internal_handle(t : *const T) -> T {
static mut singleton : *const T = null();
unsafe {
if t != null() {
singleton = t;
}
assert!(singleton != null());
(*singleton).clone()
}
}
pub fn set_handle(t : $type) -> T {
let x = Box::new(Rc::new(RefCell::new(t)));
internal_handle(Box::into_raw(x))
}
pub fn get_handle() -> T { internal_handle(null()) }
}
}
}
#[derive(Debug)]
pub struct Handle(usize);
make_handle!(statecheck,Handle);
fn main() {
let x = statecheck::set_handle(Handle { 0 : 0 });
x.borrow_mut().0 += 11;
let x = statecheck::get_handle();
x.borrow_mut().0 += 1;
let x = statecheck::get_handle();
x.borrow_mut().0 += 1;
println!("x={:?}", *x.borrow());
}
Note that the map approach could be simplified by using rust-typemap.
I can think of some… not recommended… alternatives:
#[link_section = ".data"]
fn dummy<T>(a: &&&&&&&&i32) -> i32 {
// The code for this should take up at least 8 bytes... probably...
********a
}
fn foo<T>() {
let ptr = dummy::<T> as *mut *const T;
println!("{:?}", ptr);
}
fn main() {
foo::<i32>();
foo::<i64>();
}
note that that won't do the right thing if the same specialization is instantiated from multiple crates. or possibly ever.