Skip to content
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

Overflow evaluating requirement in latest nightly (1.85) #135143

Closed
Azorlogh opened this issue Jan 6, 2025 · 4 comments · Fixed by #135149
Closed

Overflow evaluating requirement in latest nightly (1.85) #135143

Azorlogh opened this issue Jan 6, 2025 · 4 comments · Fixed by #135149
Assignees
Labels
A-trait-system Area: Trait system C-bug Category: This is a bug. regression-from-stable-to-nightly Performance or correctness regression from stable to nightly.

Comments

@Azorlogh
Copy link

Azorlogh commented Jan 6, 2025

This code fails to compile on the latest nightly (1.85):

Playground link: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=c912d455ab2679f04d8b3e8dedf694dc

pub struct Vec2;

pub trait Point {
    type S: Scalar;
}
impl Point for Vec2 {
    type S = f32;
}

pub trait Point2: Point<S = Self::S2> {
    type S2: Scalar;
}
impl Point2 for Vec2 {
    type S2 = Self::S;
}

pub trait Scalar: Default {}
impl Scalar for f32 {}

pub struct Bar<T: Default>(pub Vec<T>);
pub struct Foo<P: Point>(pub Vec<P>);

impl<P: Point2> From<Foo<P>> for Bar<P::S> {
    fn from(r: Foo<P>) -> Self {
        Self(r.0.iter().map(|_| Default::default()).collect())
    }
}

pub trait DoThing {
    fn do_thing();
}
impl DoThing for Foo<Vec2> {
    fn do_thing() {
        let _ = Bar::from(Foo::<Vec2>(vec![]));
    }
}

I expected to see this happen: It compiles without any errors

Instead, this happened: On nightly, it fails to compile with

error[E0275]: overflow evaluating the requirement `<Vec2 as Point>::S == _`

On stable (1.83.0) and beta (1.84.0-beta.6), it compiles just fine.

I encountered this bug while compiling this library, and then reduced the code until I got the example above: https://github.com/MetabuildDev/selo

Meta

rustc --version --verbose:

rustc 1.85.0-nightly (14ee63a3c 2024-12-29)
binary: rustc
commit-hash: 14ee63a3c651bb7a243c8b07333749ab4b152e13
commit-date: 2024-12-29
host: x86_64-unknown-linux-gnu
release: 1.85.0-nightly
LLVM version: 19.1.6
@Azorlogh Azorlogh added the C-bug Category: This is a bug. label Jan 6, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jan 6, 2025
@theemathas
Copy link
Contributor

theemathas commented Jan 6, 2025

My attempt at "simplifying" the reproducer code (requires an unstable feature):

#![feature(trusted_len)]

pub struct Vec2;

pub trait Point {
    type S;
}
impl Point for Vec2 {
    type S = f32;
}

pub trait Point2: Point<S = Self::S2> {
    type S2;
}
impl Point2 for Vec2 {
    type S2 = Self::S;
}

////////////////////

pub struct RepeatWith<F>(F);

impl<A, F: FnMut() -> A> Iterator for RepeatWith<F> {
    type Item = A;
    fn next(&mut self) -> Option<A> {
        None
    }
}

unsafe impl<A, F: FnMut() -> A> std::iter::TrustedLen for RepeatWith<F> {}

////////////////////

trait MyFrom<T> {
    fn my_from();
}
impl<P: Point2> MyFrom<P::S> for P {
    fn my_from() {
        _ = RepeatWith(|| unimplemented!()).collect::<Vec<P::S>>();
    }
}

pub fn do_thing() {
    <Vec2 as MyFrom<_>>::my_from();
}

Playground link

Note that removing the TrustedLen impl makes the code compile on nightly, which implies that the issue is probably related to specialization.

Replacing RepeatWith with a call to std::iter::repeat_with makes the code compile on stable while still erroring on nightly. Playground link

@rustbot labels +regression-from-stable-to-nightly +A-trait-system +A-specialization

@rustbot rustbot added A-specialization Area: Trait impl specialization A-trait-system Area: Trait system regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Jan 6, 2025
@compiler-errors
Copy link
Member

This seems to have regressed in #134081.

@compiler-errors
Copy link
Member

