Compiler insists that trait cannot be dynamically used

I forked the crate timeago and am struggling to use Box<dyn Language>, as the compiler reports E0038:

the trait Language cannot be made into an object Language cannot be made into an object

I'm trying to modify the Language trait so that it implements Clone:

#[allow(missing_docs)]
pub trait Language : Clone {
    // ...
}

I removed the following implementation, but the IDE extension is persisting with the above error:

#[cfg_attr(rustfmt, rustfmt_skip)]
impl<L:Language+?Sized> Language for Box<L> {
    fn too_low(&self) -> &'static str   { (**self).too_low() }
    fn too_high(&self) -> &'static str  { (**self).too_high() }
    fn ago(&self) -> &'static str       { (**self).ago() }
    fn place_ago_before(&self) -> bool  { (**self).place_ago_before() }
    fn get_word(&self, tu: TimeUnit, x: u64) -> &'static str  { 
        (**self).get_word(tu, x)
    }
}

At this point I just can't try fighting the IDE anymore.

Functions such as boxup or from_isolang explicitly use dyn Language. The generic Language for Box<L> implementation isn’t actually problematic if Language isn’t object safe anymore.

I’m not entirely sure if you’re trying to keep using dyn Language i.e. keep Language object safe or not. If you do want to keep object safety, then the : Clone supertrait is not an option. One possible alternative is to use something like the dyn_clone crate.

1 Like

Thanks, dyn_clone resolves the Box<dyn T> references. However, when I want to do dyn_clone::clone_box(l) I'm forced to add a 'static lifetime to l.

impl DynamicFormatter {
    pub fn with_language<'a>(l: &'a dyn Language) -> Self {
        Self {
            lang: dyn_clone::clone_box(l),
            // ...
        }
    }
}

Ah, it works if the parameter is a Box.

Issue possibly related to dyn_clone.

the parameter type L may not live long enough
...so that the type L will meet its required lifetime bounds

What I'm trying to do is wrap a DynamicFormatter from Formatter. The timeago crate Formatter structure is parameterized with a Language, so for my needs I need a version of this structure that is not parameterized (constructed with a runtime Language).

The error above is on following code (timeago fork):

impl<L: Language> Formatter<L> {
    /// Constructor for some default formatting with specified language instance
    ///
    /// It emits one item (chunk), limits to seconds and has no maximum duration.
    pub fn with_language(l: L) -> Self {
        Formatter {
            lang: dyn_clone::clone(&l),
            _subformatter: DynamicFormatter::with_language(dyn_clone::clone_box(&l)),
        }
    }

(Error is on _subformatter field's value).

I'd like to not break compatibility with this timeago fork. Appreciate further help!

The type Box<dyn Language>, or more explicitly and equivalently Box<dyn Language + 'static>, can only be created from a type Box<L> if there is a L: 'static bound.

I think the easiest way to fix your problem is to just add a where clause where L: 'static to pub fn with_language. This does create some limitation on the types that can be used for L (e. g. limiting the usability of reference types in place of L), but AFAICT this should not matter at all for the kinds of types that implement the Language trait.

    pub fn with_language(l: L) -> Self
    where
        L: 'static
    {
        Formatter {
            lang: dyn_clone::clone(&l),
            _subformatter: DynamicFormatter::with_language(dyn_clone::clone_box(&l)),
        }
    }
1 Like