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

Miscompilation with recent Nightlies #66851

Closed
leonardo-m opened this issue Nov 28, 2019 · 4 comments · Fixed by #66870
Closed

Miscompilation with recent Nightlies #66851

leonardo-m opened this issue Nov 28, 2019 · 4 comments · Fixed by #66870
Assignees
Labels
C-bug Category: This is a bug. E-needs-bisection Call for participation: This issue needs bisection: https://github.com/rust-lang/cargo-bisect-rustc E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@leonardo-m
Copy link

leonardo-m commented Nov 28, 2019

Since few Rustc nightly versions I see a miscompilation problem with the code below.
I am using:

rustc 1.41.0-nightly (e87a205c2 2019-11-27)
binary: rustc
commit-hash: e87a205c2e117d9fb57f6cdeac0a7f6e95c88316
commit-date: 2019-11-27
host: x86_64-pc-windows-gnu
release: 1.41.0-nightly
LLVM version: 9.0

If I compile with:

-C opt-level=1 -Z mir-opt-level=1   ==> OK
-C opt-level=0 -Z mir-opt-level=2   ==> OK
-C opt-level=1 -Z mir-opt-level=2   ==> Runtime error

The code:

#[cfg(debug_assertions)]
use std::convert::TryFrom;

#[cfg(not(debug_assertions))]
macro_rules! to { ($e:expr, $t:ident) => (($e) as $t) }

#[cfg(debug_assertions)]
macro_rules! to { ($e:expr, $t:ident) => ($t::try_from($e).unwrap()) }

fn e103() -> Option<u64> {
    const TARGET: i32 = 7;
    const MAX_COST: i32 = 1 << 12;
    const MAX_COST_U: usize = MAX_COST as _;

    type TSubsets = [i32; 1 << TARGET];
    type TOccupancy = [bool; MAX_COST_U];
    type TMaxMin = [[i32; 2]; 16];

    enum SpecialsRes { Res(u64), Val(i32), Err }

    fn specials(len: i32,
                max_min: &mut TMaxMin,
                mut cost_ceiling: i32,
                vmax: i32,
                ix: i32,
                occupancy: &mut TOccupancy,
                subsets: &mut TSubsets) -> SpecialsRes {
        if ix == len || ix < 0 {
            let mut result = String::new();
            for i in (0 .. ix).rev() {
                result += &subsets[1 << i].to_string();
            }
            return if let Ok(r) = result.parse() {
                SpecialsRes::Res(r)
            } else {
                SpecialsRes::Err
            };
        }

        let mut lo_val: i32 = 0;
        let mut hi_val = vmax;

        for i in 0 .. ix {
            lo_val = lo_val.max(max_min[to!{i, usize} + 1][1] -
                                max_min[to!{i, usize} + 1][0]);
            hi_val = hi_val.min(max_min[to!{i, usize} + 2][0] -
                                max_min[to!{i, usize}][1]);
        }

        let r = len - ix;
        hi_val = hi_val.min(cost_ceiling - lo_val * r - r * (r + 1) / 2);

        let mut v = lo_val + (len - ix);
        while v < hi_val {
            let mut res = true;
            let pl = 1 << ix;
            let mut marked: i32 = 0;

            for i in 0 .. pl {
                let s = subsets[i] + v;
                if occupancy[to!{s, usize}] {
                    res = false;
                    break;
                }
                subsets[pl + i] = s;
                occupancy[to!{s, usize}] = true;
                marked += 1;
            }

            if res {
                let mut new_max_min: TMaxMin = Default::default();
                new_max_min[to!{ix, usize} + 2][0] = std::i32::MAX;

                for i in 1 .. ix + 2 {
                    new_max_min[to!{i, usize}][0] = max_min[to!{i, usize}][0]
                                                    .min(v + max_min[to!{i, usize} - 1][0]);
                    new_max_min[to!{i, usize}][1] = max_min[to!{i, usize}][1]
                                                    .max(v + max_min[to!{i, usize} - 1][1]);
                }

                let res = specials(len,
                                   &mut new_max_min,
                                   cost_ceiling - v,
                                   v,
                                   ix + 1,
                                   occupancy,
                                   subsets);
                match res {
                    SpecialsRes::Res(_) | SpecialsRes::Err => return res,

                    SpecialsRes::Val(val) => {
                        let new_cost_ceiling = v + val;
                        if new_cost_ceiling < cost_ceiling {
                            cost_ceiling = new_cost_ceiling;
                            hi_val = hi_val.min(cost_ceiling - lo_val * r - r * (r + 1) / 2);
                        }
                    }
                }
            }

            for i in 0 .. marked {
                occupancy[to!{subsets[pl + to!{i, usize}], usize}] = false;
            }

            v += 1;
        }

        SpecialsRes::Val(cost_ceiling)
    }

    let mut occupancy: TOccupancy = [false; MAX_COST_U];
    occupancy[0] = true;

    let mut subsets: TSubsets = [0i32; 1 << TARGET as usize];

    let mut max_min: TMaxMin = Default::default();
    max_min[1][0] = std::i32::MAX;

    match specials(TARGET, &mut max_min, MAX_COST,
                   MAX_COST, 0, &mut occupancy, &mut subsets) {
        SpecialsRes::Res(s) => Some(s),
        SpecialsRes::Val(_) | SpecialsRes::Err => None,
    }
}

fn main() {
    assert_eq!(e103(), Some(20_313_839_404_245));
}
@jonas-schievink jonas-schievink added C-bug Category: This is a bug. I-nominated I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. E-needs-bisection Call for participation: This issue needs bisection: https://github.com/rust-lang/cargo-bisect-rustc E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example labels Nov 28, 2019
@matthewjasper matthewjasper added requires-nightly This issue requires a nightly compiler in some way. and removed regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. labels Nov 28, 2019
@nagisa
Copy link
Member

nagisa commented Nov 28, 2019

NB: this is requires-nightly because it needs an unstable CLI flag to reproduce.

@Mark-Simulacrum
Copy link
Member

cc @oli-obk @ecstatic-morse since this might have something to do with recent const-eval work (apologies if I left anyone out)

@basil-cow
Copy link
Contributor

basil-cow commented Nov 29, 2019

I've managed to minify it to

#[derive(Debug, PartialEq)]
enum MyOption {
    Some(u64),
    None,
}

fn main() {
    let res = if let Ok(r) = "1".parse() {
        MyOption::Some(r)
    } else {
        MyOption::None
    };

    assert_eq!(MyOption::Some(1), res);
}

@basil-cow
Copy link
Contributor

basil-cow commented Nov 29, 2019

Bisected it to this, most probably the same issue as this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. E-needs-bisection Call for participation: This issue needs bisection: https://github.com/rust-lang/cargo-bisect-rustc E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants