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.

cc rust-lang/trait-system-refactor-initiative#52