Open
Description
Here's a sample program that uses a static HashMap of structs containing boxed values:
#[macro_use]
extern crate lazy_static;
use std::collections::HashMap;
use std::sync::Mutex;
use std::fmt::Display;
trait Value: Send + Display {
fn box_clone(&self) -> Box<dyn Value>;
}
impl Value for isize {
fn box_clone(&self) -> Box<dyn Value> {
Box::new((*self).clone())
}
}
impl Value for String {
fn box_clone(&self) -> Box<dyn Value> {
Box::new((*self).clone())
}
}
#[derive(Clone)]
struct S {
value: Box<dyn Value>
}
impl Clone for Box<dyn Value> {
fn clone(&self) -> Box<dyn Value> {
self.box_clone()
}
}
lazy_static! {
static ref Registry: Mutex<HashMap<String, S>> = {
Mutex::new(HashMap::new())
};
}
impl Registry {
fn get(&self, key: &str) -> Option<S> {
self.lock().unwrap().get(&String::from(key)).map(|s| s.clone())
}
fn set(&self, key: &str, value: S) -> Option<S> {
self.lock().unwrap().insert(String::from(key), value)
}
}
fn main() {
Registry.set("foo", S { value: Box::new(String::from("hello world")) });
Registry.set("bar", S { value: Box::new(123) });
println!("{}", Registry.get("foo").unwrap().value);
println!("{}", Registry.get("bar").unwrap().value);
}
It works as expected but when I replace redundant impl blocks with a generic one like this:
impl<T: 'static + Send + Clone + Display> Value for T {
fn box_clone(&self) -> Box<dyn Value> {
Box::new((*self).clone())
}
}
it fails with stack overflow in runtime:
thread 'main' has overflowed its stack
fatal runtime error: stack overflow
[1] 48231 abort cargo run
I'm new to Rust and not sure whether it's a bug. Maybe I just do something wrong. However I found the error strange because I don't explicitly do recursion or something else that potentially can lead to stack overflow here. Also it's weird that the compiler didn't find any problem because generics are compile-time concern.
By the way when I replace static variable with a local one it works fine even with the generic impl.
rustc 1.31.1 (b6c32da 2018-12-18), macOS 10.14.2