“obviously sound” min_specialization extension

Default function bodies for traits are obviously sound, and have been available (roughly) forever.

Providing a partial always applicable default impl of a supertrait based on a subtrait should be sound for the same reason, right? Is this indeed a well-defined sound subset of specialization?

A blanket impl with defaulted members is already min_specialization.

Example:

Full default:

#![feature(min_specialization)]

trait Spam {
    fn spam(count: f32);
}

trait SpamMore: Spam {
    fn spam_more(count: f64);
}

impl<T> Spam for T
where T: SpamMore,
{
    default fn spam(count: f32) {
        Self::spam_more(count as _);
    }
}

Partial default:

#![feature(specialization)]

trait Spam {
    fn spam(count: f32);
    
    fn unrelated();
}

trait SpamMore: Spam {
    fn spam_more(count: f64);
}

default impl<T> Spam for T
where T: SpamMore,
{
    default fn spam(count: f32) {
        Self::spam_more(count as _);
    }
}

Though I do suppose this unhelpful error is a problem:

struct A;

impl SpamMore for A {
    fn spam_more(_count: f64) {}
}

// no impl Spam for A
error[E0275]: overflow evaluating the requirement `A: Spam`
  --> src/lib.rs:23:6
   |
23 | impl SpamMore for A {
   |      ^^^^^^^^
   |
note: required by a bound in `SpamMore`
  --> src/lib.rs:9:17
   |
9  | trait SpamMore: Spam {
   |                 ^^^^ required by this bound in `SpamMore`

(It works fine with an impl Spam for A.)

I didn't say it was not incomplete_features, just “obviously sound.”

3 Likes