blob: 586aea80ccef258b2891116bfc0c6a5da9f8095d [file] [log] [blame]
/*
REQUIRED_ARGS: -preview=rvaluerefparam
TEST_OUTPUT:
---
\ 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
---
RUN_OUTPUT:
---
Success
---
*/
import core.stdc.stdio;
template TypeTuple(T...){ alias T TypeTuple; }
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=2625
struct Pair {
immutable uint g1;
uint g2;
}
void test1() {
Pair[1] stuff;
static assert(!__traits(compiles, (stuff[0] = Pair(1, 2))));
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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);
}
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=3511
struct S4
{
private int _prop = 42;
ref int property() return { 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
{
return mX;
}
ref string y() return
{
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));
}
void test6()
{
int dtors;
struct S6
{
@disable this(this);
~this() { dtors++; }
}
S6[2] arr;
arr = S6();
assert(dtors == 2);
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=4424
void test4424()
{
static struct S
{
this(this) {}
void opAssign(T)(T rhs) if (!is(T == S)) {}
}
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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; }
do { return n; }
})));
static assert(!is(typeof({
int func1b(int n)
out(r){ r = 20; }
do{ return n; }
})));
struct DataX
{
int x;
}
static assert(!is(typeof({
DataX func2a(DataX n)
in{ n.x = 10; }
do { return n; }
})));
static assert(!is(typeof({
DataX func2b(DataX n)
in{}
out(r){ r.x = 20; }
do{ return n; }
})));
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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.
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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;
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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) {}
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=9140
immutable(int)[] bar9140()
out(result) {
foreach (ref r; result) {}
} do {
return null;
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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;
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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;
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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));
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=9658
struct S9658
{
private bool _isNull = true;
this(int v) const
{
_isNull = false; // cannot modify const expression this._isNull
}
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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));
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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[])));
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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");
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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;
}
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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);
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=12500
void test12500()
{
size_t foo;
++foo *= 1.5; // Rewrite to: (foo += 1) *= 1.5;
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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);
}
/***************************************************/
// https://issues.dlang.org/show_bug.cgi?id=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
{
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();
test6();
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;
}