Skip to content

Stack overflow on cloning static boxed value with a generic impl #57633

Open
@feymartynov

Description

@feymartynov

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintsArea: Lints (warnings about flaws in source code) such as unused_mut.C-enhancementCategory: An issue proposing an enhancement or a PR with one.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions