Skip to content

Regression: implementing Clone for trait objects #61759

Closed
@ryzhyk

Description

@ryzhyk

The following code used to work with rustc 1.32 and earlier, but it crashes with stack overflow due to infinite recursion in 1.35

pub trait CBFn: Fn() {
   fn clone_boxed(&self) -> Box<dyn CBFn>;
}

impl<T> CBFn for T
where
   T: 'static + Clone + Fn()
{
   fn clone_boxed(&self) -> Box<dyn CBFn> {
       Box::new(T::clone(self))
   }
}

impl Clone for Box<dyn CBFn> {
   fn clone(&self) -> Self {
       self.clone_boxed()
   }
}

fn main() { 
    let f = || {};
    let b: Box<dyn CBFn> = Box::new(f);
    let bb = b.clone();
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
warning: unused variable: `bb`
  --> src/main.rs:23:9
   |
23 |     let bb = b.clone();
   |         ^^ help: consider prefixing with an underscore: `_bb`
   |
   = note: #[warn(unused_variables)] on by default

    Finished dev [unoptimized + debuginfo] target(s) in 0.81s
     Running `target/debug/playground`

thread 'main' has overflowed its stack
fatal runtime error: stack overflow
timeout: the monitored command dumped core
/root/entrypoint.sh: line 8:     8 Aborted                 timeout --signal=KILL ${timeout} "$@"

Update

It does work correctly with a slightly modified main using as_ref() to explicitly extract reference out of the box.

fn main() { 
    let f = || {};
    let b: Box<dyn CBFn> = Box::new(f);
    let bb = b.as_ref().clone();
}

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.P-highHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions