associated_type_defaults are unsound in the new solver · Issue #46 · rust-lang/trait-system-refactor-initiative (original) (raw)

rust-lang/rust#110673 attempted to make alias bounds sound in the new solver by only assembling alias bounds for a projection (such as <A as B>::C) when the trait that the projection comes from (<A as B>) can be satisfied via a param-env candidate.

This is problematic when checking whether an associated type default is well-formed, because we assume within the trait that Self: Trait<..> holds.

// compile-flags: -Ztrait-solver=next #![feature(associated_type_defaults)]

trait Tr { type Ty: Copy = String;

fn clone(x: &Self::Ty) -> Self::Ty {
    *x
}

}

impl Tr for () {}

fn main() { let x = String::from("hello, world"); let y = <() as Tr>::clone(&x); drop(x); println!("{y}"); // ^^ }

During check_type_bounds in the above program, we must prove:

[
    Obligation(predicate=Binder { value: TraitPredicate(<<Self as Tr>::Ty as std:📑:Sized>, polarity:Positive), bound_vars: [] }, depth=0),
    Obligation(predicate=Binder { value: TraitPredicate(<<Self as Tr>::Ty as std:📑:Copy>, polarity:Positive), bound_vars: [] }, depth=0),
]

given the caller bounds of:

[
    Binder { value: TraitPredicate(<Self as Tr>, polarity:Positive), bound_vars: [] },
]

Which means that the check implemented in EvalCtxt::validate_alias_bound_self_from_param_env succeeds.