-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
regression: overflow evaluating the requirement #128887
Comments
Alright, it would be very useful to get a minimization of the underlying pattern here. I think we likely want to accept this breakage 🤔 |
Outdated commentSomewhat minimized from the triangulate crate: Code (109 lines)use std::{convert::TryInto, marker::PhantomData};
struct PolygonElement<Index>(Index);
trait PolygonList<'p>: 'p {
type Vertex: 'p;
type Index: 'p;
type IntoItem: Into<PolygonElement<Self::Index>>;
type Iter<'i>: Iterator<Item = Self::IntoItem>
where
Self: 'i,
Self::Vertex: 'i,
'p: 'i;
fn iter_indices<'i>(&'i self) -> Self::Iter<'i>
where
Self: 'i,
Self::Vertex: 'i,
'p: 'i;
}
struct IndexWithIter<'i, Iter, OldIndex: Mappable<Old>, New: TryInto<Old>, Old: TryInto<New>> {
iter: Iter,
_phantom: PhantomData<&'i (OldIndex, New, Old)>,
}
impl<'i, Iter: Iterator + 'i, OldIndex: Mappable<Old>, New: TryInto<Old>, Old: TryInto<New>>
IndexWithIter<'i, Iter, OldIndex, New, Old>
where
Iter::Item: Into<PolygonElement<OldIndex>>,
OldIndex::Output<New>: Mappable<New, Output<Old> = OldIndex>,
{
fn new(iter: Iter) -> Self {
unimplemented!()
}
}
impl<'i, Iter: Iterator + 'i, OldIndex: Mappable<New>, In: TryInto<New>, New: TryInto<In>> Iterator
for IndexWithIter<'i, Iter, OldIndex, In, New>
{
type Item = PolygonElement<OldIndex::Output<In>>;
fn next(&mut self) -> Option<Self::Item> {
unimplemented!()
}
}
struct IndexWith<
'p,
P: PolygonList<'p, Index = OldIndex>,
OldIndex: Mappable<Old>,
Old: TryInto<New>,
New: TryInto<Old>,
>(P, PhantomData<&'p (OldIndex, Old, New)>)
where
OldIndex::Output<New>: Mappable<New, Output<Old> = OldIndex>;
impl<
'p,
P: PolygonList<'p, Index = OldIndex>,
OldIndex: Mappable<Old>,
New: TryInto<Old>,
Old: TryInto<New>,
> PolygonList<'p> for IndexWith<'p, P, OldIndex, Old, New>
where
OldIndex::Output<New>: Mappable<New, Output<Old> = OldIndex>,
{
type Vertex = P::Vertex;
type Index = OldIndex::Output<New>;
type IntoItem = PolygonElement<Self::Index>;
type Iter<'i> = IndexWithIter<'i, P::Iter<'i>, OldIndex, New, Old>
where Self: 'i, 'p: 'i;
fn iter_indices<'i>(&'i self) -> Self::Iter<'i>
where
Self: 'i,
Self::Vertex: 'i,
'p: 'i,
{
unimplemented!()
}
}
fn foo<
'p,
'i,
P: PolygonList<'p, Index = OldIndex>,
OldIndex: Mappable<Old>,
New: TryInto<Old>,
Old: TryInto<New>,
>(
x: IndexWith<'p, P, OldIndex, Old, New>,
) where
IndexWith<'p, P, OldIndex, Old, New>: 'i,
P::Vertex: 'i,
'p: 'i,
OldIndex::Output<New>: Mappable<New, Output<Old> = OldIndex>,
{
IndexWithIter::new(x.0.iter_indices());
}
pub trait Mappable<T> {
type Output<U>;
}
impl<T> Mappable<T> for T {
type Output<U> = U;
} |
WG-prioritization assigning priority (Zulip discussion). @rustbot label -I-prioritize +P-high
Depending on the result of the investigation, could #126128 end up in the release notes, correct? (just mentioning so we dont forget to label it as such) |
Minimized from the triangulate crate (I'm unable to make it any smaller): pub trait Mappable<T> {
type Output;
}
pub trait Mappable2<T> {
type Output;
}
// Deleting this impl makes it compile on beta
impl<T> Mappable2<T> for T {
type Output = i32;
}
pub trait Generic<M> {}
// Deleting the `: Mappable<T>` makes it error on stable.
pub struct IndexWithIter<I, M: Mappable<T>, T>(I, M, T);
// Changing the where clause to be an inline bound (`impl<I: Generic<M>, ....`) causes it to compile on beta
impl<I, M: Mappable<T, Output: Mappable2<T, Output = M>>, T> IndexWithIter<I, M, T>
where
I: Generic<M>,
{
fn new(_: I) {}
}
pub fn foo<M: Mappable<T, Output: Mappable2<T, Output = M>>, T>(x: impl Generic<M>) {
IndexWithIter::new(x);
} Compiles on stable. Gives the following error on beta:
|
I am unable to reproduce the issues with poke_search_cli or similari on my computer. |
slightly more readable for me 🤔 pub trait Mappable<T> {
type Output;
}
pub trait Mappable2<T> {
type Output;
}
// Deleting this impl makes it compile on beta
impl<T> Mappable2<T> for T {
type Output = i32;
}
pub trait Generic<M> {}
// Deleting the `: Mappable<T>` makes it error on stable.
pub struct IndexWithIter<I, M: Mappable<T>, T>(I, M, T);
// Changing the where clause to be an inline bound (`impl<I: Generic<M>, ....`) causes it to compile on beta
impl<I, M, T> IndexWithIter<I, M, T>
where
M: Mappable<T>,
M::Output: Mappable2<T, Output = M>,
I: Generic<M>,
{
fn new(x: I) {
IndexWithIter::<_, _, _>::new(x);
}
} this is somehow caused by the order in which we evaluate nested goals and also subtyping, but I don't fully understand why this is happening yet. |
yeah, I am also unable to reproduce the overflow in |
I have encountered an issue that may be related to this issue, report filed at: geoarrow/geoarrow-rs#716 The compile error that only occurs with nightly + release build, the code compiles for nightly + debug builds, and stable + release. the error message starts
Full message and attached file in the linked issue |
Outdated commentSomewhat minimized test case from geoarrow-rs (very bizarre): Command to reproduce (yes, you need to build it in release mode) cargo +nightly build --release Cargo.toml [package]
name = "geoarrow" # Renaming this package *sometimes* causes the code to compile
edition = "2021" src/lib.rs// Deleting this trait makes the code compile.
pub trait Irrelevant {}
pub struct GeometryCollection {}
pub trait GeometryCollectionTrait: Sized {
type T;
type ItemType: GeometryTrait<T = Self::T>;
fn geometries(&self) -> GeometryCollectionIterator<Self::T, Self::ItemType, Self> {
unimplemented!()
}
}
impl GeometryCollectionTrait for GeometryCollection {
type T = f64;
type ItemType = Geometry;
}
pub enum Geometry {}
pub trait GeometryTrait {
type T;
type GeometryCollection: GeometryCollectionTrait<T = Self::T>;
fn as_type(&self) -> Self::GeometryCollection {
unimplemented!()
}
}
impl<'a> GeometryTrait for Geometry {
type T = f64;
type GeometryCollection = GeometryCollection;
}
impl<'a> GeometryTrait for &'a Geometry {
type T = f64;
type GeometryCollection = GeometryCollection;
}
pub struct GeometryCollectionIterator<
T,
ItemType: GeometryTrait<T = T>,
G: GeometryCollectionTrait<T = T, ItemType = ItemType>,
> {
_geom: G,
}
impl<T, ItemType: GeometryTrait<T = T>, G: GeometryCollectionTrait<T = T, ItemType = ItemType>>
Iterator for GeometryCollectionIterator<T, ItemType, G>
{
type Item = ItemType;
fn next(&mut self) -> Option<Self::Item> {
unimplemented!()
}
}
fn geometry_eq<T>(left: &impl GeometryTrait<T = T>, right: &impl GeometryTrait<T = T>) {
let l = left.as_type();
let r = right.as_type();
geometry_collection_eq(&l, &r);
}
fn geometry_collection_eq<T>(
left: &impl GeometryCollectionTrait<T = T>,
right: &impl GeometryCollectionTrait<T = T>,
) {
let left_geometry = left.geometries().next().unwrap();
let right_geometry = right.geometries().next().unwrap();
geometry_eq(&left_geometry, &right_geometry);
}
impl Geometry {
// Renaming this function *sometimes* makes the code compile.
pub fn eq<G: GeometryTrait<T = f64>>(&self, other: &G) {
geometry_eq(self, other);
}
} Output of `rustc +nightly --version --verbose`
|
Without actually verifying it, I suspect that this is due to MIR inlining causing instantiations that overflow. MIR inlining depends on the crate hash/defpath hash, so is affected by changes to the crate name. |
Outdated commentSlightly minimized further than before. Same Cargo.toml. src/lib.rspub trait Irrelevant {}
pub struct IrrelevantFoo;
impl Foo for IrrelevantFoo {
type T = f64;
type BarType = IrrelevantBar;
}
pub struct IrrelevantBar;
impl<'a> Bar for IrrelevantBar {
type T = f64;
type FooType = IrrelevantFoo;
}
impl<'a> Bar for &'a IrrelevantBar {
type T = f64;
type FooType = IrrelevantFoo;
}
// Deleting the stuff above makes the code compile.
pub trait Foo {
type T;
type BarType: Bar<T = Self::T>;
}
pub trait Bar {
type T;
type FooType: Foo<T = Self::T>;
}
pub struct BarProducer<T, ItemType: Bar<T = T>> {
_dummy: ItemType,
}
trait Producer {
type Item;
fn produce(&mut self) -> Self::Item {
unimplemented!()
}
}
impl<T, ItemType: Bar<T = T>> Producer for BarProducer<T, ItemType> {
type Item = ItemType;
}
#[allow(unconditional_recursion)]
fn recurse<T, G: Bar<T = T>>() {
let mut producer: BarProducer<T, <G::FooType as Foo>::BarType> = conjure();
producer.produce();
recurse::<_, <G::FooType as Foo>::BarType>();
}
fn conjure<T>() -> T {
unimplemented!()
}
pub struct Something;
impl Something {
// Renaming this function *sometimes* makes the code compile.
pub fn eq<G: Bar<T = f64>>() {
recurse::<_, G>();
}
} |
Hi, thanks for looking into this. I tried your suggestion on the original crate, (actually the commit 46554582089404faca5da8dfdde6f871cb1378e2 from the geoarrow repo) as well as geoarrow v0.2.0 RUSTFLAGS="-Zinline-mir" cargo build --release However the same error occurs
rustc +nightly --version --verbose |
@apps4uco Your build command is incorrect. I can confirm that, on commit 2089a0189a16a8959605791fbbc2cc48113f1ccf (tag rust-v0.2.0), and also on my minimized test case, compiling with the following command compiles fine without an error: RUSTFLAGS='-Zinline-mir=no' cargo +nightly build --release While the following command produces an error: cargo +nightly build --release |
This version of the issue (minimized from geoarrow-rs) has now been fixed in #129714.Final minimized reproduction from the geoarrow-rs case. Commands that produce errors cargo +beta build --release
cargo +nightly build --release Commands that run successfully without errors: cargo +beta build
cargo +nightly build
RUSTFLAGS='-Zinline-mir=no' cargo +nightly build --release Cargo.toml [package]
name = "b" # Renaming this package *sometimes* causes the code to compile
edition = "2021" src/lib.rs pub trait Foo {
type Associated;
type Chain: Foo<Associated = Self::Associated>;
}
trait FooExt {
fn do_ext() {}
}
impl<T: Foo<Associated = f64>> FooExt for T {}
#[allow(unconditional_recursion)]
fn recurse<T: Foo<Associated = f64>>() {
T::do_ext();
recurse::<T::Chain>();
}
// Renaming this function *sometimes* makes the code compile.
pub fn lol<T: Foo<Associated = f64>>() {
recurse::<T>();
} Output of `rustc +nightly --version --verbose`
This seems... bad |
I should have stated that the global configuration I have is $ rustup default So it should be the same command as you had, or am I missing something? It seems like a very weird edge case that we have hit. What produced an error for me yesterday compiles fine today with the same command. Could that be related to the order cargo is compiling the crates? Thanks once again for looking into this. |
…r-errors Use a reduced recursion limit in the MIR inliner's cycle breaker This probably papers over rust-lang#128887, but primarily I'm opening this PR because multiple compiler people have thought about making this change which probably means it's a good idea. r? compiler-errors
Use a reduced recursion limit in the MIR inliner's cycle breaker This probably papers over rust-lang/rust#128887, but primarily I'm opening this PR because multiple compiler people have thought about making this change which probably means it's a good idea. r? compiler-errors
…ler-errors Add a test for trait solver overflow in MIR inliner cycle detection This test is a combination of the reproducer posted here: rust-lang#128887 (comment) and the existing test for polymorphic recursion: https://github.com/rust-lang/rust/blob/784d444733d65c3d305ce5edcbb41e3d0d0aee2e/tests/mir-opt/inline/polymorphic_recursion.rs r? `@compiler-errors`
…ler-errors Add a test for trait solver overflow in MIR inliner cycle detection This test is a combination of the reproducer posted here: rust-lang#128887 (comment) and the existing test for polymorphic recursion: https://github.com/rust-lang/rust/blob/784d444733d65c3d305ce5edcbb41e3d0d0aee2e/tests/mir-opt/inline/polymorphic_recursion.rs r? ``@compiler-errors``
…ler-errors Add a test for trait solver overflow in MIR inliner cycle detection This test is a combination of the reproducer posted here: rust-lang#128887 (comment) and the existing test for polymorphic recursion: https://github.com/rust-lang/rust/blob/784d444733d65c3d305ce5edcbb41e3d0d0aee2e/tests/mir-opt/inline/polymorphic_recursion.rs r? ```@compiler-errors```
Rollup merge of rust-lang#129757 - saethlin:half-a-recursion, r=compiler-errors Add a test for trait solver overflow in MIR inliner cycle detection This test is a combination of the reproducer posted here: rust-lang#128887 (comment) and the existing test for polymorphic recursion: https://github.com/rust-lang/rust/blob/784d444733d65c3d305ce5edcbb41e3d0d0aee2e/tests/mir-opt/inline/polymorphic_recursion.rs r? ```@compiler-errors```
Add a test for trait solver overflow in MIR inliner cycle detection This test is a combination of the reproducer posted here: rust-lang/rust#128887 (comment) and the existing test for polymorphic recursion: https://github.com/rust-lang/rust/blob/784d444733d65c3d305ce5edcbb41e3d0d0aee2e/tests/mir-opt/inline/polymorphic_recursion.rs r? ```@compiler-errors```
Current status: The issue from geoarrow-rs has been fixed in #129714. The issue from the triangulate crate is still unfixed, and might end up in stable rust version 1.81.0. Maybe this should go on the release notes? |
thinking through this: The change in #126128 changes the equate of the self type Where this previously equated the inference variables, resulting in Trying to prove We first constrain We then first prove the projection predicate which overflows and then the
|
this regression therefore doesn't need an associated type bound on |
so what's going on here is the following change from the old behavior:
to the new behavior
so, assuming that the fact that |
The reason that using #128887 (comment) trait Mappable<T> {
type Output;
}
pub trait Bound<T> {}
// Deleting this impl makes it compile on beta
impl<T> Bound<T> for T {}
trait Generic<M> {}
// Deleting the `: Mappable<T>` makes it error on stable.
pub struct IndexWithIter<I, M: Mappable<T>, T>(I, M, T);
impl<I, M, T> IndexWithIter<I, M, T>
where
<M as Mappable<T>>::Output: Bound<T>,
// flipping these where bounds causes this to succeed, even when removing
// the where-clause on the struct definition.
M: Mappable<T>,
I: Generic<M>,
{
fn new(x: I) {
IndexWithIter::<_, _, _>::new(x);
}
}
We could in theory fix this by reverting occurs check failures back to a hard error in case the projection does not reference bound variables or placeholders (as we should have eagerly replaced all such projections with inference variables), however, this feels subtle and not worth it imo. With this, I think we should not do anything here. I expect that #129073 will fix this again. THe underlying issue of fatal overflow introducing order dependence still persists however. cc @compiler-errors please test the minimization |
OK, I assume them we want to keep this issue open until merge of #129073 (else, LMK if it can be closed) |
Add a test for trait solver overflow in MIR inliner cycle detection This test is a combination of the reproducer posted here: rust-lang/rust#128887 (comment) and the existing test for polymorphic recursion: https://github.com/rust-lang/rust/blob/784d444733d65c3d305ce5edcbb41e3d0d0aee2e/tests/mir-opt/inline/polymorphic_recursion.rs r? ```@compiler-errors```
Downgrading priority to get it off my radar @rustbot label -P-high +P-medium |
My crate
Compiles fine:
Fails to compile:
FWIW it does compile with
|
I've split the latest geoarrow regression to a separate issue in #131960, to reduce confusion. |
Closes #716. Ref georust/geo#1255 (comment). Note that this is the same underlying implementation as upstream geo in <georust/geo#1255>. However, the trait-based implementation hits this compiler regression <rust-lang/rust#128887>, <rust-lang/rust#131960>, which prevents from compiling in release mode on a stable Rust version. For some reason, the **function-based implementation** does not hit this regression, and thus allows building geoarrow without using latest nightly and a custom `RUSTFLAGS`. Note that it's only `GeometryTrait` and `GeometryCollectionTrait` that hit this compiler bug. Other traits can use the upstream impls.
The text was updated successfully, but these errors were encountered: