coherence incorrectly considers unnormalizable_projection: Trait to not hold even if it could (original) (raw)
// crate dep trait IsUnit {} impl IsUnit for () {}
pub trait WithAssoc<'a> { type Assoc; }
// The two impls of Trait overlap
pub trait Trait {}
impl Trait for T
where
T: 'static,
for<'a> T: WithAssoc<'a>,
for<'a> <T as WithAssoc<'a>>::Assoc: IsUnit,
{
}
impl Trait for Box {}
// root crate
use dep::*;
struct Local; impl WithAssoc<'_> for Box { type Assoc = (); }
fn impls_trait<T: Trait>() {}
fn main() { impls_trait::<Box>(); }
During coherence for<'a> <Box<T> as WithAssoc<'a>>::Assoc: IsUnit is considered to not hold.
This allows overlapping impls in coherence which is generally considered to be unsoundâ„¢.
Coherence considers the impls to be disjoint because for<'a> <Box<T> as WithAssoc<'a>>::Assoc: IsUnit, does not hold. When trying to normalize <Box<T> as WithAssoc<'a>>::Assoc ends up ambiguous, we keep the projection around. Coherence then considers for<'a> <Box<T> as WithAssoc<'a>>::Assoc: IsUnit to not have any impl as IsUnit is a local trait.