summaryrefslogtreecommitdiffstats
path: root/tests/mir-opt/dataflow-const-prop/enum.rs
blob: 79a20d7ef457dc09058ed54f19e1ee67ffa2462d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// unit-test: DataflowConstProp

#![feature(custom_mir, core_intrinsics, rustc_attrs)]

use std::intrinsics::mir::*;

enum E {
    V1(i32),
    V2(i32)
}

// EMIT_MIR enum.simple.DataflowConstProp.diff
fn simple() {
    let e = E::V1(0);
    let x = match e { E::V1(x) => x, E::V2(x) => x };
}

#[rustc_layout_scalar_valid_range_start(1)]
#[rustc_nonnull_optimization_guaranteed]
struct NonZeroUsize(usize);

// EMIT_MIR enum.mutate_discriminant.DataflowConstProp.diff
#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
fn mutate_discriminant() -> u8 {
    mir!(
        let x: Option<NonZeroUsize>;
        {
            SetDiscriminant(x, 1);
            // This assignment overwrites the niche in which the discriminant is stored.
            place!(Field(Field(Variant(x, 1), 0), 0)) = 0_usize;
            // So we cannot know the value of this discriminant.
            let a = Discriminant(x);
            match a {
                0 => bb1,
                _ => bad,
            }
        }
        bb1 = {
            RET = 1;
            Return()
        }
        bad = {
            RET = 2;
            Unreachable()
        }
    )
}

// EMIT_MIR enum.multiple.DataflowConstProp.diff
fn multiple(x: bool, i: u8) {
    let e = if x {
        Some(i)
    } else {
        None
    };
    // The dataflow state must have:
    //   discriminant(e) => Top
    //   (e as Some).0 => Top
    let x = match e { Some(i) => i, None => 0 };
    // Therefore, `x` should be `Top` here, and no replacement shall happen.
    let y = x;
}

fn main() {
    simple();
    mutate_discriminant();
    multiple(false, 5);
}