]>
Commit | Line | Data |
---|---|---|
7da827c9 | 1 | /* |
5fee5ec3 | 2 | REQUIRED_ARGS: -preview=rvaluerefparam |
7da827c9 IB |
3 | TEST_OUTPUT: |
4 | --- | |
5 | \ S1 S2a S2b S3a S3b S4a S4b | |
6 | - true true true true true true true | |
7 | Xa true true true true true true true | |
8 | Xb true true true true true true true | |
9 | Xc true true true true true true true | |
10 | Xd true true true true true true true | |
11 | Xe true true true true true true true | |
12 | Xf true true true true true true true | |
13 | Xg true true true true true true true | |
14 | --- | |
15 | ||
16 | RUN_OUTPUT: | |
17 | --- | |
18 | Success | |
19 | --- | |
20 | */ | |
21 | ||
b4c522fa IB |
22 | import core.stdc.stdio; |
23 | ||
24 | template TypeTuple(T...){ alias T TypeTuple; } | |
25 | ||
26 | /***************************************************/ | |
5fee5ec3 | 27 | // https://issues.dlang.org/show_bug.cgi?id=2625 |
b4c522fa IB |
28 | |
29 | struct Pair { | |
30 | immutable uint g1; | |
31 | uint g2; | |
32 | } | |
33 | ||
34 | void test1() { | |
35 | Pair[1] stuff; | |
36 | static assert(!__traits(compiles, (stuff[0] = Pair(1, 2)))); | |
37 | } | |
38 | ||
39 | /***************************************************/ | |
5fee5ec3 | 40 | // https://issues.dlang.org/show_bug.cgi?id=5327 |
b4c522fa IB |
41 | |
42 | struct ID | |
43 | { | |
44 | immutable int value; | |
45 | } | |
46 | ||
47 | struct Data | |
48 | { | |
49 | ID id; | |
50 | } | |
51 | void test2() | |
52 | { | |
53 | Data data = Data(ID(1)); | |
54 | immutable int* val = &data.id.value; | |
55 | static assert(!__traits(compiles, data = Data(ID(2)))); | |
56 | } | |
57 | ||
58 | /***************************************************/ | |
59 | ||
60 | struct S31A | |
61 | { | |
62 | union | |
63 | { | |
64 | immutable int field1; | |
65 | immutable int field2; | |
66 | } | |
67 | ||
68 | enum result = false; | |
69 | } | |
70 | struct S31B | |
71 | { | |
72 | union | |
73 | { | |
74 | immutable int field1; | |
75 | int field2; | |
76 | } | |
77 | ||
78 | enum result = true; | |
79 | } | |
80 | struct S31C | |
81 | { | |
82 | union | |
83 | { | |
84 | int field1; | |
85 | immutable int field2; | |
86 | } | |
87 | ||
88 | enum result = true; | |
89 | } | |
90 | struct S31D | |
91 | { | |
92 | union | |
93 | { | |
94 | int field1; | |
95 | int field2; | |
96 | } | |
97 | ||
98 | enum result = true; | |
99 | } | |
100 | ||
101 | struct S32A | |
102 | { | |
103 | int dummy0; | |
104 | union | |
105 | { | |
106 | immutable int field1; | |
107 | int field2; | |
108 | } | |
109 | ||
110 | enum result = true; | |
111 | } | |
112 | struct S32B | |
113 | { | |
114 | immutable int dummy0; | |
115 | union | |
116 | { | |
117 | immutable int field1; | |
118 | int field2; | |
119 | } | |
120 | ||
121 | enum result = false; | |
122 | } | |
123 | ||
124 | ||
125 | struct S32C | |
126 | { | |
127 | union | |
128 | { | |
129 | immutable int field1; | |
130 | int field2; | |
131 | } | |
132 | int dummy1; | |
133 | ||
134 | enum result = true; | |
135 | } | |
136 | struct S32D | |
137 | { | |
138 | union | |
139 | { | |
140 | immutable int field1; | |
141 | int field2; | |
142 | } | |
143 | immutable int dummy1; | |
144 | ||
145 | enum result = false; | |
146 | } | |
147 | ||
148 | void test3() | |
149 | { | |
150 | foreach (S; TypeTuple!(S31A,S31B,S31C,S31D, S32A,S32B,S32C,S32D)) | |
151 | { | |
152 | S s; | |
153 | static assert(__traits(compiles, s = s) == S.result); | |
154 | } | |
155 | } | |
156 | ||
157 | /***************************************************/ | |
5fee5ec3 | 158 | // https://issues.dlang.org/show_bug.cgi?id=3511 |
b4c522fa IB |
159 | |
160 | struct S4 | |
161 | { | |
162 | private int _prop = 42; | |
5fee5ec3 | 163 | ref int property() return { return _prop; } |
b4c522fa IB |
164 | } |
165 | ||
166 | void test4() | |
167 | { | |
168 | S4 s; | |
169 | assert(s.property == 42); | |
170 | s.property = 23; // Rewrite to s.property() = 23 | |
171 | assert(s.property == 23); | |
172 | } | |
173 | ||
174 | /***************************************************/ | |
175 | ||
176 | struct S5 | |
177 | { | |
178 | int mX; | |
179 | string mY; | |
180 | ||
5fee5ec3 | 181 | ref int x() return |
b4c522fa IB |
182 | { |
183 | return mX; | |
184 | } | |
5fee5ec3 | 185 | ref string y() return |
b4c522fa IB |
186 | { |
187 | return mY; | |
188 | } | |
189 | ||
190 | ref int err(Object) | |
191 | { | |
192 | static int v; | |
193 | return v; | |
194 | } | |
195 | } | |
196 | ||
197 | void test5() | |
198 | { | |
199 | S5 s; | |
200 | s.x += 4; | |
201 | assert(s.mX == 4); | |
202 | s.x -= 2; | |
203 | assert(s.mX == 2); | |
204 | s.x *= 4; | |
205 | assert(s.mX == 8); | |
206 | s.x /= 2; | |
207 | assert(s.mX == 4); | |
208 | s.x %= 3; | |
209 | assert(s.mX == 1); | |
210 | s.x <<= 3; | |
211 | assert(s.mX == 8); | |
212 | s.x >>= 1; | |
213 | assert(s.mX == 4); | |
214 | s.x >>>= 1; | |
215 | assert(s.mX == 2); | |
216 | s.x &= 0xF; | |
217 | assert(s.mX == 0x2); | |
218 | s.x |= 0x8; | |
219 | assert(s.mX == 0xA); | |
220 | s.x ^= 0xF; | |
221 | assert(s.mX == 0x5); | |
222 | ||
223 | s.x ^^= 2; | |
224 | assert(s.mX == 25); | |
225 | ||
226 | s.mY = "ABC"; | |
227 | s.y ~= "def"; | |
228 | assert(s.mY == "ABCdef"); | |
229 | ||
230 | static assert(!__traits(compiles, s.err += 1)); | |
231 | } | |
232 | ||
c8dfa79c IB |
233 | void test6() |
234 | { | |
235 | int dtors; | |
236 | struct S6 | |
237 | { | |
238 | @disable this(this); | |
239 | ~this() { dtors++; } | |
240 | } | |
241 | ||
242 | S6[2] arr; | |
243 | arr = S6(); | |
244 | ||
245 | assert(dtors == 2); | |
246 | } | |
247 | ||
b4c522fa | 248 | /***************************************************/ |
5fee5ec3 | 249 | // https://issues.dlang.org/show_bug.cgi?id=4424 |
b4c522fa IB |
250 | |
251 | void test4424() | |
252 | { | |
253 | static struct S | |
254 | { | |
255 | this(this) {} | |
256 | void opAssign(T)(T rhs) if (!is(T == S)) {} | |
257 | } | |
258 | } | |
259 | ||
260 | /***************************************************/ | |
5fee5ec3 | 261 | // https://issues.dlang.org/show_bug.cgi?id=6174 |
b4c522fa IB |
262 | |
263 | struct CtorTest6174(Data) | |
264 | { | |
265 | const Data data; | |
266 | ||
267 | const Data[2] sa1; | |
268 | const Data[2][1] sa2; | |
269 | const Data[][2] sa3; | |
270 | ||
271 | const Data[] da1; | |
272 | const Data[2][] da2; | |
273 | ||
274 | this(Data a) | |
275 | { | |
276 | auto pdata = &data; | |
277 | ||
278 | // If compiler can determine that an assignment really sets the fields | |
279 | // which belongs to `this` object, it can bypass const qualifier. | |
280 | // For example, sa3, da1, da2, and pdata have indirections. | |
281 | // As long as you don't try to rewrite values beyond the indirections, | |
282 | // an assignment will always be succeeded inside constructor. | |
283 | ||
284 | static assert( is(typeof( data = a ))); // OK | |
285 | static if (is(Data == struct)) | |
286 | { | |
287 | static assert( is(typeof( data.x = 1 ))); // OK | |
288 | static assert( is(typeof( data.y = 2 ))); // OK | |
289 | } | |
290 | static assert(!is(typeof( *pdata = a ))); // NG | |
291 | static assert( is(typeof( *&data = a ))); // OK | |
292 | ||
293 | static assert( is(typeof( sa1 = [a,a] ))); // OK | |
294 | static assert( is(typeof( sa1[0] = a ))); // OK | |
295 | static assert( is(typeof( sa1[] = a ))); // OK | |
296 | static assert( is(typeof( sa1[][] = a ))); // OK | |
297 | ||
298 | static assert( is(typeof( sa2 = [[a,a]] ))); // OK | |
299 | static assert( is(typeof( sa2[0][0] = a ))); // OK | |
300 | static assert( is(typeof( sa2[][0][] = a ))); // OK | |
301 | static assert( is(typeof( sa2[0][][0] = a ))); // OK | |
302 | ||
303 | static assert( is(typeof( sa3 = [[a],[]] ))); // OK | |
304 | static assert( is(typeof( sa3[0] = [a,a] ))); // OK | |
305 | static assert(!is(typeof( sa3[0][0] = a ))); // NG | |
306 | static assert( is(typeof( sa3[] = [a] ))); // OK | |
307 | static assert( is(typeof( sa3[][0] = [a] ))); // OK | |
308 | static assert(!is(typeof( sa3[][0][0] = a ))); // NG | |
309 | ||
310 | static assert( is(typeof( da1 = [a,a] ))); // OK | |
311 | static assert(!is(typeof( da1[0] = a ))); // NG | |
312 | static assert(!is(typeof( da1[] = a ))); // NG | |
313 | ||
314 | static assert( is(typeof( da2 = [[a,a]] ))); // OK | |
315 | static assert(!is(typeof( da2[0][0] = a ))); // NG | |
316 | static assert(!is(typeof( da2[] = [a,a] ))); // NG | |
317 | static assert(!is(typeof( da2[][0] = a ))); // NG | |
318 | static assert(!is(typeof( da2[0][] = a ))); // NG | |
319 | } | |
320 | void func(Data a) | |
321 | { | |
322 | auto pdata = &data; | |
323 | ||
324 | static assert(!is(typeof( data = a ))); // NG | |
325 | static if (is(Data == struct)) | |
326 | { | |
327 | static assert(!is(typeof( data.x = 1 ))); // NG | |
328 | static assert(!is(typeof( data.y = 2 ))); // NG | |
329 | } | |
330 | static assert(!is(typeof( *pdata = a ))); // NG | |
331 | static assert(!is(typeof( *&data = a ))); // NG | |
332 | ||
333 | static assert(!is(typeof( sa1 = [a,a] ))); // NG | |
334 | static assert(!is(typeof( sa1[0] = a ))); // NG | |
335 | static assert(!is(typeof( sa1[] = a ))); // NG | |
336 | static assert(!is(typeof( sa1[][] = a ))); // NG | |
337 | ||
338 | static assert(!is(typeof( sa2 = [[a,a]] ))); // NG | |
339 | static assert(!is(typeof( sa2[0][0] = a ))); // NG | |
340 | static assert(!is(typeof( sa2[][0][] = a ))); // NG | |
341 | static assert(!is(typeof( sa2[0][][0] = a ))); // NG | |
342 | ||
343 | static assert(!is(typeof( sa3 = [[a],[]] ))); // NG | |
344 | static assert(!is(typeof( sa3[0] = [a,a] ))); // NG | |
345 | static assert(!is(typeof( sa3[0][0] = a ))); // NG | |
346 | static assert(!is(typeof( sa3[] = [a] ))); // NG | |
347 | static assert(!is(typeof( sa3[][0] = [a] ))); // NG | |
348 | static assert(!is(typeof( sa3[][0][0] = a ))); // NG | |
349 | ||
350 | static assert(!is(typeof( da1 = [a,a] ))); // NG | |
351 | static assert(!is(typeof( da1[0] = a ))); // NG | |
352 | static assert(!is(typeof( da1[] = a ))); // NG | |
353 | ||
354 | static assert(!is(typeof( da2 = [[a,a]] ))); // NG | |
355 | static assert(!is(typeof( da2[0][0] = a ))); // NG | |
356 | static assert(!is(typeof( da2[] = [a,a] ))); // NG | |
357 | static assert(!is(typeof( da2[][0] = a ))); // NG | |
358 | static assert(!is(typeof( da2[0][] = a ))); // NG | |
359 | } | |
360 | } | |
361 | ||
362 | const char gc6174; | |
363 | const char[1] ga6174; | |
364 | static this() | |
365 | { | |
366 | gc6174 = 'a'; // OK | |
367 | ga6174[0] = 'a'; // line 5, Err | |
368 | } | |
369 | struct Foo6174 | |
370 | { | |
371 | const char cc; | |
372 | const char[1] array; | |
373 | const char[1] arr; | |
374 | this(char c) | |
375 | { | |
376 | cc = c; // OK | |
377 | array = [c]; // line 12, Err | |
378 | arr[0] = c; // line 12, Err | |
379 | } | |
380 | } | |
381 | void test6174a() | |
382 | { | |
383 | static struct Pair | |
384 | { | |
385 | const int x; | |
386 | int y; | |
387 | } | |
388 | alias CtorTest6174!long CtorTest1; | |
389 | alias CtorTest6174!Pair CtorTest2; | |
390 | ||
391 | auto foo = Foo6174('c'); | |
392 | } | |
393 | ||
394 | /***************************************************/ | |
395 | ||
396 | template Select(bool cond, T, F) | |
397 | { | |
398 | static if (cond) | |
399 | alias Select = T; | |
400 | else | |
401 | alias Select = F; | |
402 | } | |
403 | ||
404 | void test6174b() | |
405 | { | |
406 | enum { none, unrelated, mutable, constant } | |
407 | ||
408 | static struct FieldStruct(bool c, int k) | |
409 | { | |
410 | enum fieldConst = c; | |
411 | enum assignKind = k; | |
412 | ||
413 | Select!(fieldConst, const int, int) x; | |
414 | int y; | |
415 | ||
416 | static if (assignKind == none) {} | |
417 | static if (assignKind == unrelated) void opAssign(int) {} | |
418 | static if (assignKind == mutable) void opAssign(FieldStruct) {} | |
419 | static if (assignKind == constant) void opAssign(FieldStruct) const {} | |
420 | } | |
421 | static struct TestStruct(F, bool fieldConst) | |
422 | { | |
423 | int w; | |
424 | Select!(fieldConst, const F, F) f; | |
425 | Select!(fieldConst, const int, int) z; | |
426 | ||
427 | this(int) | |
428 | { | |
429 | // If F has an identity `opAssign`,it is used even for initializing. | |
430 | // Otherwise, initializing will always succeed, by bypassing const qualifier. | |
431 | static assert(is(typeof( f = F() )) == ( | |
432 | F.assignKind == none || | |
433 | F.assignKind == unrelated || | |
434 | F.assignKind == mutable || | |
435 | F.assignKind == constant)); | |
436 | ||
437 | static assert(is(typeof( w = 1000 )) == true); | |
438 | static assert(is(typeof( f.x = 1000 )) == true); | |
439 | static assert(is(typeof( f.y = 1000 )) == true); | |
440 | static assert(is(typeof( z = 1000 )) == true); | |
441 | } | |
442 | void func() | |
443 | { | |
444 | // In mutable member functions, identity assignment is allowed | |
445 | // when all of the fields are identity assignable, | |
446 | // or identity `opAssign`, which callable from mutable object, is defined. | |
447 | static assert(__traits(compiles, f = F()) == ( | |
448 | F.assignKind == none && !fieldConst && !F.fieldConst || | |
449 | F.assignKind == unrelated && !fieldConst && !F.fieldConst || | |
450 | F.assignKind == constant || | |
451 | F.assignKind == mutable && !fieldConst)); | |
452 | ||
453 | static assert(__traits(compiles, w = 1000) == true); | |
454 | static assert(__traits(compiles, f.x = 1000) == (!fieldConst && !F.fieldConst)); | |
455 | static assert(__traits(compiles, f.y = 1000) == (!fieldConst && true )); | |
456 | static assert(__traits(compiles, z = 1000) == !fieldConst); | |
457 | } | |
458 | void func() const | |
459 | { | |
460 | // In non-mutable member functions, identity assignment is allowed | |
461 | // just only user-defined identity `opAssign` is qualified. | |
462 | static assert(__traits(compiles, f = F()) == (F.assignKind == constant)); | |
463 | ||
464 | static assert(__traits(compiles, w = 1000) == false); | |
465 | static assert(__traits(compiles, f.x = 1000) == false); | |
466 | static assert(__traits(compiles, f.y = 1000) == false); | |
467 | static assert(__traits(compiles, z = 1000) == false); | |
468 | } | |
469 | } | |
470 | foreach (fieldConst; TypeTuple!(false, true)) | |
471 | foreach ( hasConst; TypeTuple!(false, true)) | |
472 | foreach (assignKind; TypeTuple!(none, unrelated, mutable, constant)) | |
473 | { | |
474 | alias TestStruct!(FieldStruct!(hasConst, assignKind), fieldConst) TestX; | |
475 | } | |
476 | } | |
477 | ||
478 | void test6174c() | |
479 | { | |
480 | static assert(!is(typeof({ | |
481 | int func1a(int n) | |
482 | in{ n = 10; } | |
5fee5ec3 | 483 | do { return n; } |
b4c522fa IB |
484 | }))); |
485 | static assert(!is(typeof({ | |
486 | int func1b(int n) | |
487 | out(r){ r = 20; } | |
5fee5ec3 | 488 | do{ return n; } |
b4c522fa IB |
489 | }))); |
490 | ||
491 | struct DataX | |
492 | { | |
493 | int x; | |
494 | } | |
495 | static assert(!is(typeof({ | |
496 | DataX func2a(DataX n) | |
497 | in{ n.x = 10; } | |
5fee5ec3 | 498 | do { return n; } |
b4c522fa IB |
499 | }))); |
500 | static assert(!is(typeof({ | |
501 | DataX func2b(DataX n) | |
502 | in{} | |
503 | out(r){ r.x = 20; } | |
5fee5ec3 | 504 | do{ return n; } |
b4c522fa IB |
505 | }))); |
506 | } | |
507 | ||
508 | /***************************************************/ | |
5fee5ec3 | 509 | // https://issues.dlang.org/show_bug.cgi?id=6216 |
b4c522fa IB |
510 | |
511 | void test6216a() | |
512 | { | |
513 | static class C{} | |
514 | ||
515 | static struct Xa{ int n; } | |
516 | static struct Xb{ int[] a; } | |
517 | static struct Xc{ C c; } | |
518 | static struct Xd{ void opAssign(typeof(this) rhs){} } | |
519 | static struct Xe{ void opAssign(T)(T rhs){} } | |
520 | static struct Xf{ void opAssign(int rhs){} } | |
521 | static struct Xg{ void opAssign(T)(T rhs)if(!is(T==typeof(this))){} } | |
522 | ||
523 | // has value type as member | |
524 | static struct S1 (X){ static if (!is(X==void)) X x; int n; } | |
525 | ||
526 | // has reference type as member | |
527 | static struct S2a(X){ static if (!is(X==void)) X x; int[] a; } | |
528 | static struct S2b(X){ static if (!is(X==void)) X x; C c; } | |
529 | ||
530 | // has identity opAssign | |
531 | static struct S3a(X){ static if (!is(X==void)) X x; void opAssign(typeof(this) rhs){} } | |
532 | static struct S3b(X){ static if (!is(X==void)) X x; void opAssign(T)(T rhs){} } | |
533 | ||
534 | // has non identity opAssign | |
535 | static struct S4a(X){ static if (!is(X==void)) X x; void opAssign(int rhs){} } | |
536 | static struct S4b(X){ static if (!is(X==void)) X x; void opAssign(T)(T rhs)if(!is(T==typeof(this))){} } | |
537 | ||
538 | enum result = [ | |
539 | /*S1, S2a, S2b, S3a, S3b, S4a, S4b*/ | |
540 | /*- */ [true, true, true, true, true, true, true], | |
541 | /*Xa*/ [true, true, true, true, true, true, true], | |
542 | /*Xb*/ [true, true, true, true, true, true, true], | |
543 | /*Xc*/ [true, true, true, true, true, true, true], | |
544 | /*Xd*/ [true, true, true, true, true, true, true], | |
545 | /*Xe*/ [true, true, true, true, true, true, true], | |
546 | /*Xf*/ [true, true, true, true, true, true, true], | |
547 | /*Xg*/ [true, true, true, true, true, true, true], | |
548 | ]; | |
549 | ||
550 | pragma(msg, "\\\tS1\tS2a\tS2b\tS3a\tS3b\tS4a\tS4b"); | |
551 | foreach (i, X; TypeTuple!(void,Xa,Xb,Xc,Xd,Xe,Xf,Xg)) | |
552 | { | |
553 | S1!X s1; | |
554 | S2a!X s2a; | |
555 | S2b!X s2b; | |
556 | S3a!X s3a; | |
557 | S3b!X s3b; | |
558 | S4a!X s4a; | |
559 | S4b!X s4b; | |
560 | ||
561 | pragma(msg, | |
562 | is(X==void) ? "-" : X.stringof, | |
563 | "\t", __traits(compiles, (s1 = s1)), | |
564 | "\t", __traits(compiles, (s2a = s2a)), | |
565 | "\t", __traits(compiles, (s2b = s2b)), | |
566 | "\t", __traits(compiles, (s3a = s3a)), | |
567 | "\t", __traits(compiles, (s3b = s3b)), | |
568 | "\t", __traits(compiles, (s4a = s4a)), | |
569 | "\t", __traits(compiles, (s4b = s4b)) ); | |
570 | ||
571 | static assert(result[i] == | |
572 | [ __traits(compiles, (s1 = s1)), | |
573 | __traits(compiles, (s2a = s2a)), | |
574 | __traits(compiles, (s2b = s2b)), | |
575 | __traits(compiles, (s3a = s3a)), | |
576 | __traits(compiles, (s3b = s3b)), | |
577 | __traits(compiles, (s4a = s4a)), | |
578 | __traits(compiles, (s4b = s4b)) ]); | |
579 | } | |
580 | } | |
581 | ||
582 | void test6216b() | |
583 | { | |
584 | static int cnt = 0; | |
585 | ||
586 | static struct X | |
587 | { | |
588 | int n; | |
589 | void opAssign(X rhs){ cnt = 1; } | |
590 | } | |
591 | static struct S | |
592 | { | |
593 | int n; | |
594 | X x; | |
595 | } | |
596 | ||
597 | S s; | |
598 | s = s; | |
599 | assert(cnt == 1); | |
600 | // Built-in opAssign runs member's opAssign | |
601 | } | |
602 | ||
603 | void test6216c() | |
604 | { | |
605 | static int cnt = 0; | |
606 | ||
607 | static struct X | |
608 | { | |
609 | int n; | |
610 | void opAssign(const X rhs) const { cnt = 2; } | |
611 | } | |
612 | static struct S | |
613 | { | |
614 | int n; | |
615 | const(X) x; | |
616 | } | |
617 | ||
618 | S s; | |
619 | const(S) cs; | |
620 | s = s; | |
621 | s = cs; // cs is copied as mutable and assigned into s | |
622 | assert(cnt == 2); | |
623 | static assert(!__traits(compiles, cs = cs)); | |
624 | // built-in opAssin is only allowed with mutable object | |
625 | } | |
626 | ||
627 | void test6216d() | |
628 | { | |
629 | static int cnt = 0; | |
630 | ||
631 | static struct X | |
632 | { | |
633 | int[] arr; // X has mutable indirection | |
634 | void opAssign(const X rhs) const { ++cnt; } | |
635 | } | |
636 | static struct S | |
637 | { | |
638 | int n; | |
639 | const(X) x; | |
640 | } | |
641 | ||
642 | X mx; | |
643 | const X cx; | |
644 | mx = mx; // copying mx to const X is possible | |
645 | assert(cnt == 1); | |
646 | mx = cx; | |
647 | assert(cnt == 2); | |
648 | cx = mx; // copying mx to const X is possible | |
649 | assert(cnt == 3); | |
650 | ||
651 | S s; | |
652 | const(S) cs; | |
653 | s = s; | |
654 | s = cs; | |
655 | //assert(cnt == 4); | |
656 | static assert(!__traits(compiles, cs = cs)); | |
657 | // built-in opAssin is only allowed with mutable object | |
658 | } | |
659 | ||
660 | void test6216e() | |
661 | { | |
662 | static struct X | |
663 | { | |
664 | int x; | |
665 | @disable void opAssign(X); | |
666 | } | |
667 | static struct S | |
668 | { | |
669 | X x; | |
670 | } | |
671 | S s; | |
672 | static assert(!__traits(compiles, s = s)); | |
673 | // built-in generated opAssin is marked as @disable. | |
674 | } | |
675 | ||
676 | /***************************************************/ | |
5fee5ec3 | 677 | // https://issues.dlang.org/show_bug.cgi?id=6286 |
b4c522fa IB |
678 | |
679 | void test6286() | |
680 | { | |
681 | const(int)[4] src = [1, 2, 3, 4]; | |
682 | int[4] dst; | |
683 | dst = src; | |
684 | dst[] = src[]; | |
685 | dst = 4; | |
686 | int[4][4] x; | |
687 | x = dst; | |
688 | } | |
689 | ||
690 | /***************************************************/ | |
5fee5ec3 | 691 | // https://issues.dlang.org/show_bug.cgi?id=6336 |
b4c522fa IB |
692 | |
693 | void test6336() | |
694 | { | |
695 | // structs aren't identity assignable | |
696 | static struct S1 | |
697 | { | |
698 | immutable int n; | |
699 | } | |
700 | static struct S2 | |
701 | { | |
702 | void opAssign(int n){ assert(0); } | |
703 | } | |
704 | ||
705 | S1 s1; | |
706 | S2 s2; | |
707 | ||
708 | void f(S)(out S s){} | |
709 | static assert(!__traits(compiles, f(s1))); | |
710 | f(s2); | |
711 | // Out parameters refuse only S1 because it isn't blit assignable | |
712 | ||
713 | ref S g(S)(ref S s){ return s; } | |
714 | g(s1); | |
715 | g(s2); | |
716 | // Allow return by ref both S1 and S2 | |
717 | } | |
718 | ||
719 | /***************************************************/ | |
5fee5ec3 | 720 | // https://issues.dlang.org/show_bug.cgi?id=8783 |
b4c522fa IB |
721 | |
722 | struct Foo8783 | |
723 | { | |
724 | int[1] bar; | |
725 | } | |
726 | ||
727 | const Foo8783[1] foos8783; | |
728 | ||
729 | static this() | |
730 | { | |
731 | foreach (i; 0 .. foos8783.length) | |
732 | foos8783[i].bar[i] = 1; // OK | |
733 | foreach (i, ref f; foos8783) | |
734 | f.bar[i] = 1; // line 9, Error | |
735 | } | |
736 | ||
737 | /***************************************************/ | |
5fee5ec3 | 738 | // https://issues.dlang.org/show_bug.cgi?id=9077 |
b4c522fa IB |
739 | |
740 | struct S9077a | |
741 | { | |
742 | void opAssign(int n) {} | |
743 | void test() { typeof(this) s; s = this; } | |
744 | this(this) {} | |
745 | } | |
746 | struct S9077b | |
747 | { | |
748 | void opAssign()(int n) {} | |
749 | void test() { typeof(this) s; s = this; } | |
750 | this(this) {} | |
751 | } | |
752 | ||
753 | /***************************************************/ | |
5fee5ec3 | 754 | // https://issues.dlang.org/show_bug.cgi?id=9140 |
b4c522fa IB |
755 | |
756 | immutable(int)[] bar9140() | |
757 | out(result) { | |
758 | foreach (ref r; result) {} | |
5fee5ec3 | 759 | } do { |
b4c522fa IB |
760 | return null; |
761 | } | |
762 | ||
763 | /***************************************************/ | |
5fee5ec3 | 764 | // https://issues.dlang.org/show_bug.cgi?id=9154 |
b4c522fa IB |
765 | |
766 | struct S9154a | |
767 | { | |
768 | int x; | |
769 | void opAssign(ref S9154a s) { } | |
770 | } | |
771 | struct S9154b | |
772 | { | |
773 | int x; | |
774 | void opAssign(X)(ref X s) { } | |
775 | } | |
776 | struct T9154 | |
777 | { | |
778 | S9154a member1; | |
779 | S9154b member2; | |
780 | } | |
781 | ||
782 | void test9154() | |
783 | { | |
784 | T9154 t1, t2; | |
785 | t1 = t2; | |
786 | } | |
787 | ||
788 | /***************************************************/ | |
5fee5ec3 | 789 | // https://issues.dlang.org/show_bug.cgi?id=9258 |
b4c522fa IB |
790 | |
791 | class A9258 {} | |
792 | class B9258 : A9258 // Error: class test.B9258 identity assignment operator overload is illegal | |
793 | { | |
794 | void opAssign(A9258 b) {} | |
795 | } | |
796 | ||
797 | class C9258 | |
798 | { | |
799 | int n; | |
800 | alias n this; | |
801 | void opAssign(int n) {} | |
802 | } | |
803 | class D9258 | |
804 | { | |
805 | int n; | |
806 | alias n this; | |
807 | void opAssign(int n, int y = 0) {} | |
808 | } | |
809 | class E9258 : A9258 | |
810 | { | |
811 | void set(A9258 a) {} | |
812 | alias set opAssign; | |
813 | } | |
814 | ||
815 | /***************************************************/ | |
5fee5ec3 | 816 | // https://issues.dlang.org/show_bug.cgi?id=9416 |
b4c522fa IB |
817 | |
818 | struct S9416 | |
819 | { | |
820 | void opAssign()(S9416) | |
821 | { | |
822 | static assert(0); | |
823 | } | |
824 | } | |
825 | struct U9416 | |
826 | { | |
827 | S9416 s; | |
828 | } | |
829 | void test9416() | |
830 | { | |
831 | U9416 u; | |
832 | static assert(__traits(allMembers, U9416)[$-1] == "opAssign"); | |
833 | static assert(!__traits(compiles, u = u)); | |
834 | } | |
835 | ||
836 | /***************************************************/ | |
5fee5ec3 | 837 | // https://issues.dlang.org/show_bug.cgi?id=9658 |
b4c522fa IB |
838 | |
839 | struct S9658 | |
840 | { | |
841 | private bool _isNull = true; | |
842 | this(int v) const | |
843 | { | |
844 | _isNull = false; // cannot modify const expression this._isNull | |
845 | } | |
846 | } | |
847 | ||
848 | /***************************************************/ | |
5fee5ec3 | 849 | // https://issues.dlang.org/show_bug.cgi?id=11187 |
b4c522fa IB |
850 | |
851 | void test11187() | |
852 | { | |
853 | static struct X | |
854 | { | |
855 | int[] arr; | |
856 | } | |
857 | static struct S | |
858 | { | |
859 | const(X) cx; | |
860 | } | |
861 | static assert(is(typeof((const S).init.cx.arr) == const(int[]))); | |
862 | static assert(is(typeof(( S).init.cx.arr) == const(int[]))); | |
863 | const S sc; | |
864 | S sm = sc; | |
865 | static assert(is(const S : S)); | |
866 | } | |
867 | ||
868 | /***************************************************/ | |
5fee5ec3 | 869 | // https://issues.dlang.org/show_bug.cgi?id=12131 |
b4c522fa IB |
870 | |
871 | struct X12131 | |
872 | { | |
873 | void opAssign()(X12131 y) pure {} | |
874 | } | |
875 | ||
876 | struct Y12131 | |
877 | { | |
878 | X12131 a; | |
879 | } | |
880 | ||
881 | void test12131() pure | |
882 | { | |
883 | X12131 x; | |
884 | x = X12131(); // OK | |
885 | ||
886 | Y12131 y; | |
887 | y = Y12131(); // OK <- Error | |
888 | } | |
889 | ||
890 | /***************************************************/ | |
5fee5ec3 | 891 | // https://issues.dlang.org/show_bug.cgi?id=12211 |
b4c522fa IB |
892 | |
893 | void test12211() | |
894 | { | |
895 | int a = 0; | |
896 | void foo(ref int x) | |
897 | { | |
898 | assert(x == 10); | |
899 | assert(&x == &a); | |
900 | x = 3; | |
901 | } | |
902 | foo(a = 10); | |
903 | assert(a == 3); | |
904 | foo(a += 7); | |
905 | assert(a == 3); | |
906 | ||
907 | // array ops should make rvalue | |
908 | int[3] sa, sb; | |
909 | void bar(ref int[]) {} | |
5fee5ec3 IB |
910 | static assert(__traits(compiles, bar(sa[] = sb[]))); |
911 | static assert(__traits(compiles, bar(sa[] += sb[]))); | |
b4c522fa IB |
912 | } |
913 | ||
914 | /***************************************************/ | |
5fee5ec3 | 915 | // https://issues.dlang.org/show_bug.cgi?id=4791 (dup of 12212) |
b4c522fa IB |
916 | |
917 | void test4791() | |
918 | { | |
919 | int[2] na; | |
920 | na = na; | |
921 | ||
922 | static struct S | |
923 | { | |
924 | static string res; | |
925 | int n; | |
926 | this(this) { ++n; res ~= "p" ~ cast(char)('0' + n); } | |
927 | ~this() { res ~= "d" ~ cast(char)('0' + n); } | |
928 | } | |
929 | { | |
930 | S[3] sa; | |
931 | sa[0].n = 1, sa[1].n = 2, sa[2].n = 3; | |
932 | ||
933 | S.res = null; | |
934 | sa = sa; | |
935 | assert(S.res == "p2d1p3d2p4d3"); | |
936 | assert(sa[0].n == 2 && sa[1].n == 3 && sa[2].n == 4); | |
937 | ||
938 | S.res = null; | |
939 | } | |
940 | assert(S.res == "d4d3d2"); | |
941 | } | |
942 | ||
943 | /***************************************************/ | |
5fee5ec3 | 944 | // https://issues.dlang.org/show_bug.cgi?id=12212 |
b4c522fa IB |
945 | |
946 | void test12212() | |
947 | { | |
948 | struct S | |
949 | { | |
950 | int x, y; | |
951 | static int cpctor; | |
952 | this(this) { cpctor++; } | |
953 | } | |
954 | ||
955 | void funcVal(E)(E[3] x) {} | |
956 | auto funcRef(E)(ref E[3] x) { return &x; } | |
957 | ref get(E)(ref E[3] a){ return a; } | |
958 | ||
959 | { | |
960 | int[3] a, b; | |
961 | funcVal(a = b); | |
962 | ||
963 | auto p = funcRef(a = b); | |
964 | assert(p == &a); | |
965 | } | |
966 | ||
967 | { | |
968 | S.cpctor = 0; | |
969 | ||
970 | S[3] a, b; | |
971 | assert(S.cpctor == 0); | |
972 | ||
973 | S[3] c = a; | |
974 | //printf("cpctpr = %d\n", S.cpctor); | |
975 | assert(S.cpctor == 3); | |
976 | S.cpctor = 0; | |
977 | ||
978 | c = a; | |
979 | //printf("cpctpr = %d\n", S.cpctor); | |
980 | assert(S.cpctor == 3); | |
981 | S.cpctor = 0; | |
982 | ||
983 | c = (a = b); | |
984 | //printf("cpctpr = %d\n", S.cpctor); | |
985 | assert(S.cpctor == 6); | |
986 | S.cpctor = 0; | |
987 | ||
988 | c = (get(a) = b); | |
989 | //printf("cpctpr = %d\n", S.cpctor); | |
990 | assert(S.cpctor == 6); | |
991 | S.cpctor = 0; | |
992 | } | |
993 | { | |
994 | S.cpctor = 0; | |
995 | ||
996 | S[3] a, b; | |
997 | assert(S.cpctor == 0); | |
998 | ||
999 | funcVal(a = b); | |
1000 | //printf("cpctpr = %d\n", S.cpctor); | |
1001 | assert(S.cpctor == 6); | |
1002 | S.cpctor = 0; | |
1003 | ||
1004 | funcVal(get(a) = b); | |
1005 | //printf("cpctpr = %d\n", S.cpctor); | |
1006 | assert(S.cpctor == 6); | |
1007 | S.cpctor = 0; | |
1008 | } | |
1009 | { | |
1010 | S.cpctor = 0; | |
1011 | ||
1012 | S[3] a, b; | |
1013 | assert(S.cpctor == 0); | |
1014 | ||
1015 | S[3]* p; | |
1016 | ||
1017 | p = funcRef(a = b); | |
1018 | //printf("cpctpr = %d\n", S.cpctor); | |
1019 | assert(p == &a); | |
1020 | assert(S.cpctor == 3); | |
1021 | S.cpctor = 0; | |
1022 | ||
1023 | p = funcRef(get(a) = b); | |
1024 | assert(p == &a); | |
1025 | //printf("cpctpr = %d\n", S.cpctor); | |
1026 | assert(S.cpctor == 3); | |
1027 | S.cpctor = 0; | |
1028 | } | |
1029 | } | |
1030 | ||
1031 | /***************************************************/ | |
5fee5ec3 | 1032 | // https://issues.dlang.org/show_bug.cgi?id=12650 |
b4c522fa IB |
1033 | |
1034 | void test12650() | |
1035 | { | |
1036 | // AssignExp::toElem should make an lvalue of e1. | |
1037 | static class A1 | |
1038 | { | |
1039 | struct S { int a; } | |
1040 | ||
1041 | static foo(ref const(S) s) | |
1042 | { | |
1043 | assert(s.a == 2); | |
1044 | return &s; | |
1045 | } | |
1046 | ||
1047 | S s; | |
1048 | ||
1049 | this() | |
1050 | { | |
1051 | const v = S(2); | |
1052 | ||
1053 | // (this.s = v) will become ConstructExp | |
1054 | auto p = foo(s = v); | |
1055 | assert(p == &s); | |
1056 | } | |
1057 | } | |
1058 | assert(new A1().s.a == 2); | |
1059 | ||
1060 | static class A2 | |
1061 | { | |
1062 | static foo(ref int[2] sa) | |
1063 | { | |
1064 | assert(sa[1] == 2); | |
1065 | return &sa; | |
1066 | } | |
1067 | ||
1068 | int[2] sa; | |
1069 | ||
1070 | this() | |
1071 | { | |
1072 | // (this.sa = [1,2]) will become ConstructExp | |
1073 | auto p = foo(sa = [1,2]); | |
1074 | assert(p == &sa); | |
1075 | } | |
1076 | } | |
1077 | assert(new A2().sa[1] == 2); | |
1078 | ||
1079 | static class A3 | |
1080 | { | |
1081 | static foo(ref int n) | |
1082 | { | |
1083 | assert(n == 2); | |
1084 | return &n; | |
1085 | } | |
1086 | ||
1087 | int n; | |
1088 | ||
1089 | this() | |
1090 | { | |
1091 | const v = 2; | |
1092 | ||
1093 | // (this.n = v) will become ConstructExp | |
1094 | auto p = foo(n = v); | |
1095 | assert(p == &n); | |
1096 | } | |
1097 | } | |
1098 | assert(new A3().n == 2); | |
1099 | } | |
1100 | ||
1101 | /***************************************************/ | |
5fee5ec3 | 1102 | // https://issues.dlang.org/show_bug.cgi?id=13044 |
b4c522fa IB |
1103 | |
1104 | void test13044() | |
1105 | { | |
1106 | static struct Good | |
1107 | { | |
1108 | const int i; | |
1109 | } | |
1110 | ||
1111 | static struct Bad | |
1112 | { | |
1113 | const int i; | |
1114 | ~this() {} | |
1115 | } | |
1116 | ||
1117 | Good good1, good2; | |
1118 | static assert(!__traits(compiles, { good1 = good2; })); // OK | |
1119 | ||
1120 | Bad bad1, bad2; | |
1121 | static assert(!__traits(compiles, { bad1 = bad2; })); // OK <- fails | |
1122 | } | |
1123 | ||
1124 | /***************************************************/ | |
5fee5ec3 | 1125 | // https://issues.dlang.org/show_bug.cgi?id=12500 |
b4c522fa IB |
1126 | |
1127 | void test12500() | |
1128 | { | |
1129 | size_t foo; | |
1130 | ++foo *= 1.5; // Rewrite to: (foo += 1) *= 1.5; | |
1131 | } | |
1132 | ||
1133 | /***************************************************/ | |
5fee5ec3 | 1134 | // https://issues.dlang.org/show_bug.cgi?id=14672 |
b4c522fa IB |
1135 | |
1136 | void test14672() | |
1137 | { | |
1138 | interface I {} | |
1139 | ||
1140 | class B {} | |
1141 | class D : B, I {} | |
1142 | ||
1143 | D d = new D(); | |
1144 | D[] da = [d]; | |
1145 | B[] ba = [null]; | |
1146 | I[] ia = [null]; | |
1147 | ||
1148 | // ba and da points different payloads, | |
1149 | // so element-wise assignment should work. | |
1150 | ba[] = da[]; // OK <- e2ir ICE | |
1151 | assert(ba[0] is d); | |
1152 | ||
1153 | // Today element-wise assignment is implemented as memcpy, For that reason | |
1154 | // the conversion from derived classes to base interfaces is disallowed | |
1155 | // because it requries offset adjustments. | |
1156 | static assert(!__traits(compiles, { ia[] = da[]; })); | |
1157 | ||
1158 | // after the assignment, ba will wongly point the payload of da, | |
1159 | // that's typed as D[]. To aboid type system breaking, it's disallowed. | |
1160 | static assert(!__traits(compiles, { ba = da; })); | |
1161 | ||
1162 | // the assigned array literal is a new payload, | |
1163 | // so rebinding ba should work. | |
1164 | ba = [d]; // OK | |
1165 | assert(ba[0] is d); | |
1166 | } | |
1167 | ||
1168 | /***************************************************/ | |
5fee5ec3 | 1169 | // https://issues.dlang.org/show_bug.cgi?id=15044 |
b4c522fa IB |
1170 | |
1171 | void destroy15044(T)(ref T obj) | |
1172 | { | |
1173 | static if (__traits(hasMember, T, "__xdtor")) | |
1174 | obj.__xdtor(); | |
1175 | else | |
1176 | static assert(0, T.stringof); | |
1177 | } | |
1178 | ||
1179 | struct V15044 | |
1180 | { | |
1181 | ~this() | |
1182 | { | |
1183 | } | |
1184 | ||
5fee5ec3 | 1185 | RC15044!V15044 dup() return |
b4c522fa IB |
1186 | { |
1187 | return RC15044!V15044(&this); | |
1188 | } | |
1189 | } | |
1190 | ||
1191 | struct RC15044(T) | |
1192 | { | |
1193 | ~this() | |
1194 | { | |
1195 | destroy15044(*t); | |
1196 | static assert(__traits(hasMember, T, "__xdtor")); | |
1197 | } | |
1198 | T* t; | |
1199 | } | |
1200 | ||
1201 | /***************************************************/ | |
1202 | ||
1203 | int main() | |
1204 | { | |
1205 | test1(); | |
1206 | test2(); | |
1207 | test3(); | |
1208 | test4(); | |
1209 | test5(); | |
c8dfa79c | 1210 | test6(); |
b4c522fa IB |
1211 | test4424(); |
1212 | test6174a(); | |
1213 | test6174b(); | |
1214 | test6174c(); | |
1215 | test6216a(); | |
1216 | test6216b(); | |
1217 | test6216c(); | |
1218 | test6216d(); | |
1219 | test6216e(); | |
1220 | test6286(); | |
1221 | test6336(); | |
1222 | test9154(); | |
1223 | test9416(); | |
1224 | test11187(); | |
1225 | test12131(); | |
1226 | test12211(); | |
1227 | test4791(); | |
1228 | test12212(); | |
1229 | test12650(); | |
1230 | test13044(); | |
1231 | test12500(); | |
1232 | test14672(); | |
1233 | ||
1234 | printf("Success\n"); | |
1235 | return 0; | |
1236 | } |