[Idea] About soundness in specialization

With all the above said, it might surprise some people that the nightly compiler (as of 2/3/2022) already appears to behave in the manner described above.

(quoted from here)

Not in a way that helps with soundness:

#![feature(specialization)]
#![allow(incomplete_features)]
#![allow(unused_variables)]

trait Is<T> {
    fn is(&self);
}

impl<A, B> Is<A> for B {
    default fn is(&self) {
        println!("no");
    }
}

impl<T> Is<T> for T {
    fn is(&self) {
        println!("yes");
    }
}

fn is_static_str<N: Is<&'static str>>(t: N) {
    t.is();
}

fn fully_generic_wrapper_function_without_trait_bound<N>(t: N) {
    is_static_str::<N>(t);
}

fn main() {
    let static_str: &'static str = "hey";

    let deallocated_at_end_of_main: String = "hello".to_string();
    let not_static_str: &'_ str = deallocated_at_end_of_main.as_str();

    is_static_str(static_str); // Ok, prints "yes"
    is_static_str(0u32); // Ok, prints "no"
    is_static_str(&0u32); // Ok, prints "no"
    // is_static_str(not_static_str); // Error, borrowed value does not live long enough

    fully_generic_wrapper_function_without_trait_bound(static_str); // yes
    fully_generic_wrapper_function_without_trait_bound(0u32); // no
    fully_generic_wrapper_function_without_trait_bound(&0u32); // no
    fully_generic_wrapper_function_without_trait_bound(not_static_str); // yes (no Error!)
}

And on a quick read of your proposal I don’t see how your rules can address the soundness problems from trait-bound-less wrapping functions, since the information about the specialized instances is completely lost/hidden to type-checking the call to such a wrapper function. The only (somewhat sane) sound approach I can come up with is to forbid a function like the fully_generic_wrapper_function_without_trait_bound above entirely.

2 Likes