import core.stdc.stdio;

template TypeTuple(T...){ alias T TypeTuple; }

/***************************************************/
// 2625

struct Pair {
    immutable uint g1;
    uint g2;
}

void test1() {
    Pair[1] stuff;
    static assert(!__traits(compiles, (stuff[0] = Pair(1, 2))));
}

/***************************************************/
// 5327

struct ID
{
    immutable int value;
}

struct Data
{
    ID id;
}
void test2()
{
    Data data = Data(ID(1));
    immutable int* val = &data.id.value;
    static assert(!__traits(compiles, data = Data(ID(2))));
}

/***************************************************/

struct S31A
{
    union
    {
        immutable int field1;
        immutable int field2;
    }

    enum result = false;
}
struct S31B
{
    union
    {
        immutable int field1;
        int field2;
    }

    enum result = true;
}
struct S31C
{
    union
    {
        int field1;
        immutable int field2;
    }

    enum result = true;
}
struct S31D
{
    union
    {
        int field1;
        int field2;
    }

    enum result = true;
}

struct S32A
{
    int dummy0;
    union
    {
        immutable int field1;
        int field2;
    }

    enum result = true;
}
struct S32B
{
    immutable int dummy0;
    union
    {
        immutable int field1;
        int field2;
    }

    enum result = false;
}


struct S32C
{
    union
    {
        immutable int field1;
        int field2;
    }
    int dummy1;

    enum result = true;
}
struct S32D
{
    union
    {
        immutable int field1;
        int field2;
    }
    immutable int dummy1;

    enum result = false;
}

void test3()
{
    foreach (S; TypeTuple!(S31A,S31B,S31C,S31D, S32A,S32B,S32C,S32D))
    {
        S s;
        static assert(__traits(compiles, s = s) == S.result);
    }
}

/***************************************************/
// 3511

struct S4
{
    private int _prop = 42;
    ref int property() { return _prop; }
}

void test4()
{
    S4 s;
    assert(s.property == 42);
    s.property = 23;    // Rewrite to s.property() = 23
    assert(s.property == 23);
}

/***************************************************/

struct S5
{
    int mX;
    string mY;

    ref int x()
    {
        return mX;
    }
    ref string y()
    {
        return mY;
    }

    ref int err(Object)
    {
        static int v;
        return v;
    }
}

void test5()
{
    S5 s;
    s.x += 4;
    assert(s.mX == 4);
    s.x -= 2;
    assert(s.mX == 2);
    s.x *= 4;
    assert(s.mX == 8);
    s.x /= 2;
    assert(s.mX == 4);
    s.x %= 3;
    assert(s.mX == 1);
    s.x <<= 3;
    assert(s.mX == 8);
    s.x >>= 1;
    assert(s.mX == 4);
    s.x >>>= 1;
    assert(s.mX == 2);
    s.x &= 0xF;
    assert(s.mX == 0x2);
    s.x |= 0x8;
    assert(s.mX == 0xA);
    s.x ^= 0xF;
    assert(s.mX == 0x5);

    s.x ^^= 2;
    assert(s.mX == 25);

    s.mY = "ABC";
    s.y ~= "def";
    assert(s.mY == "ABCdef");

    static assert(!__traits(compiles, s.err += 1));
}

/***************************************************/
// 4424

void test4424()
{
    static struct S
    {
        this(this) {}
        void opAssign(T)(T rhs) if (!is(T == S)) {}
    }
}

/***************************************************/
// 6174

struct CtorTest6174(Data)
{
    const Data data;

    const Data[2] sa1;
    const Data[2][1] sa2;
    const Data[][2] sa3;

    const Data[] da1;
    const Data[2][] da2;

    this(Data a)
    {
        auto pdata = &data;

        // If compiler can determine that an assignment really sets the fields
        // which belongs to `this` object, it can bypass const qualifier.
        // For example, sa3, da1, da2, and pdata have indirections.
        // As long as you don't try to rewrite values beyond the indirections,
        // an assignment will always be succeeded inside constructor.

        static assert( is(typeof( data        = a         )));    // OK
      static if (is(Data == struct))
      {
        static assert( is(typeof( data.x      = 1         )));    // OK
        static assert( is(typeof( data.y      = 2         )));    // OK
      }
        static assert(!is(typeof( *pdata      = a         )));    // NG
        static assert( is(typeof( *&data      = a         )));    // OK

        static assert( is(typeof( sa1         = [a,a]     )));    // OK
        static assert( is(typeof( sa1[0]      = a         )));    // OK
        static assert( is(typeof( sa1[]       = a         )));    // OK
        static assert( is(typeof( sa1[][]     = a         )));    // OK

        static assert( is(typeof( sa2         = [[a,a]]   )));    // OK
        static assert( is(typeof( sa2[0][0]   = a         )));    // OK
        static assert( is(typeof( sa2[][0][]  = a         )));    // OK
        static assert( is(typeof( sa2[0][][0] = a         )));    // OK

        static assert( is(typeof( sa3         = [[a],[]]  )));    // OK
        static assert( is(typeof( sa3[0]      = [a,a]     )));    // OK
        static assert(!is(typeof( sa3[0][0]   = a         )));    // NG
        static assert( is(typeof( sa3[]       = [a]       )));    // OK
        static assert( is(typeof( sa3[][0]    = [a]       )));    // OK
        static assert(!is(typeof( sa3[][0][0] = a         )));    // NG

        static assert( is(typeof( da1         = [a,a]     )));    // OK
        static assert(!is(typeof( da1[0]      = a         )));    // NG
        static assert(!is(typeof( da1[]       = a         )));    // NG

        static assert( is(typeof( da2         = [[a,a]]   )));    // OK
        static assert(!is(typeof( da2[0][0]   = a         )));    // NG
        static assert(!is(typeof( da2[]       = [a,a]     )));    // NG
        static assert(!is(typeof( da2[][0]    = a         )));    // NG
        static assert(!is(typeof( da2[0][]    = a         )));    // NG
    }
    void func(Data a)
    {
        auto pdata = &data;

        static assert(!is(typeof( data        = a         )));    // NG
      static if (is(Data == struct))
      {
        static assert(!is(typeof( data.x      = 1         )));    // NG
        static assert(!is(typeof( data.y      = 2         )));    // NG
      }
        static assert(!is(typeof( *pdata      = a         )));    // NG
        static assert(!is(typeof( *&data      = a         )));    // NG

        static assert(!is(typeof( sa1         = [a,a]     )));    // NG
        static assert(!is(typeof( sa1[0]      = a         )));    // NG
        static assert(!is(typeof( sa1[]       = a         )));    // NG
        static assert(!is(typeof( sa1[][]     = a         )));    // NG

        static assert(!is(typeof( sa2         = [[a,a]]   )));    // NG
        static assert(!is(typeof( sa2[0][0]   = a         )));    // NG
        static assert(!is(typeof( sa2[][0][]  = a         )));    // NG
        static assert(!is(typeof( sa2[0][][0] = a         )));    // NG

        static assert(!is(typeof( sa3         = [[a],[]]  )));    // NG
        static assert(!is(typeof( sa3[0]      = [a,a]     )));    // NG
        static assert(!is(typeof( sa3[0][0]   = a         )));    // NG
        static assert(!is(typeof( sa3[]       = [a]       )));    // NG
        static assert(!is(typeof( sa3[][0]    = [a]       )));    // NG
        static assert(!is(typeof( sa3[][0][0] = a         )));    // NG

        static assert(!is(typeof( da1         = [a,a]     )));    // NG
        static assert(!is(typeof( da1[0]      = a         )));    // NG
        static assert(!is(typeof( da1[]       = a         )));    // NG

        static assert(!is(typeof( da2         = [[a,a]]   )));    // NG
        static assert(!is(typeof( da2[0][0]   = a         )));    // NG
        static assert(!is(typeof( da2[]       = [a,a]     )));    // NG
        static assert(!is(typeof( da2[][0]    = a         )));    // NG
        static assert(!is(typeof( da2[0][]    = a         )));    // NG
    }
}

const char gc6174;
const char[1] ga6174;
static this()
{
    gc6174 = 'a';    // OK
    ga6174[0] = 'a'; // line 5, Err
}
struct Foo6174
{
    const char cc;
    const char[1] array;
    const char[1] arr;
    this(char c)
    {
        cc = c;       // OK
        array = [c];  // line 12, Err
        arr[0] = c;   // line 12, Err
    }
}
void test6174a()
{
    static struct Pair
    {
        const int x;
        int y;
    }
    alias CtorTest6174!long CtorTest1;
    alias CtorTest6174!Pair CtorTest2;

    auto foo = Foo6174('c');
}

/***************************************************/

template Select(bool cond, T, F)
{
    static if (cond)
        alias Select = T;
    else
        alias Select = F;
}

void test6174b()
{
    enum { none, unrelated, mutable, constant }

    static struct FieldStruct(bool c, int k)
    {
        enum fieldConst = c;
        enum assignKind = k;

        Select!(fieldConst, const int, int) x;
        int y;

        static if (assignKind == none)      {}
        static if (assignKind == unrelated) void opAssign(int) {}
        static if (assignKind == mutable)   void opAssign(FieldStruct) {}
        static if (assignKind == constant)  void opAssign(FieldStruct) const {}
    }
    static struct TestStruct(F, bool fieldConst)
    {
        int w;
        Select!(fieldConst, const F, F) f;
        Select!(fieldConst, const int, int) z;

        this(int)
        {
            // If F has an identity `opAssign`,it is used even for initializing.
            // Otherwise, initializing  will always succeed, by bypassing const qualifier.
            static assert(is(typeof( f = F() )) == (
                            F.assignKind == none ||
                            F.assignKind == unrelated ||
                            F.assignKind == mutable ||
                            F.assignKind == constant));

            static assert(is(typeof(   w = 1000 )) == true);
            static assert(is(typeof( f.x = 1000 )) == true);
            static assert(is(typeof( f.y = 1000 )) == true);
            static assert(is(typeof(   z = 1000 )) == true);
        }
        void func()
        {
            // In mutable member functions, identity assignment is allowed
            // when all of the fields are identity assignable,
            // or identity `opAssign`, which callable from mutable object, is defined.
            static assert(__traits(compiles, f = F()) == (
                            F.assignKind == none      && !fieldConst && !F.fieldConst ||
                            F.assignKind == unrelated && !fieldConst && !F.fieldConst ||
                            F.assignKind == constant ||
                            F.assignKind == mutable   && !fieldConst));

            static assert(__traits(compiles,   w = 1000) == true);
            static assert(__traits(compiles, f.x = 1000) == (!fieldConst && !F.fieldConst));
            static assert(__traits(compiles, f.y = 1000) == (!fieldConst && true         ));
            static assert(__traits(compiles,   z = 1000) == !fieldConst);
        }
        void func() const
        {
            // In non-mutable member functions, identity assignment is allowed
            // just only user-defined identity `opAssign` is qualified.
            static assert(__traits(compiles, f = F()) == (F.assignKind == constant));

            static assert(__traits(compiles,   w = 1000) == false);
            static assert(__traits(compiles, f.x = 1000) == false);
            static assert(__traits(compiles, f.y = 1000) == false);
            static assert(__traits(compiles,   z = 1000) == false);
        }
    }
    foreach (fieldConst; TypeTuple!(false, true))
    foreach (  hasConst; TypeTuple!(false, true))
    foreach (assignKind; TypeTuple!(none, unrelated, mutable, constant))
    {
        alias TestStruct!(FieldStruct!(hasConst, assignKind), fieldConst) TestX;
    }
}

void test6174c()
{
    static assert(!is(typeof({
        int func1a(int n)
        in{ n = 10; }
        body { return n; }
    })));
    static assert(!is(typeof({
        int func1b(int n)
        out(r){ r = 20; }
        body{ return n; }
    })));

    struct DataX
    {
        int x;
    }
    static assert(!is(typeof({
        DataX func2a(DataX n)
        in{ n.x = 10; }
        body { return n; }
    })));
    static assert(!is(typeof({
        DataX func2b(DataX n)
        in{}
        out(r){ r.x = 20; }
        body{ return n; }
    })));
}

/***************************************************/
// 6216

void test6216a()
{
    static class C{}

    static struct Xa{ int n; }
    static struct Xb{ int[] a; }
    static struct Xc{ C c; }
    static struct Xd{ void opAssign(typeof(this) rhs){} }
    static struct Xe{ void opAssign(T)(T rhs){} }
    static struct Xf{ void opAssign(int rhs){} }
    static struct Xg{ void opAssign(T)(T rhs)if(!is(T==typeof(this))){} }

    // has value type as member
    static struct S1 (X){ static if (!is(X==void)) X x; int n; }

    // has reference type as member
    static struct S2a(X){ static if (!is(X==void)) X x; int[] a; }
    static struct S2b(X){ static if (!is(X==void)) X x; C c; }

    // has identity opAssign
    static struct S3a(X){ static if (!is(X==void)) X x; void opAssign(typeof(this) rhs){} }
    static struct S3b(X){ static if (!is(X==void)) X x; void opAssign(T)(T rhs){} }

    // has non identity opAssign
    static struct S4a(X){ static if (!is(X==void)) X x; void opAssign(int rhs){} }
    static struct S4b(X){ static if (!is(X==void)) X x; void opAssign(T)(T rhs)if(!is(T==typeof(this))){} }

    enum result = [
        /*S1,   S2a,    S2b,    S3a,    S3b,    S4a,    S4b*/
/*- */  [true,  true,   true,   true,   true,   true,   true],
/*Xa*/  [true,  true,   true,   true,   true,   true,   true],
/*Xb*/  [true,  true,   true,   true,   true,   true,   true],
/*Xc*/  [true,  true,   true,   true,   true,   true,   true],
/*Xd*/  [true,  true,   true,   true,   true,   true,   true],
/*Xe*/  [true,  true,   true,   true,   true,   true,   true],
/*Xf*/  [true,  true,   true,   true,   true,   true,   true],
/*Xg*/  [true,  true,   true,   true,   true,   true,   true],
    ];

    pragma(msg, "\\\tS1\tS2a\tS2b\tS3a\tS3b\tS4a\tS4b");
    foreach (i, X; TypeTuple!(void,Xa,Xb,Xc,Xd,Xe,Xf,Xg))
    {
        S1!X  s1;
        S2a!X s2a;
        S2b!X s2b;
        S3a!X s3a;
        S3b!X s3b;
        S4a!X s4a;
        S4b!X s4b;

        pragma(msg,
                is(X==void) ? "-" : X.stringof,
                "\t", __traits(compiles, (s1  = s1)),
                "\t", __traits(compiles, (s2a = s2a)),
                "\t", __traits(compiles, (s2b = s2b)),
                "\t", __traits(compiles, (s3a = s3a)),
                "\t", __traits(compiles, (s3b = s3b)),
                "\t", __traits(compiles, (s4a = s4a)),
                "\t", __traits(compiles, (s4b = s4b))  );

        static assert(result[i] ==
            [   __traits(compiles, (s1  = s1)),
                __traits(compiles, (s2a = s2a)),
                __traits(compiles, (s2b = s2b)),
                __traits(compiles, (s3a = s3a)),
                __traits(compiles, (s3b = s3b)),
                __traits(compiles, (s4a = s4a)),
                __traits(compiles, (s4b = s4b))  ]);
    }
}

void test6216b()
{
    static int cnt = 0;

    static struct X
    {
        int n;
        void opAssign(X rhs){ cnt = 1; }
    }
    static struct S
    {
        int n;
        X x;
    }

    S s;
    s = s;
    assert(cnt == 1);
    // Built-in opAssign runs member's opAssign
}

void test6216c()
{
    static int cnt = 0;

    static struct X
    {
        int n;
        void opAssign(const X rhs) const { cnt = 2; }
    }
    static struct S
    {
        int n;
        const(X) x;
    }

    S s;
    const(S) cs;
    s = s;
    s = cs;     // cs is copied as mutable and assigned into s
    assert(cnt == 2);
    static assert(!__traits(compiles, cs = cs));
                // built-in opAssin is only allowed with mutable object
}

void test6216d()
{
    static int cnt = 0;

    static struct X
    {
        int[] arr;  // X has mutable indirection
        void opAssign(const X rhs) const { ++cnt; }
    }
    static struct S
    {
        int n;
        const(X) x;
    }

    X mx;
    const X cx;
    mx = mx;    // copying mx to const X is possible
    assert(cnt == 1);
    mx = cx;
    assert(cnt == 2);
    cx = mx;    // copying mx to const X is possible
    assert(cnt == 3);

    S s;
    const(S) cs;
    s = s;
    s = cs;
    //assert(cnt == 4);
    static assert(!__traits(compiles, cs = cs));
                // built-in opAssin is only allowed with mutable object
}

void test6216e()
{
    static struct X
    {
        int x;
        @disable void opAssign(X);
    }
    static struct S
    {
        X x;
    }
    S s;
    static assert(!__traits(compiles, s = s));
                // built-in generated opAssin is marked as @disable.
}

/***************************************************/
// 6286

void test6286()
{
    const(int)[4] src = [1, 2, 3, 4];
    int[4] dst;
    dst = src;
    dst[] = src[];
    dst = 4;
    int[4][4] x;
    x = dst;
}

/***************************************************/
// 6336

void test6336()
{
    // structs aren't identity assignable
    static struct S1
    {
        immutable int n;
    }
    static struct S2
    {
        void opAssign(int n){ assert(0); }
    }

    S1 s1;
    S2 s2;

    void f(S)(out S s){}
    static assert(!__traits(compiles, f(s1)));
    f(s2);
    // Out parameters refuse only S1 because it isn't blit assignable

    ref S g(S)(ref S s){ return s; }
    g(s1);
    g(s2);
    // Allow return by ref both S1 and S2
}

/***************************************************/
// 8783

struct Foo8783
{
    int[1] bar;
}

const Foo8783[1] foos8783;

static this()
{
    foreach (i; 0 .. foos8783.length)
        foos8783[i].bar[i] = 1; // OK
    foreach (i, ref f; foos8783)
        f.bar[i] = 1; // line 9, Error
}

/***************************************************/
// 9077

struct S9077a
{
    void opAssign(int n) {}
    void test() { typeof(this) s; s = this; }
    this(this) {}
}
struct S9077b
{
    void opAssign()(int n) {}
    void test() { typeof(this) s; s = this; }
    this(this) {}
}

/***************************************************/
// 9140

immutable(int)[] bar9140()
out(result) {
    foreach (ref r; result) {}
} body {
    return null;
}

/***************************************************/
// 9154

struct S9154a
{
    int x;
    void opAssign(ref S9154a s) { }
}
struct S9154b
{
    int x;
    void opAssign(X)(ref X s) { }
}
struct T9154
{
    S9154a member1;
    S9154b member2;
}

void test9154()
{
    T9154 t1, t2;
    t1 = t2;
}

/***************************************************/
// 9258

class A9258 {}
class B9258 : A9258 // Error: class test.B9258 identity assignment operator overload is illegal
{
    void opAssign(A9258 b) {}
}

class C9258
{
    int n;
    alias n this;
    void opAssign(int n) {}
}
class D9258
{
    int n;
    alias n this;
    void opAssign(int n, int y = 0) {}
}
class E9258 : A9258
{
    void set(A9258 a) {}
    alias set opAssign;
}

/***************************************************/
// 9416

struct S9416
{
    void opAssign()(S9416)
    {
        static assert(0);
    }
}
struct U9416
{
    S9416 s;
}
void test9416()
{
    U9416 u;
    static assert(__traits(allMembers, U9416)[$-1] == "opAssign");
    static assert(!__traits(compiles, u = u));
}

/***************************************************/
// 9658

struct S9658
{
    private bool _isNull = true;
    this(int v) const
    {
        _isNull = false;    // cannot modify const expression this._isNull
    }
}

/***************************************************/
// 11187

void test11187()
{
    static struct X
    {
        int[] arr;
    }
    static struct S
    {
        const(X) cx;
    }
    static assert(is(typeof((const S).init.cx.arr) == const(int[])));
    static assert(is(typeof((      S).init.cx.arr) == const(int[])));
    const S sc;
    S sm = sc;
    static assert(is(const S : S));
}

/***************************************************/
// 12131

struct X12131
{
    void opAssign()(X12131 y) pure {}
}

struct Y12131
{
    X12131 a;
}

void test12131() pure
{
    X12131 x;
    x = X12131();   // OK

    Y12131 y;
    y = Y12131();   // OK <- Error
}

/***************************************************/
// 12211

void test12211()
{
    int a = 0;
    void foo(ref int x)
    {
        assert(x == 10);
        assert(&x == &a);
        x = 3;
    }
    foo(a = 10);
    assert(a == 3);
    foo(a += 7);
    assert(a == 3);

    // array ops should make rvalue
    int[3] sa, sb;
    void bar(ref int[]) {}
    static assert(!__traits(compiles, bar(sa[]  = sb[])));
    static assert(!__traits(compiles, bar(sa[] += sb[])));
}

/***************************************************/
// 4791 (dup of 12212)

void test4791()
{
    int[2] na;
    na = na;

    static struct S
    {
        static string res;
        int n;
        this(this) { ++n; res ~= "p" ~ cast(char)('0' + n); }
        ~this()    {      res ~= "d" ~ cast(char)('0' + n); }
    }
    {
        S[3] sa;
        sa[0].n = 1, sa[1].n = 2, sa[2].n = 3;

        S.res = null;
        sa = sa;
        assert(S.res == "p2d1p3d2p4d3");
        assert(sa[0].n == 2 && sa[1].n == 3 && sa[2].n == 4);

        S.res = null;
    }
    assert(S.res == "d4d3d2");
}

/***************************************************/
// 12212

void test12212()
{
    struct S
    {
        int x, y;
        static int cpctor;
        this(this) { cpctor++; }
    }

    void funcVal(E)(E[3] x) {}
    auto funcRef(E)(ref E[3] x) { return &x; }
    ref get(E)(ref E[3] a){ return a; }

    {
        int[3] a, b;
        funcVal(a = b);

        auto p = funcRef(a = b);
        assert(p == &a);
    }

    {
        S.cpctor = 0;

        S[3] a, b;
        assert(S.cpctor == 0);

        S[3] c = a;
        //printf("cpctpr = %d\n", S.cpctor);
        assert(S.cpctor == 3);
        S.cpctor = 0;

        c = a;
        //printf("cpctpr = %d\n", S.cpctor);
        assert(S.cpctor == 3);
        S.cpctor = 0;

        c = (a = b);
        //printf("cpctpr = %d\n", S.cpctor);
        assert(S.cpctor == 6);
        S.cpctor = 0;

        c = (get(a) = b);
        //printf("cpctpr = %d\n", S.cpctor);
        assert(S.cpctor == 6);
        S.cpctor = 0;
    }
    {
        S.cpctor = 0;

        S[3] a, b;
        assert(S.cpctor == 0);

        funcVal(a = b);
        //printf("cpctpr = %d\n", S.cpctor);
        assert(S.cpctor == 6);
        S.cpctor = 0;

        funcVal(get(a) = b);
        //printf("cpctpr = %d\n", S.cpctor);
        assert(S.cpctor == 6);
        S.cpctor = 0;
    }
    {
        S.cpctor = 0;

        S[3] a, b;
        assert(S.cpctor == 0);

        S[3]* p;

        p = funcRef(a = b);
        //printf("cpctpr = %d\n", S.cpctor);
        assert(p == &a);
        assert(S.cpctor == 3);
        S.cpctor = 0;

        p = funcRef(get(a) = b);
        assert(p == &a);
        //printf("cpctpr = %d\n", S.cpctor);
        assert(S.cpctor == 3);
        S.cpctor = 0;
    }
}

/***************************************************/
// 12650

void test12650()
{
    // AssignExp::toElem should make an lvalue of e1.
    static class A1
    {
        struct S { int a; }

        static foo(ref const(S) s)
        {
            assert(s.a == 2);
            return &s;
        }

        S s;

        this()
        {
            const v = S(2);

            // (this.s = v) will become ConstructExp
            auto p = foo(s = v);
            assert(p == &s);
        }
    }
    assert(new A1().s.a == 2);

    static class A2
    {
        static foo(ref int[2] sa)
        {
            assert(sa[1] == 2);
            return &sa;
        }

        int[2] sa;

        this()
        {
            // (this.sa = [1,2]) will become ConstructExp
            auto p = foo(sa = [1,2]);
            assert(p == &sa);
        }
    }
    assert(new A2().sa[1] == 2);

    static class A3
    {
        static foo(ref int n)
        {
            assert(n == 2);
            return &n;
        }

        int n;

        this()
        {
            const v = 2;

            // (this.n = v) will become ConstructExp
            auto p = foo(n = v);
            assert(p == &n);
        }
    }
    assert(new A3().n == 2);
}

/***************************************************/
// 13044

void test13044()
{
    static struct Good
    {
        const int i;
    }

    static struct Bad
    {
        const int i;
        ~this() {}
    }

    Good good1, good2;
    static assert(!__traits(compiles, { good1 = good2; })); // OK

    Bad bad1, bad2;
    static assert(!__traits(compiles, { bad1 = bad2; }));   // OK <- fails
}

/***************************************************/
// 12500

void test12500()
{
    size_t foo;
    ++foo *= 1.5;   // Rewrite to: (foo += 1) *= 1.5;
}

/***************************************************/
// 14672

void test14672()
{
    interface I {}

    class B {}
    class D : B, I {}

    D d = new D();
    D[] da = [d];
    B[] ba = [null];
    I[] ia = [null];

    // ba and da points different payloads,
    // so element-wise assignment should work.
    ba[] = da[];    // OK <- e2ir ICE
    assert(ba[0] is d);

    // Today element-wise assignment is implemented as memcpy, For that reason
    // the conversion from derived classes to base interfaces is disallowed
    // because it requries offset adjustments.
    static assert(!__traits(compiles, { ia[] = da[]; }));

    // after the assignment, ba will wongly point the payload of da,
    // that's typed as D[]. To aboid type system breaking, it's disallowed.
    static assert(!__traits(compiles, { ba = da; }));

    // the assigned array literal is a new payload,
    // so rebinding ba should work.
    ba = [d];       // OK
    assert(ba[0] is d);
}

/***************************************************/
// 15044

void destroy15044(T)(ref T obj)
{
    static if (__traits(hasMember, T, "__xdtor"))
        obj.__xdtor();
    else
        static assert(0, T.stringof);
}

struct V15044
{
    ~this()
    {
    }

    RC15044!V15044 dup()
    {
        return RC15044!V15044(&this);
    }
}

struct RC15044(T)
{
    ~this()
    {
        destroy15044(*t);
        static assert(__traits(hasMember, T, "__xdtor"));
    }
    T* t;
}

/***************************************************/

int main()
{
    test1();
    test2();
    test3();
    test4();
    test5();
    test4424();
    test6174a();
    test6174b();
    test6174c();
    test6216a();
    test6216b();
    test6216c();
    test6216d();
    test6216e();
    test6286();
    test6336();
    test9154();
    test9416();
    test11187();
    test12131();
    test12211();
    test4791();
    test12212();
    test12650();
    test13044();
    test12500();
    test14672();

    printf("Success\n");
    return 0;
}
