solver cycles are coinductive once they have one coinductive step by lcnr · Pull Request #136824 · rust-lang/rust (original) (raw)

Implements the new cycle semantics in the new solver, dealing with the fallout from rust-lang/trait-system-refactor-initiative#10.

The first commit has been extensively fuzzed via https://github.com/lcnr/search_graph_fuzz.

A trait solver cycle is now coinductive if it has at least one coinductive step. A step is only considered coinductive if it's a where-clause of an impl of a coinductive trait. The only coinductive traits are Sized and auto traits.

This differs from the current stable because where a cycle had to consist of exclusively coinductive goals. This is overly limiting and wasn't properly enforced as it (mostly) ignored all non-trait goals.

A more in-depth explanation of my reasoning can be found in this separate doc: https://gist.github.com/lcnr/c49d887bbd34f5d05c36d1cf7a1bf5a5. A summary:

we can therefore make any cycle during which we step into an auto trait (or Sized) impl coinductive


To fix rust-lang/trait-system-refactor-initiative#10 we could go with a more restrictive version which tries to restrict cycles to only allow code already supported on stable, potentially forcing cycles to be ambiguous if they step through an impl-where clause of a non-coinductive trait.

PathKind should be a strictly ordered set to allow merging paths without worry. We could therefore add another variant PathKind::ForceUnknown which is greater than PathKind::Coinductive. We already have to add such a third PathKind in #137314 anyways.

I am not doing this here due to multiple reasons:

r? @compiler-errors @nikomatsakis