Anyways I have a fix but I'll need to minimize this futher. I don't believe this relies on specialization.

@rustbot claim

@compiler-errors
Copy link
Member

Overflows on nightly with no specialization:

pub struct Vec2;

pub trait Point {
    type S;
}
impl Point for Vec2 {
    type S = f32;
}

pub trait Point2: Point<S = Self::S2> {
    type S2;
}
impl Point2 for Vec2 {
    type S2 = Self::S;
}

trait MyFrom<T> {
    fn my_from();
}
impl<P: Point2> MyFrom<P::S> for P {
    fn my_from() {
        // This is just a really dumb way to force the legacy symbol mangling to
        // mangle the closure's parent impl def path *with* args. Otherwise,
        // legacy symbol mangling will strip the args from the instance, meaning
        // that we don't trigger the bug.
        let c = || {};
        let x = Box::new(c) as Box<dyn Fn()>;
    }
}

fn main() {
    <Vec2 as MyFrom<_>>::my_from();
}

@compiler-errors compiler-errors removed the A-specialization Area: Trait impl specialization label Jan 6, 2025
@apiraino apiraino removed the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Jan 6, 2025
@saethlin saethlin removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jan 7, 2025
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Jan 7, 2025
Use a post-monomorphization typing env when mangling components that come from impls

When mangling associated methods of impls, we were previously using the wrong param-env. Instead of using a fully monomorphized param-env like we usually do in codegen, we were taking the post-analysis param-env, and treating it as an early binder to *re-substitute* the impl args. I've pointed out the problematic old code in an inline comment.

This would give us param-envs with possibly trivial predicates that would prevent normalization via param-env shadowing.

In the example test linked below, `tests/ui/symbol-names/normalize-in-param-env.rs`, this happens when we mangle the impl `impl<P: Point2> MyFrom<P::S> for P` with the substitution `P = Vec2`. Because the where clause of the impl is `P: Point2`, which elaborates to `[P: Point2, P: Point, <P as Point>::S projects-to <P as Point2>::S2]` and the fact that `impl Point2 for Vec2` normalizes `Vec2::S2` to `Vec2::S`, this causes a cycle.

The proper fix here is to use a fully monomorphized param-env for the case where the impl is properly substituted.

Fixes rust-lang#135143

While rust-lang#134081 uncovered this bug for legacy symbol mangling, it was preexisting for v0 symbol mangling. This PR fixes both. The test requires a "hack" because we strip the args of the instance we're printing for legacy symbol mangling except for drop glue, so we box a closure to ensure we generate drop glue.

r? oli-obk
@bors bors closed this as completed in 3e12d4d Jan 8, 2025
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Jan 8, 2025
Rollup merge of rust-lang#135149 - compiler-errors:mangle, r=oli-obk

Use a post-monomorphization typing env when mangling components that come from impls

When mangling associated methods of impls, we were previously using the wrong param-env. Instead of using a fully monomorphized param-env like we usually do in codegen, we were taking the post-analysis param-env, and treating it as an early binder to *re-substitute* the impl args. I've pointed out the problematic old code in an inline comment.

This would give us param-envs with possibly trivial predicates that would prevent normalization via param-env shadowing.

In the example test linked below, `tests/ui/symbol-names/normalize-in-param-env.rs`, this happens when we mangle the impl `impl<P: Point2> MyFrom<P::S> for P` with the substitution `P = Vec2`. Because the where clause of the impl is `P: Point2`, which elaborates to `[P: Point2, P: Point, <P as Point>::S projects-to <P as Point2>::S2]` and the fact that `impl Point2 for Vec2` normalizes `Vec2::S2` to `Vec2::S`, this causes a cycle.

The proper fix here is to use a fully monomorphized param-env for the case where the impl is properly substituted.

Fixes rust-lang#135143

While rust-lang#134081 uncovered this bug for legacy symbol mangling, it was preexisting for v0 symbol mangling. This PR fixes both. The test requires a "hack" because we strip the args of the instance we're printing for legacy symbol mangling except for drop glue, so we box a closure to ensure we generate drop glue.

r? oli-obk
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-trait-system Area: Trait system C-bug Category: This is a bug. regression-from-stable-to-nightly Performance or correctness regression from stable to nightly.
Projects
None yet
6 participants