Skip to content

fn match_fresh_trait_refs removal #56

Open
@lcnr

Description

@lcnr

The old solver eagerly detects unbounded recursion and forces the affected goals to be ambiguous. This check forces some goals which would not recurse to ambiguity as well. These goals now correctly result in NoSolution.

https://github.com/rust-lang/rust/blob/b14fd2359f47fb9a14bbfe55359db4bb3af11861/compiler/rustc_trait_selection/src/traits/select/mod.rs#L1172-L1211.

This test fails with ambiguity with old solver due to multiple candidates, and successfully compiles with new:

trait Trait<T, DUMMY> {}
struct W<T>(T);
// To pass coherence.
trait IsNotI32 {}

// This impl does not hold but gets forced as ambiguous due to
// `fn match_fresh_trait_refs`.
impl<T, DUMMY> Trait<T, DUMMY> for W<T>
where
    DUMMY: IsNotI32,
    W<u32>: Trait<i32, DUMMY> {}

// This impl holds.
impl Trait<u32, i32> for W<u32> {}
    

fn impls_trait<T: Trait<U, DUMMY>, U, DUMMY>() {}

fn main() {
    impls_trait::<W<_>, _, _>()
}

Removing this check does worsen performance by not as eagerly detecting overflow. However, correctly tracking the stack dependent behavior for this check would probably have a far greater performance impact.


This check prevents typenum from reaching the recursion limit in the old solver, cc #56

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions