// Test evaluation order of operands of the compound assignment operators

// run-pass

use std::ops::AddAssign;

enum Side {
    Lhs,
    Rhs,
}

// In the following tests, we place our value into a wrapper type so that we
// can do an element access as the outer place expression. If we just had the
// block expression, it'd be a value expression and not compile.
struct Wrapper<T>(T);

// Evaluation order for `a op= b` where typeof(a) and typeof(b) are primitives
// is first `b` then `a`.
fn primitive_compound() {
    let mut side_order = vec![];
    let mut int = Wrapper(0);

    {
        side_order.push(Side::Lhs);
        int
    }.0 += {
        side_order.push(Side::Rhs);
        0
    };

    assert!(matches!(side_order[..], [Side::Rhs, Side::Lhs]));
}

// Evaluation order for `a op=b` otherwise is first `a` then `b`.
fn generic_compound<T: AddAssign<T> + Default>() {
    let mut side_order = vec![];
    let mut add_assignable: Wrapper<T> = Wrapper(Default::default());

    {
        side_order.push(Side::Lhs);
        add_assignable
    }.0 += {
        side_order.push(Side::Rhs);
        Default::default()
    };

    assert!(matches!(side_order[..], [Side::Lhs, Side::Rhs]));
}

fn custom_compound() {
    struct Custom;

    impl AddAssign<()> for Custom {
        fn add_assign(&mut self, _: ()) {
            // this block purposely left blank
        }
    }

    let mut side_order = vec![];
    let mut custom = Wrapper(Custom);

    {
        side_order.push(Side::Lhs);
        custom
    }.0 += {
        side_order.push(Side::Rhs);
    };

    assert!(matches!(side_order[..], [Side::Lhs, Side::Rhs]));
}

fn main() {
    primitive_compound();
    generic_compound::<i32>();
    custom_compound();
}
