Skip to content

Rust is overflowing on recursive trait evaluation where it didn't before #34260

Open
@sgrif

Description

@sgrif

This can be simplified down to the following:

trait MyTrait {
    type Output;
}

impl<T: MyTrait> MyTrait for T {
    type Output = <T as MyTrait>::Output;
}

trait SomeOtherTrait {}

impl<T> SomeOtherTrait for T where T: MyTrait, T::Output: Send {}

fn main() {}

When compiling that program, rust will overflow when it did not on older versions.. Of course that example is contrived, and attempting to use any concrete type there will always overflow. It is simplified from the slightly more realistic example in https://is.gd/XSHLG2, which is simplified from the real world case where I encountered this, which was trying to pull https://github.com/diesel-rs/diesel/blob/f0a75bb/diesel/src/query_dsl/load_dsl.rs#L23-L29 into a separate trait.

The important distinction is that we're now overflowing in a generic context, in cases where there are some concrete types which are valid. Specifically this causes confusing differing behavior between where clauses on methods and where clauses on trait impls. The above code is fine if the where clause is instead on some trait method, as it's no longer evaluated until there's a concrete type that the method is being called on.

I'd actually think that rustc could always avoid overflow here, and instead detect that it's evaluating the same trait impl def for the same type and answer no. The code implies that was the intention. But that's aside the point, this is about a concrete change in behavior.

The issue was first introduced in nightly-2015-08-15. On nightlies prior to that, https://is.gd/vrEvFN would compile successfully. It manifested as an actual stack overflow until nightly-2015-10-29, where it became a proper error (hilariously giving a warning that this warning would become a hard error due to RFC 1214, when it was already hard erroring). I believe this was an unintentional side effect of implementing RFC 1214, as that was merged in on the nightly that introduced the issue.

Metadata

Metadata

Assignees

Labels

A-type-systemArea: Type systemC-bugCategory: This is a bug.P-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions