Call non-object-safe method from object-safe one

The following code:

trait Trait {
    fn foo()
    where
        Self: Sized,
    {
    }

    fn bar(&self) {
        Self::foo();
    }
}

Fails with:

error[E0277]: the size for values of type `Self` cannot be known at compilation time
 --> src/lib.rs:9:9
  |
9 |         Self::foo();
  |         ^^^^^^^^^ doesn't have a size known at compile-time
  |
note: required by a bound in `Trait::foo`
 --> src/lib.rs:4:15
  |
2 |     fn foo()
  |        --- required by a bound in this
3 |     where
4 |         Self: Sized,
  |               ^^^^^ required by this bound in `Trait::foo`
help: consider further restricting `Self`
  |
8 |     fn bar(&self) where Self: Sized {
  |                   +++++++++++++++++

Is there a specific reason we don't allow calling a non-object-safe method from within an object-safe one within the trait? I think it should be possible; we will always know the concrete type within the implementation of the trait. Do I miss something?

If you remove the following the snippet compiles.

(a) And makes Trait non object safe. (b) This was not the question.

This doesn't seem related to object safety to me. foo has a trait bound that bar doesn't, the same error will occur no matter what the trait is.

trait Trait {
    fn foo()
    where
        Self: Clone,
    {
    }

    fn bar(&self) {
        Self::foo();
    }
}
error[E0277]: the trait bound `Self: Clone` is not satisfied
 --> src/lib.rs:9:9
  |
9 |         Self::foo();
  |         ^^^^^^^^^ the trait `Clone` is not implemented for `Self`
  |
note: required by a bound in `Trait::foo`
 --> src/lib.rs:4:15
  |
2 |     fn foo()
  |        --- required by a bound in this
3 |     where
4 |         Self: Clone,
  |               ^^^^^ required by this bound in `Trait::foo`
help: consider further restricting `Self`
  |
8 |     fn bar(&self) where Self: Clone {
  |                   +++++++++++++++++

Sure, but there there is a reason. where Self: Sized is already special, so if this could work why not?

It can't work because you can write

impl Trait for str {}

in which case, what's the default implementation of <str as Trait>::bar going to call? <str as Trait>::foo doesn't exist.

I think you want something like trait NotDyn with Sized: NotDyn, but sadly, for now we have the hack of relying on Sized to mean NotDyn.

You can work around parts of it in unsatisfying ways.

4 Likes