1 /**
2  * Semantic analysis for cast-expressions.
3  *
4  * Copyright:   Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
5  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
6  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7  * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/dcast.d, _dcast.d)
8  * Documentation:  https://dlang.org/phobos/dmd_dcast.html
9  * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/dcast.d
10  */
11 
12 module dmd.dcast;
13 
14 import core.stdc.stdio;
15 import core.stdc..string;
16 import dmd.aggregate;
17 import dmd.aliasthis;
18 import dmd.arrayop;
19 import dmd.arraytypes;
20 import dmd.dclass;
21 import dmd.declaration;
22 import dmd.dscope;
23 import dmd.dstruct;
24 import dmd.dsymbol;
25 import dmd.errors;
26 import dmd.escape;
27 import dmd.expression;
28 import dmd.expressionsem;
29 import dmd.func;
30 import dmd.globals;
31 import dmd.impcnvtab;
32 import dmd.id;
33 import dmd.init;
34 import dmd.intrange;
35 import dmd.mtype;
36 import dmd.opover;
37 import dmd.root.ctfloat;
38 import dmd.root.outbuffer;
39 import dmd.root.rmem;
40 import dmd.tokens;
41 import dmd.typesem;
42 import dmd.utf;
43 import dmd.visitor;
44 
45 enum LOG = false;
46 
47 /**************************************
48  * Do an implicit cast.
49  * Issue error if it can't be done.
50  */
51 Expression implicitCastTo(Expression e, Scope* sc, Type t)
52 {
53     extern (C++) final class ImplicitCastTo : Visitor
54     {
55         alias visit = Visitor.visit;
56     public:
57         Type t;
58         Scope* sc;
59         Expression result;
60 
61         extern (D) this(Scope* sc, Type t)
62         {
63             this.sc = sc;
64             this.t = t;
65         }
66 
67         override void visit(Expression e)
68         {
69             //printf("Expression.implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
70 
71             if (const match = e.implicitConvTo(t))
72             {
73                 if (match == MATCH.constant && (e.type.constConv(t) || !e.isLvalue() && e.type.equivalent(t)))
74                 {
75                     /* Do not emit CastExp for const conversions and
76                      * unique conversions on rvalue.
77                      */
78                     result = e.copy();
79                     result.type = t;
80                     return;
81                 }
82 
83                 auto ad = isAggregate(e.type);
84                 if (ad && ad.aliasthis)
85                 {
86                     auto ts = ad.type.isTypeStruct();
87                     const adMatch = ts
88                         ? ts.implicitConvToWithoutAliasThis(t)
89                         : ad.type.isTypeClass().implicitConvToWithoutAliasThis(t);
90 
91                     if (!adMatch)
92                     {
93                         Type tob = t.toBasetype();
94                         Type t1b = e.type.toBasetype();
95                         if (ad != isAggregate(tob))
96                         {
97                             if (t1b.ty == Tclass && tob.ty == Tclass)
98                             {
99                                 ClassDeclaration t1cd = t1b.isClassHandle();
100                                 ClassDeclaration tocd = tob.isClassHandle();
101                                 int offset;
102                                 if (tocd.isBaseOf(t1cd, &offset))
103                                 {
104                                     result = new CastExp(e.loc, e, t);
105                                     result.type = t;
106                                     return;
107                                 }
108                             }
109 
110                             /* Forward the cast to our alias this member, rewrite to:
111                              *   cast(to)e1.aliasthis
112                              */
113                             result = resolveAliasThis(sc, e);
114                             result = result.castTo(sc, t);
115                             return;
116                        }
117                     }
118                 }
119 
120                 result = e.castTo(sc, t);
121                 return;
122             }
123 
124             result = e.optimize(WANTvalue);
125             if (result != e)
126             {
127                 result.accept(this);
128                 return;
129             }
130 
131             if (t.ty != Terror && e.type.ty != Terror)
132             {
133                 if (!t.deco)
134                 {
135                     e.error("forward reference to type `%s`", t.toChars());
136                 }
137                 else
138                 {
139                     //printf("type %p ty %d deco %p\n", type, type.ty, type.deco);
140                     //type = type.typeSemantic(loc, sc);
141                     //printf("type %s t %s\n", type.deco, t.deco);
142                     auto ts = toAutoQualChars(e.type, t);
143                     e.error("cannot implicitly convert expression `%s` of type `%s` to `%s`",
144                         e.toChars(), ts[0], ts[1]);
145                 }
146             }
147             result = new ErrorExp();
148         }
149 
150         override void visit(StringExp e)
151         {
152             //printf("StringExp::implicitCastTo(%s of type %s) => %s\n", e.toChars(), e.type.toChars(), t.toChars());
153             visit(cast(Expression)e);
154             if (auto se = result.isStringExp())
155             {
156                 // Retain polysemous nature if it started out that way
157                 se.committed = e.committed;
158             }
159         }
160 
161         override void visit(ErrorExp e)
162         {
163             result = e;
164         }
165 
166         override void visit(FuncExp e)
167         {
168             //printf("FuncExp::implicitCastTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars());
169             FuncExp fe;
170             if (e.matchType(t, sc, &fe) > MATCH.nomatch)
171             {
172                 result = fe;
173                 return;
174             }
175             visit(cast(Expression)e);
176         }
177 
178         override void visit(ArrayLiteralExp e)
179         {
180             visit(cast(Expression)e);
181 
182             Type tb = result.type.toBasetype();
183             if (auto ta = tb.isTypeDArray())
184                 if (global.params.useTypeInfo && Type.dtypeinfo)
185                     semanticTypeInfo(sc, ta.next);
186         }
187 
188         override void visit(SliceExp e)
189         {
190             visit(cast(Expression)e);
191 
192             if (auto se = result.isSliceExp())
193                 if (auto ale = se.e1.isArrayLiteralExp())
194                 {
195                     Type tb = t.toBasetype();
196                     Type tx = (tb.ty == Tsarray)
197                         ? tb.nextOf().sarrayOf(ale.elements ? ale.elements.dim : 0)
198                         : tb.nextOf().arrayOf();
199                     se.e1 = ale.implicitCastTo(sc, tx);
200                 }
201         }
202     }
203 
204     scope ImplicitCastTo v = new ImplicitCastTo(sc, t);
205     e.accept(v);
206     return v.result;
207 }
208 
209 /*******************************************
210  * Return MATCH level of implicitly converting e to type t.
211  * Don't do the actual cast; don't change e.
212  */
213 MATCH implicitConvTo(Expression e, Type t)
214 {
215     extern (C++) final class ImplicitConvTo : Visitor
216     {
217         alias visit = Visitor.visit;
218     public:
219         Type t;
220         MATCH result;
221 
222         extern (D) this(Type t)
223         {
224             this.t = t;
225             result = MATCH.nomatch;
226         }
227 
228         override void visit(Expression e)
229         {
230             version (none)
231             {
232                 printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
233             }
234             //static int nest; if (++nest == 10) assert(0);
235             if (t == Type.terror)
236                 return;
237             if (!e.type)
238             {
239                 e.error("`%s` is not an expression", e.toChars());
240                 e.type = Type.terror;
241             }
242 
243             Expression ex = e.optimize(WANTvalue);
244             if (ex.type.equals(t))
245             {
246                 result = MATCH.exact;
247                 return;
248             }
249             if (ex != e)
250             {
251                 //printf("\toptimized to %s of type %s\n", e.toChars(), e.type.toChars());
252                 result = ex.implicitConvTo(t);
253                 return;
254             }
255 
256             MATCH match = e.type.implicitConvTo(t);
257             if (match != MATCH.nomatch)
258             {
259                 result = match;
260                 return;
261             }
262 
263             /* See if we can do integral narrowing conversions
264              */
265             if (e.type.isintegral() && t.isintegral() && e.type.isTypeBasic() && t.isTypeBasic())
266             {
267                 IntRange src = getIntRange(e);
268                 IntRange target = IntRange.fromType(t);
269                 if (target.contains(src))
270                 {
271                     result = MATCH.convert;
272                     return;
273                 }
274             }
275         }
276 
277         /******
278          * Given expression e of type t, see if we can implicitly convert e
279          * to type tprime, where tprime is type t with mod bits added.
280          * Returns:
281          *      match level
282          */
283         static MATCH implicitMod(Expression e, Type t, MOD mod)
284         {
285             Type tprime;
286             if (t.ty == Tpointer)
287                 tprime = t.nextOf().castMod(mod).pointerTo();
288             else if (t.ty == Tarray)
289                 tprime = t.nextOf().castMod(mod).arrayOf();
290             else if (t.ty == Tsarray)
291                 tprime = t.nextOf().castMod(mod).sarrayOf(t.size() / t.nextOf().size());
292             else
293                 tprime = t.castMod(mod);
294 
295             return e.implicitConvTo(tprime);
296         }
297 
298         static MATCH implicitConvToAddMin(BinExp e, Type t)
299         {
300             /* Is this (ptr +- offset)? If so, then ask ptr
301              * if the conversion can be done.
302              * This is to support doing things like implicitly converting a mutable unique
303              * pointer to an immutable pointer.
304              */
305 
306             Type tb = t.toBasetype();
307             Type typeb = e.type.toBasetype();
308 
309             if (typeb.ty != Tpointer || tb.ty != Tpointer)
310                 return MATCH.nomatch;
311 
312             Type t1b = e.e1.type.toBasetype();
313             Type t2b = e.e2.type.toBasetype();
314             if (t1b.ty == Tpointer && t2b.isintegral() && t1b.equivalent(tb))
315             {
316                 // ptr + offset
317                 // ptr - offset
318                 MATCH m = e.e1.implicitConvTo(t);
319                 return (m > MATCH.constant) ? MATCH.constant : m;
320             }
321             if (t2b.ty == Tpointer && t1b.isintegral() && t2b.equivalent(tb))
322             {
323                 // offset + ptr
324                 MATCH m = e.e2.implicitConvTo(t);
325                 return (m > MATCH.constant) ? MATCH.constant : m;
326             }
327 
328             return MATCH.nomatch;
329         }
330 
331         override void visit(AddExp e)
332         {
333             version (none)
334             {
335                 printf("AddExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
336             }
337             visit(cast(Expression)e);
338             if (result == MATCH.nomatch)
339                 result = implicitConvToAddMin(e, t);
340         }
341 
342         override void visit(MinExp e)
343         {
344             version (none)
345             {
346                 printf("MinExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
347             }
348             visit(cast(Expression)e);
349             if (result == MATCH.nomatch)
350                 result = implicitConvToAddMin(e, t);
351         }
352 
353         override void visit(IntegerExp e)
354         {
355             version (none)
356             {
357                 printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
358             }
359             MATCH m = e.type.implicitConvTo(t);
360             if (m >= MATCH.constant)
361             {
362                 result = m;
363                 return;
364             }
365 
366             TY ty = e.type.toBasetype().ty;
367             TY toty = t.toBasetype().ty;
368             TY oldty = ty;
369 
370             if (m == MATCH.nomatch && t.ty == Tenum)
371                 return;
372 
373             if (auto tv = t.isTypeVector())
374             {
375                 TypeBasic tb = tv.elementType();
376                 if (tb.ty == Tvoid)
377                     return;
378                 toty = tb.ty;
379             }
380 
381             switch (ty)
382             {
383             case Tbool:
384             case Tint8:
385             case Tchar:
386             case Tuns8:
387             case Tint16:
388             case Tuns16:
389             case Twchar:
390                 ty = Tint32;
391                 break;
392 
393             case Tdchar:
394                 ty = Tuns32;
395                 break;
396 
397             default:
398                 break;
399             }
400 
401             // Only allow conversion if no change in value
402             immutable dinteger_t value = e.toInteger();
403 
404             bool isLosslesslyConvertibleToFP(T)()
405             {
406                 if (e.type.isunsigned())
407                 {
408                     const f = cast(T) value;
409                     return cast(dinteger_t) f == value;
410                 }
411 
412                 const f = cast(T) cast(sinteger_t) value;
413                 return cast(sinteger_t) f == cast(sinteger_t) value;
414             }
415 
416             switch (toty)
417             {
418             case Tbool:
419                 if ((value & 1) != value)
420                     return;
421                 break;
422 
423             case Tint8:
424                 if (ty == Tuns64 && value & ~0x7FU)
425                     return;
426                 else if (cast(byte)value != value)
427                     return;
428                 break;
429 
430             case Tchar:
431                 if ((oldty == Twchar || oldty == Tdchar) && value > 0x7F)
432                     return;
433                 goto case Tuns8;
434             case Tuns8:
435                 //printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value);
436                 if (cast(ubyte)value != value)
437                     return;
438                 break;
439 
440             case Tint16:
441                 if (ty == Tuns64 && value & ~0x7FFFU)
442                     return;
443                 else if (cast(short)value != value)
444                     return;
445                 break;
446 
447             case Twchar:
448                 if (oldty == Tdchar && value > 0xD7FF && value < 0xE000)
449                     return;
450                 goto case Tuns16;
451             case Tuns16:
452                 if (cast(ushort)value != value)
453                     return;
454                 break;
455 
456             case Tint32:
457                 if (ty == Tuns32)
458                 {
459                 }
460                 else if (ty == Tuns64 && value & ~0x7FFFFFFFU)
461                     return;
462                 else if (cast(int)value != value)
463                     return;
464                 break;
465 
466             case Tuns32:
467                 if (ty == Tint32)
468                 {
469                 }
470                 else if (cast(uint)value != value)
471                     return;
472                 break;
473 
474             case Tdchar:
475                 if (value > 0x10FFFFU)
476                     return;
477                 break;
478 
479             case Tfloat32:
480                 if (!isLosslesslyConvertibleToFP!float)
481                     return;
482                 break;
483 
484             case Tfloat64:
485                 if (!isLosslesslyConvertibleToFP!double)
486                     return;
487                 break;
488 
489             case Tfloat80:
490                 if (!isLosslesslyConvertibleToFP!real_t)
491                     return;
492                 break;
493 
494             case Tpointer:
495                 //printf("type = %s\n", type.toBasetype()->toChars());
496                 //printf("t = %s\n", t.toBasetype()->toChars());
497                 if (ty == Tpointer && e.type.toBasetype().nextOf().ty == t.toBasetype().nextOf().ty)
498                 {
499                     /* Allow things like:
500                      *      const char* P = cast(char *)3;
501                      *      char* q = P;
502                      */
503                     break;
504                 }
505                 goto default;
506 
507             default:
508                 visit(cast(Expression)e);
509                 return;
510             }
511 
512             //printf("MATCH.convert\n");
513             result = MATCH.convert;
514         }
515 
516         override void visit(ErrorExp e)
517         {
518             // no match
519         }
520 
521         override void visit(NullExp e)
522         {
523             version (none)
524             {
525                 printf("NullExp::implicitConvTo(this=%s, type=%s, t=%s, committed = %d)\n", e.toChars(), e.type.toChars(), t.toChars(), e.committed);
526             }
527             if (e.type.equals(t))
528             {
529                 result = MATCH.exact;
530                 return;
531             }
532 
533             /* Allow implicit conversions from immutable to mutable|const,
534              * and mutable to immutable. It works because, after all, a null
535              * doesn't actually point to anything.
536              */
537             if (t.equivalent(e.type))
538             {
539                 result = MATCH.constant;
540                 return;
541             }
542 
543             visit(cast(Expression)e);
544         }
545 
546         override void visit(StructLiteralExp e)
547         {
548             version (none)
549             {
550                 printf("StructLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
551             }
552             visit(cast(Expression)e);
553             if (result != MATCH.nomatch)
554                 return;
555             if (e.type.ty == t.ty && e.type.ty == Tstruct && (cast(TypeStruct)e.type).sym == (cast(TypeStruct)t).sym)
556             {
557                 result = MATCH.constant;
558                 foreach (i, el; (*e.elements)[])
559                 {
560                     if (!el)
561                         continue;
562                     Type te = e.sd.fields[i].type.addMod(t.mod);
563                     MATCH m2 = el.implicitConvTo(te);
564                     //printf("\t%s => %s, match = %d\n", el.toChars(), te.toChars(), m2);
565                     if (m2 < result)
566                         result = m2;
567                 }
568             }
569         }
570 
571         override void visit(StringExp e)
572         {
573             version (none)
574             {
575                 printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n", e.toChars(), e.committed, e.type.toChars(), t.toChars());
576             }
577             if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid)
578                 return;
579 
580             if (!(e.type.ty == Tsarray || e.type.ty == Tarray || e.type.ty == Tpointer))
581                 return visit(cast(Expression)e);
582 
583             TY tyn = e.type.nextOf().ty;
584 
585             if (!tyn.isSomeChar)
586                 return visit(cast(Expression)e);
587 
588             switch (t.ty)
589             {
590             case Tsarray:
591                 if (e.type.ty == Tsarray)
592                 {
593                     TY tynto = t.nextOf().ty;
594                     if (tynto == tyn)
595                     {
596                         if ((cast(TypeSArray)e.type).dim.toInteger() == (cast(TypeSArray)t).dim.toInteger())
597                         {
598                             result = MATCH.exact;
599                         }
600                         return;
601                     }
602                     if (tynto.isSomeChar)
603                     {
604                         if (e.committed && tynto != tyn)
605                             return;
606                         size_t fromlen = e.numberOfCodeUnits(tynto);
607                         size_t tolen = cast(size_t)(cast(TypeSArray)t).dim.toInteger();
608                         if (tolen < fromlen)
609                             return;
610                         if (tolen != fromlen)
611                         {
612                             // implicit length extending
613                             result = MATCH.convert;
614                             return;
615                         }
616                     }
617                     if (!e.committed && tynto.isSomeChar)
618                     {
619                         result = MATCH.exact;
620                         return;
621                     }
622                 }
623                 else if (e.type.ty == Tarray)
624                 {
625                     TY tynto = t.nextOf().ty;
626                     if (tynto.isSomeChar)
627                     {
628                         if (e.committed && tynto != tyn)
629                             return;
630                         size_t fromlen = e.numberOfCodeUnits(tynto);
631                         size_t tolen = cast(size_t)(cast(TypeSArray)t).dim.toInteger();
632                         if (tolen < fromlen)
633                             return;
634                         if (tolen != fromlen)
635                         {
636                             // implicit length extending
637                             result = MATCH.convert;
638                             return;
639                         }
640                     }
641                     if (tynto == tyn)
642                     {
643                         result = MATCH.exact;
644                         return;
645                     }
646                     if (!e.committed && tynto.isSomeChar)
647                     {
648                         result = MATCH.exact;
649                         return;
650                     }
651                 }
652                 goto case; /+ fall through +/
653             case Tarray:
654             case Tpointer:
655                 Type tn = t.nextOf();
656                 MATCH m = MATCH.exact;
657                 if (e.type.nextOf().mod != tn.mod)
658                 {
659                     // https://issues.dlang.org/show_bug.cgi?id=16183
660                     if (!tn.isConst() && !tn.isImmutable())
661                         return;
662                     m = MATCH.constant;
663                 }
664                 if (!e.committed)
665                 {
666                     switch (tn.ty)
667                     {
668                     case Tchar:
669                         if (e.postfix == 'w' || e.postfix == 'd')
670                             m = MATCH.convert;
671                         result = m;
672                         return;
673                     case Twchar:
674                         if (e.postfix != 'w')
675                             m = MATCH.convert;
676                         result = m;
677                         return;
678                     case Tdchar:
679                         if (e.postfix != 'd')
680                             m = MATCH.convert;
681                         result = m;
682                         return;
683                     case Tenum:
684                         if ((cast(TypeEnum)tn).sym.isSpecial())
685                         {
686                             /* Allow string literal -> const(wchar_t)[]
687                              */
688                             if (TypeBasic tob = tn.toBasetype().isTypeBasic())
689                             result = tn.implicitConvTo(tob);
690                             return;
691                         }
692                         break;
693                     default:
694                         break;
695                     }
696                 }
697                 break;
698 
699             default:
700                 break;
701             }
702 
703             visit(cast(Expression)e);
704         }
705 
706         override void visit(ArrayLiteralExp e)
707         {
708             version (none)
709             {
710                 printf("ArrayLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
711             }
712             Type tb = t.toBasetype();
713             Type typeb = e.type.toBasetype();
714 
715             if ((tb.ty == Tarray || tb.ty == Tsarray) &&
716                 (typeb.ty == Tarray || typeb.ty == Tsarray))
717             {
718                 result = MATCH.exact;
719                 Type typen = typeb.nextOf().toBasetype();
720 
721                 if (auto tsa = tb.isTypeSArray())
722                 {
723                     if (e.elements.dim != tsa.dim.toInteger())
724                         result = MATCH.nomatch;
725                 }
726 
727                 Type telement = tb.nextOf();
728                 if (!e.elements.dim)
729                 {
730                     if (typen.ty != Tvoid)
731                         result = typen.implicitConvTo(telement);
732                 }
733                 else
734                 {
735                     if (e.basis)
736                     {
737                         MATCH m = e.basis.implicitConvTo(telement);
738                         if (m < result)
739                             result = m;
740                     }
741                     for (size_t i = 0; i < e.elements.dim; i++)
742                     {
743                         Expression el = (*e.elements)[i];
744                         if (result == MATCH.nomatch)
745                             break;
746                         if (!el)
747                             continue;
748                         MATCH m = el.implicitConvTo(telement);
749                         if (m < result)
750                             result = m; // remember worst match
751                     }
752                 }
753 
754                 if (!result)
755                     result = e.type.implicitConvTo(t);
756 
757                 return;
758             }
759             else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray))
760             {
761                 result = MATCH.exact;
762                 // Convert array literal to vector type
763                 TypeVector tv = tb.isTypeVector();
764                 TypeSArray tbase = tv.basetype.isTypeSArray();
765                 assert(tbase);
766                 const edim = e.elements.dim;
767                 const tbasedim = tbase.dim.toInteger();
768                 if (edim > tbasedim)
769                 {
770                     result = MATCH.nomatch;
771                     return;
772                 }
773 
774                 Type telement = tv.elementType();
775                 if (edim < tbasedim)
776                 {
777                     Expression el = typeb.nextOf.defaultInitLiteral(e.loc);
778                     MATCH m = el.implicitConvTo(telement);
779                     if (m < result)
780                         result = m; // remember worst match
781                 }
782                 foreach (el; (*e.elements)[])
783                 {
784                     MATCH m = el.implicitConvTo(telement);
785                     if (m < result)
786                         result = m; // remember worst match
787                     if (result == MATCH.nomatch)
788                         break; // no need to check for worse
789                 }
790                 return;
791             }
792 
793             visit(cast(Expression)e);
794         }
795 
796         override void visit(AssocArrayLiteralExp e)
797         {
798             auto taa = t.toBasetype().isTypeAArray();
799             Type typeb = e.type.toBasetype();
800 
801             if (!(taa && typeb.ty == Taarray))
802                 return visit(cast(Expression)e);
803 
804             result = MATCH.exact;
805             foreach (i, el; (*e.keys)[])
806             {
807                 MATCH m = el.implicitConvTo(taa.index);
808                 if (m < result)
809                     result = m; // remember worst match
810                 if (result == MATCH.nomatch)
811                     break; // no need to check for worse
812                 el = (*e.values)[i];
813                 m = el.implicitConvTo(taa.nextOf());
814                 if (m < result)
815                     result = m; // remember worst match
816                 if (result == MATCH.nomatch)
817                     break; // no need to check for worse
818             }
819         }
820 
821         override void visit(CallExp e)
822         {
823             enum LOG = false;
824             static if (LOG)
825             {
826                 printf("CallExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
827             }
828 
829             visit(cast(Expression)e);
830             if (result != MATCH.nomatch)
831                 return;
832 
833             /* Allow the result of strongly pure functions to
834              * convert to immutable
835              */
836             if (e.f && e.f.isReturnIsolated() &&
837                 (!global.params.vsafe ||        // lots of legacy code breaks with the following purity check
838                  e.f.isPure() >= PURE.strong ||
839                  // Special case exemption for Object.dup() which we assume is implemented correctly
840                  e.f.ident == Id.dup &&
841                  e.f.toParent2() == ClassDeclaration.object.toParent())
842                )
843             {
844                 result = e.type.immutableOf().implicitConvTo(t);
845                 if (result > MATCH.constant) // Match level is MATCH.constant at best.
846                     result = MATCH.constant;
847                 return;
848             }
849 
850             /* Conversion is 'const' conversion if:
851              * 1. function is pure (weakly pure is ok)
852              * 2. implicit conversion only fails because of mod bits
853              * 3. each function parameter can be implicitly converted to the mod bits
854              */
855             auto tf = (e.f ? e.f.type : e.e1.type).toBasetype().isTypeFunction();
856             if (!tf)
857                 return;
858 
859             if (tf.purity == PURE.impure)
860                 return;
861             if (e.f && e.f.isNested())
862                 return;
863 
864             /* See if fail only because of mod bits.
865              *
866              * https://issues.dlang.org/show_bug.cgi?id=14155
867              * All pure functions can access global immutable data.
868              * So the returned pointer may refer an immutable global data,
869              * and then the returned pointer that points non-mutable object
870              * cannot be unique pointer.
871              *
872              * Example:
873              *  immutable g;
874              *  static this() { g = 1; }
875              *  const(int*) foo() pure { return &g; }
876              *  void test() {
877              *    immutable(int*) ip = foo(); // OK
878              *    int* mp = foo();            // should be disallowed
879              *  }
880              */
881             if (e.type.immutableOf().implicitConvTo(t) < MATCH.constant && e.type.addMod(MODFlags.shared_).implicitConvTo(t) < MATCH.constant && e.type.implicitConvTo(t.addMod(MODFlags.shared_)) < MATCH.constant)
882             {
883                 return;
884             }
885             // Allow a conversion to immutable type, or
886             // conversions of mutable types between thread-local and shared.
887 
888             /* Get mod bits of what we're converting to
889              */
890             Type tb = t.toBasetype();
891             MOD mod = tb.mod;
892             if (tf.isref)
893             {
894             }
895             else
896             {
897                 if (Type ti = getIndirection(t))
898                     mod = ti.mod;
899             }
900             static if (LOG)
901             {
902                 printf("mod = x%x\n", mod);
903             }
904             if (mod & MODFlags.wild)
905                 return; // not sure what to do with this
906 
907             /* Apply mod bits to each function parameter,
908              * and see if we can convert the function argument to the modded type
909              */
910 
911             size_t nparams = tf.parameterList.length;
912             size_t j = tf.isDstyleVariadic(); // if TypeInfoArray was prepended
913             if (auto dve = e.e1.isDotVarExp())
914             {
915                 /* Treat 'this' as just another function argument
916                  */
917                 Type targ = dve.e1.type;
918                 if (targ.constConv(targ.castMod(mod)) == MATCH.nomatch)
919                     return;
920             }
921             foreach (const i; j .. e.arguments.dim)
922             {
923                 Expression earg = (*e.arguments)[i];
924                 Type targ = earg.type.toBasetype();
925                 static if (LOG)
926                 {
927                     printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
928                 }
929                 if (i - j < nparams)
930                 {
931                     Parameter fparam = tf.parameterList[i - j];
932                     if (fparam.storageClass & STC.lazy_)
933                         return; // not sure what to do with this
934                     Type tparam = fparam.type;
935                     if (!tparam)
936                         continue;
937                     if (fparam.storageClass & (STC.out_ | STC.ref_))
938                     {
939                         if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch)
940                             return;
941                         continue;
942                     }
943                 }
944                 static if (LOG)
945                 {
946                     printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
947                 }
948                 if (implicitMod(earg, targ, mod) == MATCH.nomatch)
949                     return;
950             }
951 
952             /* Success
953              */
954             result = MATCH.constant;
955         }
956 
957         override void visit(AddrExp e)
958         {
959             version (none)
960             {
961                 printf("AddrExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
962             }
963             result = e.type.implicitConvTo(t);
964             //printf("\tresult = %d\n", result);
965 
966             if (result != MATCH.nomatch)
967                 return;
968 
969             Type tb = t.toBasetype();
970             Type typeb = e.type.toBasetype();
971 
972             // Look for pointers to functions where the functions are overloaded.
973             if (e.e1.op == TOK.overloadSet &&
974                 (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
975             {
976                 OverExp eo = e.e1.isOverExp();
977                 FuncDeclaration f = null;
978                 foreach (s; eo.vars.a[])
979                 {
980                     FuncDeclaration f2 = s.isFuncDeclaration();
981                     assert(f2);
982                     if (f2.overloadExactMatch(tb.nextOf()))
983                     {
984                         if (f)
985                         {
986                             /* Error if match in more than one overload set,
987                              * even if one is a 'better' match than the other.
988                              */
989                             ScopeDsymbol.multiplyDefined(e.loc, f, f2);
990                         }
991                         else
992                             f = f2;
993                         result = MATCH.exact;
994                     }
995                 }
996             }
997 
998             if (e.e1.op == TOK.variable &&
999                 typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
1000                 tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
1001             {
1002                 /* I don't think this can ever happen -
1003                  * it should have been
1004                  * converted to a SymOffExp.
1005                  */
1006                 assert(0);
1007             }
1008 
1009             //printf("\tresult = %d\n", result);
1010         }
1011 
1012         override void visit(SymOffExp e)
1013         {
1014             version (none)
1015             {
1016                 printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1017             }
1018             result = e.type.implicitConvTo(t);
1019             //printf("\tresult = %d\n", result);
1020             if (result != MATCH.nomatch)
1021                 return;
1022 
1023             Type tb = t.toBasetype();
1024             Type typeb = e.type.toBasetype();
1025 
1026             // Look for pointers to functions where the functions are overloaded.
1027             if (typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
1028                 (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
1029             {
1030                 if (FuncDeclaration f = e.var.isFuncDeclaration())
1031                 {
1032                     f = f.overloadExactMatch(tb.nextOf());
1033                     if (f)
1034                     {
1035                         if ((tb.ty == Tdelegate && (f.needThis() || f.isNested())) ||
1036                             (tb.ty == Tpointer && !(f.needThis() || f.isNested())))
1037                         {
1038                             result = MATCH.exact;
1039                         }
1040                     }
1041                 }
1042             }
1043             //printf("\tresult = %d\n", result);
1044         }
1045 
1046         override void visit(DelegateExp e)
1047         {
1048             version (none)
1049             {
1050                 printf("DelegateExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1051             }
1052             result = e.type.implicitConvTo(t);
1053             if (result != MATCH.nomatch)
1054                 return;
1055 
1056             Type tb = t.toBasetype();
1057             Type typeb = e.type.toBasetype();
1058 
1059             // Look for pointers to functions where the functions are overloaded.
1060             if (typeb.ty == Tdelegate && tb.ty == Tdelegate)
1061             {
1062                 if (e.func && e.func.overloadExactMatch(tb.nextOf()))
1063                     result = MATCH.exact;
1064             }
1065         }
1066 
1067         override void visit(FuncExp e)
1068         {
1069             //printf("FuncExp::implicitConvTo type = %p %s, t = %s\n", e.type, e.type ? e.type.toChars() : NULL, t.toChars());
1070             MATCH m = e.matchType(t, null, null, 1);
1071             if (m > MATCH.nomatch)
1072             {
1073                 result = m;
1074                 return;
1075             }
1076             visit(cast(Expression)e);
1077         }
1078 
1079         override void visit(AndExp e)
1080         {
1081             visit(cast(Expression)e);
1082             if (result != MATCH.nomatch)
1083                 return;
1084 
1085             MATCH m1 = e.e1.implicitConvTo(t);
1086             MATCH m2 = e.e2.implicitConvTo(t);
1087 
1088             // Pick the worst match
1089             result = (m1 < m2) ? m1 : m2;
1090         }
1091 
1092         override void visit(OrExp e)
1093         {
1094             visit(cast(Expression)e);
1095             if (result != MATCH.nomatch)
1096                 return;
1097 
1098             MATCH m1 = e.e1.implicitConvTo(t);
1099             MATCH m2 = e.e2.implicitConvTo(t);
1100 
1101             // Pick the worst match
1102             result = (m1 < m2) ? m1 : m2;
1103         }
1104 
1105         override void visit(XorExp e)
1106         {
1107             visit(cast(Expression)e);
1108             if (result != MATCH.nomatch)
1109                 return;
1110 
1111             MATCH m1 = e.e1.implicitConvTo(t);
1112             MATCH m2 = e.e2.implicitConvTo(t);
1113 
1114             // Pick the worst match
1115             result = (m1 < m2) ? m1 : m2;
1116         }
1117 
1118         override void visit(CondExp e)
1119         {
1120             MATCH m1 = e.e1.implicitConvTo(t);
1121             MATCH m2 = e.e2.implicitConvTo(t);
1122             //printf("CondExp: m1 %d m2 %d\n", m1, m2);
1123 
1124             // Pick the worst match
1125             result = (m1 < m2) ? m1 : m2;
1126         }
1127 
1128         override void visit(CommaExp e)
1129         {
1130             e.e2.accept(this);
1131         }
1132 
1133         override void visit(CastExp e)
1134         {
1135             version (none)
1136             {
1137                 printf("CastExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1138             }
1139             result = e.type.implicitConvTo(t);
1140             if (result != MATCH.nomatch)
1141                 return;
1142 
1143             if (t.isintegral() && e.e1.type.isintegral() && e.e1.implicitConvTo(t) != MATCH.nomatch)
1144                 result = MATCH.convert;
1145             else
1146                 visit(cast(Expression)e);
1147         }
1148 
1149         override void visit(NewExp e)
1150         {
1151             version (none)
1152             {
1153                 printf("NewExp::implicitConvTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1154             }
1155             visit(cast(Expression)e);
1156             if (result != MATCH.nomatch)
1157                 return;
1158 
1159             /* Calling new() is like calling a pure function. We can implicitly convert the
1160              * return from new() to t using the same algorithm as in CallExp, with the function
1161              * 'arguments' being:
1162              *    thisexp
1163              *    newargs
1164              *    arguments
1165              *    .init
1166              * 'member' and 'allocator' need to be pure.
1167              */
1168 
1169             /* See if fail only because of mod bits
1170              */
1171             if (e.type.immutableOf().implicitConvTo(t.immutableOf()) == MATCH.nomatch)
1172                 return;
1173 
1174             /* Get mod bits of what we're converting to
1175              */
1176             Type tb = t.toBasetype();
1177             MOD mod = tb.mod;
1178             if (Type ti = getIndirection(t))
1179                 mod = ti.mod;
1180             static if (LOG)
1181             {
1182                 printf("mod = x%x\n", mod);
1183             }
1184             if (mod & MODFlags.wild)
1185                 return; // not sure what to do with this
1186 
1187             /* Apply mod bits to each argument,
1188              * and see if we can convert the argument to the modded type
1189              */
1190 
1191             if (e.thisexp)
1192             {
1193                 /* Treat 'this' as just another function argument
1194                  */
1195                 Type targ = e.thisexp.type;
1196                 if (targ.constConv(targ.castMod(mod)) == MATCH.nomatch)
1197                     return;
1198             }
1199 
1200             /* Check call to 'allocator', then 'member'
1201              */
1202             FuncDeclaration fd = e.allocator;
1203             for (int count = 0; count < 2; ++count, (fd = e.member))
1204             {
1205                 if (!fd)
1206                     continue;
1207                 if (fd.errors || fd.type.ty != Tfunction)
1208                     return; // error
1209                 TypeFunction tf = cast(TypeFunction)fd.type;
1210                 if (tf.purity == PURE.impure)
1211                     return; // impure
1212 
1213                 if (fd == e.member)
1214                 {
1215                     if (e.type.immutableOf().implicitConvTo(t) < MATCH.constant && e.type.addMod(MODFlags.shared_).implicitConvTo(t) < MATCH.constant && e.type.implicitConvTo(t.addMod(MODFlags.shared_)) < MATCH.constant)
1216                     {
1217                         return;
1218                     }
1219                     // Allow a conversion to immutable type, or
1220                     // conversions of mutable types between thread-local and shared.
1221                 }
1222 
1223                 Expressions* args = (fd == e.allocator) ? e.newargs : e.arguments;
1224 
1225                 size_t nparams = tf.parameterList.length;
1226                 // if TypeInfoArray was prepended
1227                 size_t j = tf.isDstyleVariadic();
1228                 for (size_t i = j; i < e.arguments.dim; ++i)
1229                 {
1230                     Expression earg = (*args)[i];
1231                     Type targ = earg.type.toBasetype();
1232                     static if (LOG)
1233                     {
1234                         printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
1235                     }
1236                     if (i - j < nparams)
1237                     {
1238                         Parameter fparam = tf.parameterList[i - j];
1239                         if (fparam.storageClass & STC.lazy_)
1240                             return; // not sure what to do with this
1241                         Type tparam = fparam.type;
1242                         if (!tparam)
1243                             continue;
1244                         if (fparam.storageClass & (STC.out_ | STC.ref_))
1245                         {
1246                             if (targ.constConv(tparam.castMod(mod)) == MATCH.nomatch)
1247                                 return;
1248                             continue;
1249                         }
1250                     }
1251                     static if (LOG)
1252                     {
1253                         printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
1254                     }
1255                     if (implicitMod(earg, targ, mod) == MATCH.nomatch)
1256                         return;
1257                 }
1258             }
1259 
1260             /* If no 'member', then construction is by simple assignment,
1261              * and just straight check 'arguments'
1262              */
1263             if (!e.member && e.arguments)
1264             {
1265                 for (size_t i = 0; i < e.arguments.dim; ++i)
1266                 {
1267                     Expression earg = (*e.arguments)[i];
1268                     if (!earg) // https://issues.dlang.org/show_bug.cgi?id=14853
1269                                // if it's on overlapped field
1270                         continue;
1271                     Type targ = earg.type.toBasetype();
1272                     static if (LOG)
1273                     {
1274                         printf("[%d] earg: %s, targ: %s\n", cast(int)i, earg.toChars(), targ.toChars());
1275                         printf("[%d] earg: %s, targm: %s\n", cast(int)i, earg.toChars(), targ.addMod(mod).toChars());
1276                     }
1277                     if (implicitMod(earg, targ, mod) == MATCH.nomatch)
1278                         return;
1279                 }
1280             }
1281 
1282             /* Consider the .init expression as an argument
1283              */
1284             Type ntb = e.newtype.toBasetype();
1285             if (ntb.ty == Tarray)
1286                 ntb = ntb.nextOf().toBasetype();
1287             if (ntb.ty == Tstruct)
1288             {
1289                 // Don't allow nested structs - uplevel reference may not be convertible
1290                 StructDeclaration sd = (cast(TypeStruct)ntb).sym;
1291                 sd.size(e.loc); // resolve any forward references
1292                 if (sd.isNested())
1293                     return;
1294             }
1295             if (ntb.isZeroInit(e.loc))
1296             {
1297                 /* Zeros are implicitly convertible, except for special cases.
1298                  */
1299                 if (ntb.ty == Tclass)
1300                 {
1301                     /* With new() must look at the class instance initializer.
1302                      */
1303                     ClassDeclaration cd = (cast(TypeClass)ntb).sym;
1304 
1305                     cd.size(e.loc); // resolve any forward references
1306 
1307                     if (cd.isNested())
1308                         return; // uplevel reference may not be convertible
1309 
1310                     assert(!cd.isInterfaceDeclaration());
1311 
1312                     struct ClassCheck
1313                     {
1314                         extern (C++) static bool convertible(Loc loc, ClassDeclaration cd, MOD mod)
1315                         {
1316                             for (size_t i = 0; i < cd.fields.dim; i++)
1317                             {
1318                                 VarDeclaration v = cd.fields[i];
1319                                 Initializer _init = v._init;
1320                                 if (_init)
1321                                 {
1322                                     if (_init.isVoidInitializer())
1323                                     {
1324                                     }
1325                                     else if (ExpInitializer ei = _init.isExpInitializer())
1326                                     {
1327                                         Type tb = v.type.toBasetype();
1328                                         if (implicitMod(ei.exp, tb, mod) == MATCH.nomatch)
1329                                             return false;
1330                                     }
1331                                     else
1332                                     {
1333                                         /* Enhancement: handle StructInitializer and ArrayInitializer
1334                                          */
1335                                         return false;
1336                                     }
1337                                 }
1338                                 else if (!v.type.isZeroInit(loc))
1339                                     return false;
1340                             }
1341                             return cd.baseClass ? convertible(loc, cd.baseClass, mod) : true;
1342                         }
1343                     }
1344 
1345                     if (!ClassCheck.convertible(e.loc, cd, mod))
1346                         return;
1347                 }
1348             }
1349             else
1350             {
1351                 Expression earg = e.newtype.defaultInitLiteral(e.loc);
1352                 Type targ = e.newtype.toBasetype();
1353 
1354                 if (implicitMod(earg, targ, mod) == MATCH.nomatch)
1355                     return;
1356             }
1357 
1358             /* Success
1359              */
1360             result = MATCH.constant;
1361         }
1362 
1363         override void visit(SliceExp e)
1364         {
1365             //printf("SliceExp::implicitConvTo e = %s, type = %s\n", e.toChars(), e.type.toChars());
1366             visit(cast(Expression)e);
1367             if (result != MATCH.nomatch)
1368                 return;
1369 
1370             Type tb = t.toBasetype();
1371             Type typeb = e.type.toBasetype();
1372 
1373             if (tb.ty == Tsarray && typeb.ty == Tarray)
1374             {
1375                 typeb = toStaticArrayType(e);
1376                 if (typeb)
1377                     result = typeb.implicitConvTo(t);
1378                 return;
1379             }
1380 
1381             /* If the only reason it won't convert is because of the mod bits,
1382              * then test for conversion by seeing if e1 can be converted with those
1383              * same mod bits.
1384              */
1385             Type t1b = e.e1.type.toBasetype();
1386             if (tb.ty == Tarray && typeb.equivalent(tb))
1387             {
1388                 Type tbn = tb.nextOf();
1389                 Type tx = null;
1390 
1391                 /* If e.e1 is dynamic array or pointer, the uniqueness of e.e1
1392                  * is equivalent with the uniqueness of the referred data. And in here
1393                  * we can have arbitrary typed reference for that.
1394                  */
1395                 if (t1b.ty == Tarray)
1396                     tx = tbn.arrayOf();
1397                 if (t1b.ty == Tpointer)
1398                     tx = tbn.pointerTo();
1399 
1400                 /* If e.e1 is static array, at least it should be an rvalue.
1401                  * If not, e.e1 is a reference, and its uniqueness does not link
1402                  * to the uniqueness of the referred data.
1403                  */
1404                 if (t1b.ty == Tsarray && !e.e1.isLvalue())
1405                     tx = tbn.sarrayOf(t1b.size() / tbn.size());
1406 
1407                 if (tx)
1408                 {
1409                     result = e.e1.implicitConvTo(tx);
1410                     if (result > MATCH.constant) // Match level is MATCH.constant at best.
1411                         result = MATCH.constant;
1412                 }
1413             }
1414 
1415             // Enhancement 10724
1416             if (tb.ty == Tpointer && e.e1.op == TOK.string_)
1417                 e.e1.accept(this);
1418         }
1419     }
1420 
1421     scope ImplicitConvTo v = new ImplicitConvTo(t);
1422     e.accept(v);
1423     return v.result;
1424 }
1425 
1426 Type toStaticArrayType(SliceExp e)
1427 {
1428     if (e.lwr && e.upr)
1429     {
1430         // For the following code to work, e should be optimized beforehand.
1431         // (eg. $ in lwr and upr should be already resolved, if possible)
1432         Expression lwr = e.lwr.optimize(WANTvalue);
1433         Expression upr = e.upr.optimize(WANTvalue);
1434         if (lwr.isConst() && upr.isConst())
1435         {
1436             size_t len = cast(size_t)(upr.toUInteger() - lwr.toUInteger());
1437             return e.type.toBasetype().nextOf().sarrayOf(len);
1438         }
1439     }
1440     else
1441     {
1442         Type t1b = e.e1.type.toBasetype();
1443         if (t1b.ty == Tsarray)
1444             return t1b;
1445     }
1446     return null;
1447 }
1448 
1449 // Try casting the alias this member. Return the expression if it succeeds, null otherwise.
1450 private Expression tryAliasThisCast(Expression e, Scope* sc, Type tob, Type t1b, Type t)
1451 {
1452     Expression result;
1453     AggregateDeclaration t1ad = isAggregate(t1b);
1454     if (!t1ad)
1455         return null;
1456 
1457     AggregateDeclaration toad = isAggregate(tob);
1458     if (t1ad == toad || !t1ad.aliasthis)
1459         return null;
1460 
1461     /* Forward the cast to our alias this member, rewrite to:
1462      *   cast(to)e1.aliasthis
1463      */
1464     result = resolveAliasThis(sc, e);
1465     const errors = global.startGagging();
1466     result = result.castTo(sc, t);
1467     return global.endGagging(errors) ? null : result;
1468 }
1469 
1470 /**************************************
1471  * Do an explicit cast.
1472  * Assume that the 'this' expression does not have any indirections.
1473  */
1474 Expression castTo(Expression e, Scope* sc, Type t)
1475 {
1476     extern (C++) final class CastTo : Visitor
1477     {
1478         alias visit = Visitor.visit;
1479     public:
1480         Type t;
1481         Scope* sc;
1482         Expression result;
1483 
1484         extern (D) this(Scope* sc, Type t)
1485         {
1486             this.sc = sc;
1487             this.t = t;
1488         }
1489 
1490         override void visit(Expression e)
1491         {
1492             //printf("Expression::castTo(this=%s, t=%s)\n", e.toChars(), t.toChars());
1493             version (none)
1494             {
1495                 printf("Expression::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
1496             }
1497             if (e.type.equals(t))
1498             {
1499                 result = e;
1500                 return;
1501             }
1502             if (e.op == TOK.variable)
1503             {
1504                 VarDeclaration v = (cast(VarExp)e).var.isVarDeclaration();
1505                 if (v && v.storage_class & STC.manifest)
1506                 {
1507                     result = e.ctfeInterpret();
1508                     /* https://issues.dlang.org/show_bug.cgi?id=18236
1509                      *
1510                      * The expression returned by ctfeInterpret points
1511                      * to the line where the manifest constant was declared
1512                      * so we need to update the location before trying to cast
1513                      */
1514                     result.loc = e.loc;
1515                     result = result.castTo(sc, t);
1516                     return;
1517                 }
1518             }
1519 
1520             Type tob = t.toBasetype();
1521             Type t1b = e.type.toBasetype();
1522             if (tob.equals(t1b))
1523             {
1524                 result = e.copy(); // because of COW for assignment to e.type
1525                 result.type = t;
1526                 return;
1527             }
1528 
1529             /* Make semantic error against invalid cast between concrete types.
1530              * Assume that 'e' is never be any placeholder expressions.
1531              * The result of these checks should be consistent with CastExp::toElem().
1532              */
1533 
1534             // Fat Value types
1535             const(bool) tob_isFV = (tob.ty == Tstruct || tob.ty == Tsarray);
1536             const(bool) t1b_isFV = (t1b.ty == Tstruct || t1b.ty == Tsarray);
1537 
1538             // Fat Reference types
1539             const(bool) tob_isFR = (tob.ty == Tarray || tob.ty == Tdelegate);
1540             const(bool) t1b_isFR = (t1b.ty == Tarray || t1b.ty == Tdelegate);
1541 
1542             // Reference types
1543             const(bool) tob_isR = (tob_isFR || tob.ty == Tpointer || tob.ty == Taarray || tob.ty == Tclass);
1544             const(bool) t1b_isR = (t1b_isFR || t1b.ty == Tpointer || t1b.ty == Taarray || t1b.ty == Tclass);
1545 
1546             // Arithmetic types (== valueable basic types)
1547             const(bool) tob_isA = (tob.isintegral() || tob.isfloating());
1548             const(bool) t1b_isA = (t1b.isintegral() || t1b.isfloating());
1549 
1550             bool hasAliasThis;
1551             if (AggregateDeclaration t1ad = isAggregate(t1b))
1552             {
1553                 AggregateDeclaration toad = isAggregate(tob);
1554                 if (t1ad != toad && t1ad.aliasthis)
1555                 {
1556                     if (t1b.ty == Tclass && tob.ty == Tclass)
1557                     {
1558                         ClassDeclaration t1cd = t1b.isClassHandle();
1559                         ClassDeclaration tocd = tob.isClassHandle();
1560                         int offset;
1561                         if (tocd.isBaseOf(t1cd, &offset))
1562                             goto Lok;
1563                     }
1564                     hasAliasThis = true;
1565                 }
1566             }
1567             else if (tob.ty == Tvector && t1b.ty != Tvector)
1568             {
1569                 //printf("test1 e = %s, e.type = %s, tob = %s\n", e.toChars(), e.type.toChars(), tob.toChars());
1570                 TypeVector tv = cast(TypeVector)tob;
1571                 result = new CastExp(e.loc, e, tv.elementType());
1572                 result = new VectorExp(e.loc, result, tob);
1573                 result = result.expressionSemantic(sc);
1574                 return;
1575             }
1576             else if (tob.ty != Tvector && t1b.ty == Tvector)
1577             {
1578                 // T[n] <-- __vector(U[m])
1579                 if (tob.ty == Tsarray)
1580                 {
1581                     if (t1b.size(e.loc) == tob.size(e.loc))
1582                         goto Lok;
1583                 }
1584                 goto Lfail;
1585             }
1586             else if (t1b.implicitConvTo(tob) == MATCH.constant && t.equals(e.type.constOf()))
1587             {
1588                 result = e.copy();
1589                 result.type = t;
1590                 return;
1591             }
1592 
1593             // arithmetic values vs. other arithmetic values
1594             // arithmetic values vs. T*
1595             if (tob_isA && (t1b_isA || t1b.ty == Tpointer) || t1b_isA && (tob_isA || tob.ty == Tpointer))
1596             {
1597                 goto Lok;
1598             }
1599 
1600             // arithmetic values vs. references or fat values
1601             if (tob_isA && (t1b_isR || t1b_isFV) || t1b_isA && (tob_isR || tob_isFV))
1602             {
1603                 goto Lfail;
1604             }
1605 
1606             // Bugzlla 3133: A cast between fat values is possible only when the sizes match.
1607             if (tob_isFV && t1b_isFV)
1608             {
1609                 if (hasAliasThis)
1610                 {
1611                     result = tryAliasThisCast(e, sc, tob, t1b, t);
1612                     if (result)
1613                         return;
1614                 }
1615 
1616                 if (t1b.size(e.loc) == tob.size(e.loc))
1617                     goto Lok;
1618 
1619                 auto ts = toAutoQualChars(e.type, t);
1620                 e.error("cannot cast expression `%s` of type `%s` to `%s` because of different sizes",
1621                     e.toChars(), ts[0], ts[1]);
1622                 result = new ErrorExp();
1623                 return;
1624             }
1625 
1626             // Fat values vs. null or references
1627             if (tob_isFV && (t1b.ty == Tnull || t1b_isR) || t1b_isFV && (tob.ty == Tnull || tob_isR))
1628             {
1629                 if (tob.ty == Tpointer && t1b.ty == Tsarray)
1630                 {
1631                     // T[n] sa;
1632                     // cast(U*)sa; // ==> cast(U*)sa.ptr;
1633                     result = new AddrExp(e.loc, e, t);
1634                     return;
1635                 }
1636                 if (tob.ty == Tarray && t1b.ty == Tsarray)
1637                 {
1638                     // T[n] sa;
1639                     // cast(U[])sa; // ==> cast(U[])sa[];
1640                     d_uns64 fsize = t1b.nextOf().size();
1641                     d_uns64 tsize = tob.nextOf().size();
1642                     if (((cast(TypeSArray)t1b).dim.toInteger() * fsize) % tsize != 0)
1643                     {
1644                         // copied from sarray_toDarray() in e2ir.c
1645                         e.error("cannot cast expression `%s` of type `%s` to `%s` since sizes don't line up", e.toChars(), e.type.toChars(), t.toChars());
1646                         result = new ErrorExp();
1647                         return;
1648                     }
1649                     goto Lok;
1650                 }
1651                 goto Lfail;
1652             }
1653 
1654             /* For references, any reinterpret casts are allowed to same 'ty' type.
1655              *      T* to U*
1656              *      R1 function(P1) to R2 function(P2)
1657              *      R1 delegate(P1) to R2 delegate(P2)
1658              *      T[] to U[]
1659              *      V1[K1] to V2[K2]
1660              *      class/interface A to B  (will be a dynamic cast if possible)
1661              */
1662             if (tob.ty == t1b.ty && tob_isR && t1b_isR)
1663                 goto Lok;
1664 
1665             // typeof(null) <-- non-null references or values
1666             if (tob.ty == Tnull && t1b.ty != Tnull)
1667                 goto Lfail; // https://issues.dlang.org/show_bug.cgi?id=14629
1668             // typeof(null) --> non-null references or arithmetic values
1669             if (t1b.ty == Tnull && tob.ty != Tnull)
1670                 goto Lok;
1671 
1672             // Check size mismatch of references.
1673             // Tarray and Tdelegate are (void*).sizeof*2, but others have (void*).sizeof.
1674             if (tob_isFR && t1b_isR || t1b_isFR && tob_isR)
1675             {
1676                 if (tob.ty == Tpointer && t1b.ty == Tarray)
1677                 {
1678                     // T[] da;
1679                     // cast(U*)da; // ==> cast(U*)da.ptr;
1680                     goto Lok;
1681                 }
1682                 if (tob.ty == Tpointer && t1b.ty == Tdelegate)
1683                 {
1684                     // void delegate() dg;
1685                     // cast(U*)dg; // ==> cast(U*)dg.ptr;
1686                     // Note that it happens even when U is a Tfunction!
1687                     e.deprecation("casting from %s to %s is deprecated", e.type.toChars(), t.toChars());
1688                     goto Lok;
1689                 }
1690                 goto Lfail;
1691             }
1692 
1693             if (t1b.ty == Tvoid && tob.ty != Tvoid)
1694             {
1695             Lfail:
1696                 /* if the cast cannot be performed, maybe there is an alias
1697                  * this that can be used for casting.
1698                  */
1699                 if (hasAliasThis)
1700                 {
1701                     result = tryAliasThisCast(e, sc, tob, t1b, t);
1702                     if (result)
1703                         return;
1704                 }
1705                 e.error("cannot cast expression `%s` of type `%s` to `%s`", e.toChars(), e.type.toChars(), t.toChars());
1706                 result = new ErrorExp();
1707                 return;
1708             }
1709 
1710         Lok:
1711             result = new CastExp(e.loc, e, t);
1712             result.type = t; // Don't call semantic()
1713             //printf("Returning: %s\n", result.toChars());
1714         }
1715 
1716         override void visit(ErrorExp e)
1717         {
1718             result = e;
1719         }
1720 
1721         override void visit(RealExp e)
1722         {
1723             if (!e.type.equals(t))
1724             {
1725                 if ((e.type.isreal() && t.isreal()) || (e.type.isimaginary() && t.isimaginary()))
1726                 {
1727                     result = e.copy();
1728                     result.type = t;
1729                 }
1730                 else
1731                     visit(cast(Expression)e);
1732                 return;
1733             }
1734             result = e;
1735         }
1736 
1737         override void visit(ComplexExp e)
1738         {
1739             if (!e.type.equals(t))
1740             {
1741                 if (e.type.iscomplex() && t.iscomplex())
1742                 {
1743                     result = e.copy();
1744                     result.type = t;
1745                 }
1746                 else
1747                     visit(cast(Expression)e);
1748                 return;
1749             }
1750             result = e;
1751         }
1752 
1753         override void visit(NullExp e)
1754         {
1755             //printf("NullExp::castTo(t = %s) %s\n", t.toChars(), toChars());
1756             visit(cast(Expression)e);
1757             if (result.op == TOK.null_)
1758             {
1759                 NullExp ex = cast(NullExp)result;
1760                 ex.committed = 1;
1761                 return;
1762             }
1763         }
1764 
1765         override void visit(StructLiteralExp e)
1766         {
1767             visit(cast(Expression)e);
1768             if (result.op == TOK.structLiteral)
1769                 (cast(StructLiteralExp)result).stype = t; // commit type
1770         }
1771 
1772         override void visit(StringExp e)
1773         {
1774             /* This follows copy-on-write; any changes to 'this'
1775              * will result in a copy.
1776              * The this.string member is considered immutable.
1777              */
1778             int copied = 0;
1779 
1780             //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t.toChars(), e.toChars(), e.committed);
1781 
1782             if (!e.committed && t.ty == Tpointer && t.nextOf().ty == Tvoid)
1783             {
1784                 e.error("cannot convert string literal to `void*`");
1785                 result = new ErrorExp();
1786                 return;
1787             }
1788 
1789             StringExp se = e;
1790             if (!e.committed)
1791             {
1792                 se = cast(StringExp)e.copy();
1793                 se.committed = 1;
1794                 copied = 1;
1795             }
1796 
1797             if (e.type.equals(t))
1798             {
1799                 result = se;
1800                 return;
1801             }
1802 
1803             Type tb = t.toBasetype();
1804             Type typeb = e.type.toBasetype();
1805 
1806             //printf("\ttype = %s\n", e.type.toChars());
1807             if (tb.ty == Tdelegate && typeb.ty != Tdelegate)
1808             {
1809                 visit(cast(Expression)e);
1810                 return;
1811             }
1812 
1813             if (typeb.equals(tb))
1814             {
1815                 if (!copied)
1816                 {
1817                     se = cast(StringExp)e.copy();
1818                     copied = 1;
1819                 }
1820                 se.type = t;
1821                 result = se;
1822                 return;
1823             }
1824 
1825             /* Handle reinterpret casts:
1826              *  cast(wchar[3])"abcd"c --> [\u6261, \u6463, \u0000]
1827              *  cast(wchar[2])"abcd"c --> [\u6261, \u6463]
1828              *  cast(wchar[1])"abcd"c --> [\u6261]
1829              *  cast(char[4])"a" --> ['a', 0, 0, 0]
1830              */
1831             if (e.committed && tb.ty == Tsarray && typeb.ty == Tarray)
1832             {
1833                 se = cast(StringExp)e.copy();
1834                 d_uns64 szx = tb.nextOf().size();
1835                 assert(szx <= 255);
1836                 se.sz = cast(ubyte)szx;
1837                 se.len = cast(size_t)(cast(TypeSArray)tb).dim.toInteger();
1838                 se.committed = 1;
1839                 se.type = t;
1840 
1841                 /* If larger than source, pad with zeros.
1842                  */
1843                 const fullSize = (se.len + 1) * se.sz; // incl. terminating 0
1844                 if (fullSize > (e.len + 1) * e.sz)
1845                 {
1846                     void* s = mem.xmalloc(fullSize);
1847                     const srcSize = e.len * e.sz;
1848                     const data = se.peekData();
1849                     memcpy(s, data.ptr, srcSize);
1850                     memset(s + srcSize, 0, fullSize - srcSize);
1851                     se.setData(s, se.len, se.sz);
1852                 }
1853                 result = se;
1854                 return;
1855             }
1856 
1857             if (tb.ty != Tsarray && tb.ty != Tarray && tb.ty != Tpointer)
1858             {
1859                 if (!copied)
1860                 {
1861                     se = cast(StringExp)e.copy();
1862                     copied = 1;
1863                 }
1864                 goto Lcast;
1865             }
1866             if (typeb.ty != Tsarray && typeb.ty != Tarray && typeb.ty != Tpointer)
1867             {
1868                 if (!copied)
1869                 {
1870                     se = cast(StringExp)e.copy();
1871                     copied = 1;
1872                 }
1873                 goto Lcast;
1874             }
1875 
1876             if (typeb.nextOf().size() == tb.nextOf().size())
1877             {
1878                 if (!copied)
1879                 {
1880                     se = cast(StringExp)e.copy();
1881                     copied = 1;
1882                 }
1883                 if (tb.ty == Tsarray)
1884                     goto L2; // handle possible change in static array dimension
1885                 se.type = t;
1886                 result = se;
1887                 return;
1888             }
1889 
1890             if (e.committed)
1891                 goto Lcast;
1892 
1893             auto X(T, U)(T tf, U tt)
1894             {
1895                 return (cast(int)tf * 256 + cast(int)tt);
1896             }
1897 
1898             {
1899                 OutBuffer buffer;
1900                 size_t newlen = 0;
1901                 int tfty = typeb.nextOf().toBasetype().ty;
1902                 int ttty = tb.nextOf().toBasetype().ty;
1903                 switch (X(tfty, ttty))
1904                 {
1905                 case X(Tchar, Tchar):
1906                 case X(Twchar, Twchar):
1907                 case X(Tdchar, Tdchar):
1908                     break;
1909 
1910                 case X(Tchar, Twchar):
1911                     for (size_t u = 0; u < e.len;)
1912                     {
1913                         dchar c;
1914                         if (const s = utf_decodeChar(se.peekString(), u, c))
1915                             e.error("%.*s", cast(int)s.length, s.ptr);
1916                         else
1917                             buffer.writeUTF16(c);
1918                     }
1919                     newlen = buffer.length / 2;
1920                     buffer.writeUTF16(0);
1921                     goto L1;
1922 
1923                 case X(Tchar, Tdchar):
1924                     for (size_t u = 0; u < e.len;)
1925                     {
1926                         dchar c;
1927                         if (const s = utf_decodeChar(se.peekString(), u, c))
1928                             e.error("%.*s", cast(int)s.length, s.ptr);
1929                         buffer.write4(c);
1930                         newlen++;
1931                     }
1932                     buffer.write4(0);
1933                     goto L1;
1934 
1935                 case X(Twchar, Tchar):
1936                     for (size_t u = 0; u < e.len;)
1937                     {
1938                         dchar c;
1939                         if (const s = utf_decodeWchar(se.peekWstring(), u, c))
1940                             e.error("%.*s", cast(int)s.length, s.ptr);
1941                         else
1942                             buffer.writeUTF8(c);
1943                     }
1944                     newlen = buffer.length;
1945                     buffer.writeUTF8(0);
1946                     goto L1;
1947 
1948                 case X(Twchar, Tdchar):
1949                     for (size_t u = 0; u < e.len;)
1950                     {
1951                         dchar c;
1952                         if (const s = utf_decodeWchar(se.peekWstring(), u, c))
1953                             e.error("%.*s", cast(int)s.length, s.ptr);
1954                         buffer.write4(c);
1955                         newlen++;
1956                     }
1957                     buffer.write4(0);
1958                     goto L1;
1959 
1960                 case X(Tdchar, Tchar):
1961                     for (size_t u = 0; u < e.len; u++)
1962                     {
1963                         uint c = se.peekDstring()[u];
1964                         if (!utf_isValidDchar(c))
1965                             e.error("invalid UCS-32 char \\U%08x", c);
1966                         else
1967                             buffer.writeUTF8(c);
1968                         newlen++;
1969                     }
1970                     newlen = buffer.length;
1971                     buffer.writeUTF8(0);
1972                     goto L1;
1973 
1974                 case X(Tdchar, Twchar):
1975                     for (size_t u = 0; u < e.len; u++)
1976                     {
1977                         uint c = se.peekDstring()[u];
1978                         if (!utf_isValidDchar(c))
1979                             e.error("invalid UCS-32 char \\U%08x", c);
1980                         else
1981                             buffer.writeUTF16(c);
1982                         newlen++;
1983                     }
1984                     newlen = buffer.length / 2;
1985                     buffer.writeUTF16(0);
1986                     goto L1;
1987 
1988                 L1:
1989                     if (!copied)
1990                     {
1991                         se = cast(StringExp)e.copy();
1992                         copied = 1;
1993                     }
1994 
1995                     {
1996                         d_uns64 szx = tb.nextOf().size();
1997                         assert(szx <= 255);
1998                         se.setData(buffer.extractSlice().ptr, newlen, cast(ubyte)szx);
1999                     }
2000                     break;
2001 
2002                 default:
2003                     assert(typeb.nextOf().size() != tb.nextOf().size());
2004                     goto Lcast;
2005                 }
2006             }
2007         L2:
2008             assert(copied);
2009 
2010             // See if need to truncate or extend the literal
2011             if (tb.ty == Tsarray)
2012             {
2013                 size_t dim2 = cast(size_t)(cast(TypeSArray)tb).dim.toInteger();
2014                 //printf("dim from = %d, to = %d\n", (int)se.len, (int)dim2);
2015 
2016                 // Changing dimensions
2017                 if (dim2 != se.len)
2018                 {
2019                     // Copy when changing the string literal
2020                     const newsz = se.sz;
2021                     const d = (dim2 < se.len) ? dim2 : se.len;
2022                     void* s = mem.xmalloc((dim2 + 1) * newsz);
2023                     memcpy(s, se.peekData().ptr, d * newsz);
2024                     // Extend with 0, add terminating 0
2025                     memset(s + d * newsz, 0, (dim2 + 1 - d) * newsz);
2026                     se.setData(s, dim2, newsz);
2027                 }
2028             }
2029             se.type = t;
2030             result = se;
2031             return;
2032 
2033         Lcast:
2034             result = new CastExp(e.loc, se, t);
2035             result.type = t; // so semantic() won't be run on e
2036         }
2037 
2038         override void visit(AddrExp e)
2039         {
2040             version (none)
2041             {
2042                 printf("AddrExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
2043             }
2044             result = e;
2045 
2046             Type tb = t.toBasetype();
2047             Type typeb = e.type.toBasetype();
2048 
2049             if (tb.equals(typeb))
2050             {
2051                 result = e.copy();
2052                 result.type = t;
2053                 return;
2054             }
2055 
2056             // Look for pointers to functions where the functions are overloaded.
2057             if (e.e1.op == TOK.overloadSet &&
2058                 (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
2059             {
2060                 OverExp eo = cast(OverExp)e.e1;
2061                 FuncDeclaration f = null;
2062                 for (size_t i = 0; i < eo.vars.a.dim; i++)
2063                 {
2064                     auto s = eo.vars.a[i];
2065                     auto f2 = s.isFuncDeclaration();
2066                     assert(f2);
2067                     if (f2.overloadExactMatch(tb.nextOf()))
2068                     {
2069                         if (f)
2070                         {
2071                             /* Error if match in more than one overload set,
2072                              * even if one is a 'better' match than the other.
2073                              */
2074                             ScopeDsymbol.multiplyDefined(e.loc, f, f2);
2075                         }
2076                         else
2077                             f = f2;
2078                     }
2079                 }
2080                 if (f)
2081                 {
2082                     f.tookAddressOf++;
2083                     auto se = new SymOffExp(e.loc, f, 0, false);
2084                     se.expressionSemantic(sc);
2085                     // Let SymOffExp::castTo() do the heavy lifting
2086                     visit(se);
2087                     return;
2088                 }
2089             }
2090 
2091             if (e.e1.op == TOK.variable &&
2092                 typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
2093                 tb.ty == Tpointer && tb.nextOf().ty == Tfunction)
2094             {
2095                 auto ve = cast(VarExp)e.e1;
2096                 auto f = ve.var.isFuncDeclaration();
2097                 if (f)
2098                 {
2099                     assert(f.isImportedSymbol());
2100                     f = f.overloadExactMatch(tb.nextOf());
2101                     if (f)
2102                     {
2103                         result = new VarExp(e.loc, f, false);
2104                         result.type = f.type;
2105                         result = new AddrExp(e.loc, result, t);
2106                         return;
2107                     }
2108                 }
2109             }
2110 
2111             if (auto f = isFuncAddress(e))
2112             {
2113                 if (f.checkForwardRef(e.loc))
2114                 {
2115                     result = new ErrorExp();
2116                     return;
2117                 }
2118             }
2119 
2120             visit(cast(Expression)e);
2121         }
2122 
2123         override void visit(TupleExp e)
2124         {
2125             if (e.type.equals(t))
2126             {
2127                 result = e;
2128                 return;
2129             }
2130 
2131             TupleExp te = cast(TupleExp)e.copy();
2132             te.e0 = e.e0 ? e.e0.copy() : null;
2133             te.exps = e.exps.copy();
2134             for (size_t i = 0; i < te.exps.dim; i++)
2135             {
2136                 Expression ex = (*te.exps)[i];
2137                 ex = ex.castTo(sc, t);
2138                 (*te.exps)[i] = ex;
2139             }
2140             result = te;
2141 
2142             /* Questionable behavior: In here, result.type is not set to t.
2143              * Therefoe:
2144              *  TypeTuple!(int, int) values;
2145              *  auto values2 = cast(long)values;
2146              *  // typeof(values2) == TypeTuple!(int, int) !!
2147              *
2148              * Only when the casted tuple is immediately expanded, it would work.
2149              *  auto arr = [cast(long)values];
2150              *  // typeof(arr) == long[]
2151              */
2152         }
2153 
2154         override void visit(ArrayLiteralExp e)
2155         {
2156             version (none)
2157             {
2158                 printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars());
2159             }
2160 
2161             ArrayLiteralExp ae = e;
2162 
2163             Type tb = t.toBasetype();
2164             if (tb.ty == Tarray && global.params.vsafe)
2165             {
2166                 if (checkArrayLiteralEscape(sc, ae, false))
2167                 {
2168                     result = new ErrorExp();
2169                     return;
2170                 }
2171             }
2172 
2173             if (e.type == t)
2174             {
2175                 result = e;
2176                 return;
2177             }
2178             Type typeb = e.type.toBasetype();
2179 
2180             if ((tb.ty == Tarray || tb.ty == Tsarray) &&
2181                 (typeb.ty == Tarray || typeb.ty == Tsarray))
2182             {
2183                 if (tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid)
2184                 {
2185                     // Don't do anything to cast non-void[] to void[]
2186                 }
2187                 else if (typeb.ty == Tsarray && typeb.nextOf().toBasetype().ty == Tvoid)
2188                 {
2189                     // Don't do anything for casting void[n] to others
2190                 }
2191                 else
2192                 {
2193                     if (tb.ty == Tsarray)
2194                     {
2195                         TypeSArray tsa = cast(TypeSArray)tb;
2196                         if (e.elements.dim != tsa.dim.toInteger())
2197                             goto L1;
2198                     }
2199 
2200                     ae = cast(ArrayLiteralExp)e.copy();
2201                     if (e.basis)
2202                         ae.basis = e.basis.castTo(sc, tb.nextOf());
2203                     ae.elements = e.elements.copy();
2204                     for (size_t i = 0; i < e.elements.dim; i++)
2205                     {
2206                         Expression ex = (*e.elements)[i];
2207                         if (!ex)
2208                             continue;
2209                         ex = ex.castTo(sc, tb.nextOf());
2210                         (*ae.elements)[i] = ex;
2211                     }
2212                     ae.type = t;
2213                     result = ae;
2214                     return;
2215                 }
2216             }
2217             else if (tb.ty == Tpointer && typeb.ty == Tsarray)
2218             {
2219                 Type tp = typeb.nextOf().pointerTo();
2220                 if (!tp.equals(ae.type))
2221                 {
2222                     ae = cast(ArrayLiteralExp)e.copy();
2223                     ae.type = tp;
2224                 }
2225             }
2226             else if (tb.ty == Tvector && (typeb.ty == Tarray || typeb.ty == Tsarray))
2227             {
2228                 // Convert array literal to vector type
2229                 TypeVector tv = cast(TypeVector)tb;
2230                 TypeSArray tbase = cast(TypeSArray)tv.basetype;
2231                 assert(tbase.ty == Tsarray);
2232                 const edim = e.elements.dim;
2233                 const tbasedim = tbase.dim.toInteger();
2234                 if (edim > tbasedim)
2235                     goto L1;
2236 
2237                 ae = cast(ArrayLiteralExp)e.copy();
2238                 ae.type = tbase; // https://issues.dlang.org/show_bug.cgi?id=12642
2239                 ae.elements = e.elements.copy();
2240                 Type telement = tv.elementType();
2241                 foreach (i; 0 .. edim)
2242                 {
2243                     Expression ex = (*e.elements)[i];
2244                     ex = ex.castTo(sc, telement);
2245                     (*ae.elements)[i] = ex;
2246                 }
2247                 // Fill in the rest with the default initializer
2248                 ae.elements.setDim(cast(size_t)tbasedim);
2249                 foreach (i; edim .. cast(size_t)tbasedim)
2250                 {
2251                     Expression ex = typeb.nextOf.defaultInitLiteral(e.loc);
2252                     ex = ex.castTo(sc, telement);
2253                     (*ae.elements)[i] = ex;
2254                 }
2255                 Expression ev = new VectorExp(e.loc, ae, tb);
2256                 ev = ev.expressionSemantic(sc);
2257                 result = ev;
2258                 return;
2259             }
2260         L1:
2261             visit(cast(Expression)ae);
2262         }
2263 
2264         override void visit(AssocArrayLiteralExp e)
2265         {
2266             //printf("AssocArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", e.toChars(), e.type.toChars(), t.toChars());
2267             if (e.type == t)
2268             {
2269                 result = e;
2270                 return;
2271             }
2272 
2273             Type tb = t.toBasetype();
2274             Type typeb = e.type.toBasetype();
2275 
2276             if (tb.ty == Taarray && typeb.ty == Taarray &&
2277                 tb.nextOf().toBasetype().ty != Tvoid)
2278             {
2279                 AssocArrayLiteralExp ae = cast(AssocArrayLiteralExp)e.copy();
2280                 ae.keys = e.keys.copy();
2281                 ae.values = e.values.copy();
2282                 assert(e.keys.dim == e.values.dim);
2283                 for (size_t i = 0; i < e.keys.dim; i++)
2284                 {
2285                     Expression ex = (*e.values)[i];
2286                     ex = ex.castTo(sc, tb.nextOf());
2287                     (*ae.values)[i] = ex;
2288 
2289                     ex = (*e.keys)[i];
2290                     ex = ex.castTo(sc, (cast(TypeAArray)tb).index);
2291                     (*ae.keys)[i] = ex;
2292                 }
2293                 ae.type = t;
2294                 result = ae;
2295                 return;
2296             }
2297             visit(cast(Expression)e);
2298         }
2299 
2300         override void visit(SymOffExp e)
2301         {
2302             version (none)
2303             {
2304                 printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
2305             }
2306             if (e.type == t && !e.hasOverloads)
2307             {
2308                 result = e;
2309                 return;
2310             }
2311 
2312             Type tb = t.toBasetype();
2313             Type typeb = e.type.toBasetype();
2314 
2315             if (tb.equals(typeb))
2316             {
2317                 result = e.copy();
2318                 result.type = t;
2319                 (cast(SymOffExp)result).hasOverloads = false;
2320                 return;
2321             }
2322 
2323             // Look for pointers to functions where the functions are overloaded.
2324             if (e.hasOverloads &&
2325                 typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
2326                 (tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
2327             {
2328                 FuncDeclaration f = e.var.isFuncDeclaration();
2329                 f = f ? f.overloadExactMatch(tb.nextOf()) : null;
2330                 if (f)
2331                 {
2332                     if (tb.ty == Tdelegate)
2333                     {
2334                         if (f.needThis() && hasThis(sc))
2335                         {
2336                             result = new DelegateExp(e.loc, new ThisExp(e.loc), f, false);
2337                             result = result.expressionSemantic(sc);
2338                         }
2339                         else if (f.needThis())
2340                         {
2341                             e.error("no `this` to create delegate for `%s`", f.toChars());
2342                             result = new ErrorExp();
2343                             return;
2344                         }
2345                         else if (f.isNested())
2346                         {
2347                             result = new DelegateExp(e.loc, IntegerExp.literal!0, f, false);
2348                             result = result.expressionSemantic(sc);
2349                         }
2350                         else
2351                         {
2352                             e.error("cannot cast from function pointer to delegate");
2353                             result = new ErrorExp();
2354                             return;
2355                         }
2356                     }
2357                     else
2358                     {
2359                         result = new SymOffExp(e.loc, f, 0, false);
2360                         result.type = t;
2361                     }
2362                     f.tookAddressOf++;
2363                     return;
2364                 }
2365             }
2366 
2367             if (auto f = isFuncAddress(e))
2368             {
2369                 if (f.checkForwardRef(e.loc))
2370                 {
2371                     result = new ErrorExp();
2372                     return;
2373                 }
2374             }
2375 
2376             visit(cast(Expression)e);
2377         }
2378 
2379         override void visit(DelegateExp e)
2380         {
2381             version (none)
2382             {
2383                 printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", e.toChars(), e.type.toChars(), t.toChars());
2384             }
2385             __gshared const(char)* msg = "cannot form delegate due to covariant return type";
2386 
2387             Type tb = t.toBasetype();
2388             Type typeb = e.type.toBasetype();
2389 
2390             if (tb.equals(typeb) && !e.hasOverloads)
2391             {
2392                 int offset;
2393                 e.func.tookAddressOf++;
2394                 if (e.func.tintro && e.func.tintro.nextOf().isBaseOf(e.func.type.nextOf(), &offset) && offset)
2395                     e.error("%s", msg);
2396                 result = e.copy();
2397                 result.type = t;
2398                 return;
2399             }
2400 
2401             // Look for delegates to functions where the functions are overloaded.
2402             if (typeb.ty == Tdelegate && tb.ty == Tdelegate)
2403             {
2404                 if (e.func)
2405                 {
2406                     auto f = e.func.overloadExactMatch(tb.nextOf());
2407                     if (f)
2408                     {
2409                         int offset;
2410                         if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset)
2411                             e.error("%s", msg);
2412                         if (f != e.func)    // if address not already marked as taken
2413                             f.tookAddressOf++;
2414                         result = new DelegateExp(e.loc, e.e1, f, false, e.vthis2);
2415                         result.type = t;
2416                         return;
2417                     }
2418                     if (e.func.tintro)
2419                         e.error("%s", msg);
2420                 }
2421             }
2422 
2423             if (auto f = isFuncAddress(e))
2424             {
2425                 if (f.checkForwardRef(e.loc))
2426                 {
2427                     result = new ErrorExp();
2428                     return;
2429                 }
2430             }
2431 
2432             visit(cast(Expression)e);
2433         }
2434 
2435         override void visit(FuncExp e)
2436         {
2437             //printf("FuncExp::castTo type = %s, t = %s\n", e.type.toChars(), t.toChars());
2438             FuncExp fe;
2439             if (e.matchType(t, sc, &fe, 1) > MATCH.nomatch)
2440             {
2441                 result = fe;
2442                 return;
2443             }
2444             visit(cast(Expression)e);
2445         }
2446 
2447         override void visit(CondExp e)
2448         {
2449             if (!e.type.equals(t))
2450             {
2451                 result = new CondExp(e.loc, e.econd, e.e1.castTo(sc, t), e.e2.castTo(sc, t));
2452                 result.type = t;
2453                 return;
2454             }
2455             result = e;
2456         }
2457 
2458         override void visit(CommaExp e)
2459         {
2460             Expression e2c = e.e2.castTo(sc, t);
2461 
2462             if (e2c != e.e2)
2463             {
2464                 result = new CommaExp(e.loc, e.e1, e2c);
2465                 result.type = e2c.type;
2466             }
2467             else
2468             {
2469                 result = e;
2470                 result.type = e.e2.type;
2471             }
2472         }
2473 
2474         override void visit(SliceExp e)
2475         {
2476             //printf("SliceExp::castTo e = %s, type = %s, t = %s\n", e.toChars(), e.type.toChars(), t.toChars());
2477 
2478             Type tb = t.toBasetype();
2479             Type typeb = e.type.toBasetype();
2480 
2481             if (e.type.equals(t) || typeb.ty != Tarray ||
2482                 (tb.ty != Tarray && tb.ty != Tsarray))
2483             {
2484                 visit(cast(Expression)e);
2485                 return;
2486             }
2487 
2488             if (tb.ty == Tarray)
2489             {
2490                 if (typeb.nextOf().equivalent(tb.nextOf()))
2491                 {
2492                     // T[] to const(T)[]
2493                     result = e.copy();
2494                     result.type = t;
2495                 }
2496                 else
2497                 {
2498                     visit(cast(Expression)e);
2499                 }
2500                 return;
2501             }
2502 
2503             // Handle the cast from Tarray to Tsarray with CT-known slicing
2504 
2505             TypeSArray tsa = cast(TypeSArray)toStaticArrayType(e);
2506             if (tsa && tsa.size(e.loc) == tb.size(e.loc))
2507             {
2508                 /* Match if the sarray sizes are equal:
2509                  *  T[a .. b] to const(T)[b-a]
2510                  *  T[a .. b] to U[dim] if (T.sizeof*(b-a) == U.sizeof*dim)
2511                  *
2512                  * If a SliceExp has Tsarray, it will become lvalue.
2513                  * That's handled in SliceExp::isLvalue and toLvalue
2514                  */
2515                 result = e.copy();
2516                 result.type = t;
2517                 return;
2518             }
2519             if (tsa && tsa.dim.equals((cast(TypeSArray)tb).dim))
2520             {
2521                 /* Match if the dimensions are equal
2522                  * with the implicit conversion of e.e1:
2523                  *  cast(float[2]) [2.0, 1.0, 0.0][0..2];
2524                  */
2525                 Type t1b = e.e1.type.toBasetype();
2526                 if (t1b.ty == Tsarray)
2527                     t1b = tb.nextOf().sarrayOf((cast(TypeSArray)t1b).dim.toInteger());
2528                 else if (t1b.ty == Tarray)
2529                     t1b = tb.nextOf().arrayOf();
2530                 else if (t1b.ty == Tpointer)
2531                     t1b = tb.nextOf().pointerTo();
2532                 else
2533                     assert(0);
2534                 if (e.e1.implicitConvTo(t1b) > MATCH.nomatch)
2535                 {
2536                     Expression e1x = e.e1.implicitCastTo(sc, t1b);
2537                     assert(e1x.op != TOK.error);
2538                     e = cast(SliceExp)e.copy();
2539                     e.e1 = e1x;
2540                     e.type = t;
2541                     result = e;
2542                     return;
2543                 }
2544             }
2545             auto ts = toAutoQualChars(tsa ? tsa : e.type, t);
2546             e.error("cannot cast expression `%s` of type `%s` to `%s`",
2547                 e.toChars(), ts[0], ts[1]);
2548             result = new ErrorExp();
2549         }
2550     }
2551 
2552     scope CastTo v = new CastTo(sc, t);
2553     e.accept(v);
2554     return v.result;
2555 }
2556 
2557 /****************************************
2558  * Set type inference target
2559  *      t       Target type
2560  *      flag    1: don't put an error when inference fails
2561  */
2562 Expression inferType(Expression e, Type t, int flag = 0)
2563 {
2564     Expression visitAle(ArrayLiteralExp ale)
2565     {
2566         Type tb = t.toBasetype();
2567         if (tb.ty == Tarray || tb.ty == Tsarray)
2568         {
2569             Type tn = tb.nextOf();
2570             if (ale.basis)
2571                 ale.basis = inferType(ale.basis, tn, flag);
2572             for (size_t i = 0; i < ale.elements.dim; i++)
2573             {
2574                 if (Expression e = (*ale.elements)[i])
2575                 {
2576                     e = inferType(e, tn, flag);
2577                     (*ale.elements)[i] = e;
2578                 }
2579             }
2580         }
2581         return ale;
2582     }
2583 
2584     Expression visitAar(AssocArrayLiteralExp aale)
2585     {
2586         Type tb = t.toBasetype();
2587         if (tb.ty == Taarray)
2588         {
2589             TypeAArray taa = cast(TypeAArray)tb;
2590             Type ti = taa.index;
2591             Type tv = taa.nextOf();
2592             for (size_t i = 0; i < aale.keys.dim; i++)
2593             {
2594                 if (Expression e = (*aale.keys)[i])
2595                 {
2596                     e = inferType(e, ti, flag);
2597                     (*aale.keys)[i] = e;
2598                 }
2599             }
2600             for (size_t i = 0; i < aale.values.dim; i++)
2601             {
2602                 if (Expression e = (*aale.values)[i])
2603                 {
2604                     e = inferType(e, tv, flag);
2605                     (*aale.values)[i] = e;
2606                 }
2607             }
2608         }
2609         return aale;
2610     }
2611 
2612     Expression visitFun(FuncExp fe)
2613     {
2614         //printf("FuncExp::inferType('%s'), to=%s\n", fe.type ? fe.type.toChars() : "null", t.toChars());
2615         if (t.ty == Tdelegate || t.ty == Tpointer && t.nextOf().ty == Tfunction)
2616         {
2617             fe.fd.treq = t;
2618         }
2619         return fe;
2620     }
2621 
2622     Expression visitTer(CondExp ce)
2623     {
2624         Type tb = t.toBasetype();
2625         ce.e1 = inferType(ce.e1, tb, flag);
2626         ce.e2 = inferType(ce.e2, tb, flag);
2627         return ce;
2628     }
2629 
2630     if (t) switch (e.op)
2631     {
2632         case TOK.arrayLiteral:      return visitAle(cast(ArrayLiteralExp) e);
2633         case TOK.assocArrayLiteral: return visitAar(cast(AssocArrayLiteralExp) e);
2634         case TOK.function_:         return visitFun(cast(FuncExp) e);
2635         case TOK.question:          return visitTer(cast(CondExp) e);
2636         default:
2637     }
2638     return e;
2639 }
2640 
2641 /****************************************
2642  * Scale addition/subtraction to/from pointer.
2643  */
2644 Expression scaleFactor(BinExp be, Scope* sc)
2645 {
2646     Type t1b = be.e1.type.toBasetype();
2647     Type t2b = be.e2.type.toBasetype();
2648     Expression eoff;
2649 
2650     if (t1b.ty == Tpointer && t2b.isintegral())
2651     {
2652         // Need to adjust operator by the stride
2653         // Replace (ptr + int) with (ptr + (int * stride))
2654         Type t = Type.tptrdiff_t;
2655 
2656         d_uns64 stride = t1b.nextOf().size(be.loc);
2657         if (!t.equals(t2b))
2658             be.e2 = be.e2.castTo(sc, t);
2659         eoff = be.e2;
2660         be.e2 = new MulExp(be.loc, be.e2, new IntegerExp(Loc.initial, stride, t));
2661         be.e2.type = t;
2662         be.type = be.e1.type;
2663     }
2664     else if (t2b.ty == Tpointer && t1b.isintegral())
2665     {
2666         // Need to adjust operator by the stride
2667         // Replace (int + ptr) with (ptr + (int * stride))
2668         Type t = Type.tptrdiff_t;
2669         Expression e;
2670 
2671         d_uns64 stride = t2b.nextOf().size(be.loc);
2672         if (!t.equals(t1b))
2673             e = be.e1.castTo(sc, t);
2674         else
2675             e = be.e1;
2676         eoff = e;
2677         e = new MulExp(be.loc, e, new IntegerExp(Loc.initial, stride, t));
2678         e.type = t;
2679         be.type = be.e2.type;
2680         be.e1 = be.e2;
2681         be.e2 = e;
2682     }
2683     else
2684         assert(0);
2685 
2686     if (sc.func && !sc.intypeof)
2687     {
2688         eoff = eoff.optimize(WANTvalue);
2689         if (eoff.op == TOK.int64 && eoff.toInteger() == 0)
2690         {
2691         }
2692         else if (sc.func.setUnsafe())
2693         {
2694             be.error("pointer arithmetic not allowed in @safe functions");
2695             return new ErrorExp();
2696         }
2697     }
2698 
2699     return be;
2700 }
2701 
2702 /**************************************
2703  * Return true if e is an empty array literal with dimensionality
2704  * equal to or less than type of other array.
2705  * [], [[]], [[[]]], etc.
2706  * I.e., make sure that [1,2] is compatible with [],
2707  * [[1,2]] is compatible with [[]], etc.
2708  */
2709 private bool isVoidArrayLiteral(Expression e, Type other)
2710 {
2711     while (e.op == TOK.arrayLiteral && e.type.ty == Tarray && ((cast(ArrayLiteralExp)e).elements.dim == 1))
2712     {
2713         auto ale = cast(ArrayLiteralExp)e;
2714         e = ale[0];
2715         if (other.ty == Tsarray || other.ty == Tarray)
2716             other = other.nextOf();
2717         else
2718             return false;
2719     }
2720     if (other.ty != Tsarray && other.ty != Tarray)
2721         return false;
2722     Type t = e.type;
2723     return (e.op == TOK.arrayLiteral && t.ty == Tarray && t.nextOf().ty == Tvoid && (cast(ArrayLiteralExp)e).elements.dim == 0);
2724 }
2725 
2726 /**************************************
2727  * Combine types.
2728  * Output:
2729  *      *pt     merged type, if *pt is not NULL
2730  *      *pe1    rewritten e1
2731  *      *pe2    rewritten e2
2732  * Returns:
2733  *      true    success
2734  *      false   failed
2735  */
2736 bool typeMerge(Scope* sc, TOK op, Type* pt, Expression* pe1, Expression* pe2)
2737 {
2738     //printf("typeMerge() %s op %s\n", pe1.toChars(), pe2.toChars());
2739 
2740     MATCH m;
2741     Expression e1 = *pe1;
2742     Expression e2 = *pe2;
2743 
2744     Type t1 = e1.type;
2745     Type t2 = e2.type;
2746 
2747     Type t1b = e1.type.toBasetype();
2748     Type t2b = e2.type.toBasetype();
2749 
2750     Type t;
2751 
2752     bool Lret()
2753     {
2754         if (!*pt)
2755             *pt = t;
2756         *pe1 = e1;
2757         *pe2 = e2;
2758 
2759         version (none)
2760         {
2761             printf("-typeMerge() %s op %s\n", e1.toChars(), e2.toChars());
2762             if (e1.type)
2763                 printf("\tt1 = %s\n", e1.type.toChars());
2764             if (e2.type)
2765                 printf("\tt2 = %s\n", e2.type.toChars());
2766             printf("\ttype = %s\n", t.toChars());
2767         }
2768         return true;
2769     }
2770 
2771     bool Lt1()
2772     {
2773         e2 = e2.castTo(sc, t1);
2774         t = t1;
2775         return Lret();
2776     }
2777 
2778     bool Lt2()
2779     {
2780         e1 = e1.castTo(sc, t2);
2781         t = t2;
2782         return Lret();
2783     }
2784 
2785     bool Lincompatible() { return false; }
2786 
2787     if (op != TOK.question || t1b.ty != t2b.ty && (t1b.isTypeBasic() && t2b.isTypeBasic()))
2788     {
2789         if (op == TOK.question && t1b.ty.isSomeChar() && t2b.ty.isSomeChar())
2790         {
2791             e1 = e1.castTo(sc, Type.tdchar);
2792             e2 = e2.castTo(sc, Type.tdchar);
2793         }
2794         else
2795         {
2796             e1 = integralPromotions(e1, sc);
2797             e2 = integralPromotions(e2, sc);
2798         }
2799     }
2800 
2801     t1 = e1.type;
2802     t2 = e2.type;
2803     assert(t1);
2804     t = t1;
2805 
2806     /* The start type of alias this type recursion.
2807      * In following case, we should save A, and stop recursion
2808      * if it appears again.
2809      *      X -> Y -> [A] -> B -> A -> B -> ...
2810      */
2811     Type att1 = null;
2812     Type att2 = null;
2813 
2814     //if (t1) printf("\tt1 = %s\n", t1.toChars());
2815     //if (t2) printf("\tt2 = %s\n", t2.toChars());
2816     debug
2817     {
2818         if (!t2)
2819             printf("\te2 = '%s'\n", e2.toChars());
2820     }
2821     assert(t2);
2822 
2823     if (t1.mod != t2.mod &&
2824         t1.ty == Tenum && t2.ty == Tenum &&
2825         (cast(TypeEnum)t1).sym == (cast(TypeEnum)t2).sym)
2826     {
2827         ubyte mod = MODmerge(t1.mod, t2.mod);
2828         t1 = t1.castMod(mod);
2829         t2 = t2.castMod(mod);
2830     }
2831 
2832 Lagain:
2833     t1b = t1.toBasetype();
2834     t2b = t2.toBasetype();
2835 
2836     TY ty = cast(TY)impcnvResult[t1b.ty][t2b.ty];
2837     if (ty != Terror)
2838     {
2839         TY ty1 = cast(TY)impcnvType1[t1b.ty][t2b.ty];
2840         TY ty2 = cast(TY)impcnvType2[t1b.ty][t2b.ty];
2841 
2842         if (t1b.ty == ty1) // if no promotions
2843         {
2844             if (t1.equals(t2))
2845             {
2846                 t = t1;
2847                 return Lret();
2848             }
2849 
2850             if (t1b.equals(t2b))
2851             {
2852                 t = t1b;
2853                 return Lret();
2854             }
2855         }
2856 
2857         t = Type.basic[ty];
2858 
2859         t1 = Type.basic[ty1];
2860         t2 = Type.basic[ty2];
2861         e1 = e1.castTo(sc, t1);
2862         e2 = e2.castTo(sc, t2);
2863         return Lret();
2864     }
2865 
2866     t1 = t1b;
2867     t2 = t2b;
2868 
2869     if (t1.ty == Ttuple || t2.ty == Ttuple)
2870         return Lincompatible();
2871 
2872     if (t1.equals(t2))
2873     {
2874         // merging can not result in new enum type
2875         if (t.ty == Tenum)
2876             t = t1b;
2877     }
2878     else if ((t1.ty == Tpointer && t2.ty == Tpointer) || (t1.ty == Tdelegate && t2.ty == Tdelegate))
2879     {
2880         // Bring pointers to compatible type
2881         Type t1n = t1.nextOf();
2882         Type t2n = t2.nextOf();
2883 
2884         if (t1n.equals(t2n))
2885         {
2886         }
2887         else if (t1n.ty == Tvoid) // pointers to void are always compatible
2888             t = t2;
2889         else if (t2n.ty == Tvoid)
2890         {
2891         }
2892         else if (t1.implicitConvTo(t2))
2893         {
2894             return Lt2();
2895         }
2896         else if (t2.implicitConvTo(t1))
2897         {
2898             return Lt1();
2899         }
2900         else if (t1n.ty == Tfunction && t2n.ty == Tfunction)
2901         {
2902             TypeFunction tf1 = cast(TypeFunction)t1n;
2903             TypeFunction tf2 = cast(TypeFunction)t2n;
2904             tf1.purityLevel();
2905             tf2.purityLevel();
2906 
2907             TypeFunction d = cast(TypeFunction)tf1.syntaxCopy();
2908 
2909             if (tf1.purity != tf2.purity)
2910                 d.purity = PURE.impure;
2911             assert(d.purity != PURE.fwdref);
2912 
2913             d.isnothrow = (tf1.isnothrow && tf2.isnothrow);
2914             d.isnogc = (tf1.isnogc && tf2.isnogc);
2915 
2916             if (tf1.trust == tf2.trust)
2917                 d.trust = tf1.trust;
2918             else if (tf1.trust <= TRUST.system || tf2.trust <= TRUST.system)
2919                 d.trust = TRUST.system;
2920             else
2921                 d.trust = TRUST.trusted;
2922 
2923             Type tx = null;
2924             if (t1.ty == Tdelegate)
2925             {
2926                 tx = new TypeDelegate(d);
2927             }
2928             else
2929                 tx = d.pointerTo();
2930 
2931             tx = tx.typeSemantic(e1.loc, sc);
2932 
2933             if (t1.implicitConvTo(tx) && t2.implicitConvTo(tx))
2934             {
2935                 t = tx;
2936                 e1 = e1.castTo(sc, t);
2937                 e2 = e2.castTo(sc, t);
2938                 return Lret();
2939             }
2940             return Lincompatible();
2941         }
2942         else if (t1n.mod != t2n.mod)
2943         {
2944             if (!t1n.isImmutable() && !t2n.isImmutable() && t1n.isShared() != t2n.isShared())
2945                 return Lincompatible();
2946             ubyte mod = MODmerge(t1n.mod, t2n.mod);
2947             t1 = t1n.castMod(mod).pointerTo();
2948             t2 = t2n.castMod(mod).pointerTo();
2949             t = t1;
2950             goto Lagain;
2951         }
2952         else if (t1n.ty == Tclass && t2n.ty == Tclass)
2953         {
2954             ClassDeclaration cd1 = t1n.isClassHandle();
2955             ClassDeclaration cd2 = t2n.isClassHandle();
2956             int offset;
2957             if (cd1.isBaseOf(cd2, &offset))
2958             {
2959                 if (offset)
2960                     e2 = e2.castTo(sc, t);
2961             }
2962             else if (cd2.isBaseOf(cd1, &offset))
2963             {
2964                 t = t2;
2965                 if (offset)
2966                     e1 = e1.castTo(sc, t);
2967             }
2968             else
2969                 return Lincompatible();
2970         }
2971         else
2972         {
2973             t1 = t1n.constOf().pointerTo();
2974             t2 = t2n.constOf().pointerTo();
2975             if (t1.implicitConvTo(t2))
2976             {
2977                 return Lt2();
2978             }
2979             else if (t2.implicitConvTo(t1))
2980             {
2981                 return Lt1();
2982             }
2983             return Lincompatible();
2984         }
2985     }
2986     else if ((t1.ty == Tsarray || t1.ty == Tarray) && (e2.op == TOK.null_ && t2.ty == Tpointer && t2.nextOf().ty == Tvoid || e2.op == TOK.arrayLiteral && t2.ty == Tsarray && t2.nextOf().ty == Tvoid && (cast(TypeSArray)t2).dim.toInteger() == 0 || isVoidArrayLiteral(e2, t1)))
2987     {
2988         /*  (T[n] op void*)   => T[]
2989          *  (T[]  op void*)   => T[]
2990          *  (T[n] op void[0]) => T[]
2991          *  (T[]  op void[0]) => T[]
2992          *  (T[n] op void[])  => T[]
2993          *  (T[]  op void[])  => T[]
2994          */
2995         goto Lx1;
2996     }
2997     else if ((t2.ty == Tsarray || t2.ty == Tarray) && (e1.op == TOK.null_ && t1.ty == Tpointer && t1.nextOf().ty == Tvoid || e1.op == TOK.arrayLiteral && t1.ty == Tsarray && t1.nextOf().ty == Tvoid && (cast(TypeSArray)t1).dim.toInteger() == 0 || isVoidArrayLiteral(e1, t2)))
2998     {
2999         /*  (void*   op T[n]) => T[]
3000          *  (void*   op T[])  => T[]
3001          *  (void[0] op T[n]) => T[]
3002          *  (void[0] op T[])  => T[]
3003          *  (void[]  op T[n]) => T[]
3004          *  (void[]  op T[])  => T[]
3005          */
3006         goto Lx2;
3007     }
3008     else if ((t1.ty == Tsarray || t1.ty == Tarray) && (m = t1.implicitConvTo(t2)) != MATCH.nomatch)
3009     {
3010         // https://issues.dlang.org/show_bug.cgi?id=7285
3011         // Tsarray op [x, y, ...] should to be Tsarray
3012         // https://issues.dlang.org/show_bug.cgi?id=14737
3013         // Tsarray ~ [x, y, ...] should to be Tarray
3014         if (t1.ty == Tsarray && e2.op == TOK.arrayLiteral && op != TOK.concatenate)
3015             return Lt1();
3016         if (m == MATCH.constant && (op == TOK.addAssign || op == TOK.minAssign || op == TOK.mulAssign || op == TOK.divAssign || op == TOK.modAssign || op == TOK.powAssign || op == TOK.andAssign || op == TOK.orAssign || op == TOK.xorAssign))
3017         {
3018             // Don't make the lvalue const
3019             t = t2;
3020             return Lret();
3021         }
3022         return Lt2();
3023     }
3024     else if ((t2.ty == Tsarray || t2.ty == Tarray) && t2.implicitConvTo(t1))
3025     {
3026         // https://issues.dlang.org/show_bug.cgi?id=7285
3027         // https://issues.dlang.org/show_bug.cgi?id=14737
3028         if (t2.ty == Tsarray && e1.op == TOK.arrayLiteral && op != TOK.concatenate)
3029             return Lt2();
3030         return Lt1();
3031     }
3032     else if ((t1.ty == Tsarray || t1.ty == Tarray || t1.ty == Tpointer) && (t2.ty == Tsarray || t2.ty == Tarray || t2.ty == Tpointer) && t1.nextOf().mod != t2.nextOf().mod)
3033     {
3034         /* If one is mutable and the other invariant, then retry
3035          * with both of them as const
3036          */
3037         Type t1n = t1.nextOf();
3038         Type t2n = t2.nextOf();
3039         ubyte mod;
3040         if (e1.op == TOK.null_ && e2.op != TOK.null_)
3041             mod = t2n.mod;
3042         else if (e1.op != TOK.null_ && e2.op == TOK.null_)
3043             mod = t1n.mod;
3044         else if (!t1n.isImmutable() && !t2n.isImmutable() && t1n.isShared() != t2n.isShared())
3045             return Lincompatible();
3046         else
3047             mod = MODmerge(t1n.mod, t2n.mod);
3048 
3049         if (t1.ty == Tpointer)
3050             t1 = t1n.castMod(mod).pointerTo();
3051         else
3052             t1 = t1n.castMod(mod).arrayOf();
3053 
3054         if (t2.ty == Tpointer)
3055             t2 = t2n.castMod(mod).pointerTo();
3056         else
3057             t2 = t2n.castMod(mod).arrayOf();
3058         t = t1;
3059         goto Lagain;
3060     }
3061     else if (t1.ty == Tclass && t2.ty == Tclass)
3062     {
3063         if (t1.mod != t2.mod)
3064         {
3065             ubyte mod;
3066             if (e1.op == TOK.null_ && e2.op != TOK.null_)
3067                 mod = t2.mod;
3068             else if (e1.op != TOK.null_ && e2.op == TOK.null_)
3069                 mod = t1.mod;
3070             else if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
3071                 return Lincompatible();
3072             else
3073                 mod = MODmerge(t1.mod, t2.mod);
3074             t1 = t1.castMod(mod);
3075             t2 = t2.castMod(mod);
3076             t = t1;
3077             goto Lagain;
3078         }
3079         goto Lcc;
3080     }
3081     else if (t1.ty == Tclass || t2.ty == Tclass)
3082     {
3083     Lcc:
3084         while (1)
3085         {
3086             MATCH i1 = e2.implicitConvTo(t1);
3087             MATCH i2 = e1.implicitConvTo(t2);
3088 
3089             if (i1 && i2)
3090             {
3091                 // We have the case of class vs. void*, so pick class
3092                 if (t1.ty == Tpointer)
3093                     i1 = MATCH.nomatch;
3094                 else if (t2.ty == Tpointer)
3095                     i2 = MATCH.nomatch;
3096             }
3097 
3098             if (i2)
3099             {
3100                 e2 = e2.castTo(sc, t2);
3101                 return Lt2();
3102             }
3103             else if (i1)
3104             {
3105                 e1 = e1.castTo(sc, t1);
3106                 return Lt1();
3107             }
3108             else if (t1.ty == Tclass && t2.ty == Tclass)
3109             {
3110                 TypeClass tc1 = cast(TypeClass)t1;
3111                 TypeClass tc2 = cast(TypeClass)t2;
3112 
3113                 /* Pick 'tightest' type
3114                  */
3115                 ClassDeclaration cd1 = tc1.sym.baseClass;
3116                 ClassDeclaration cd2 = tc2.sym.baseClass;
3117                 if (cd1 && cd2)
3118                 {
3119                     t1 = cd1.type.castMod(t1.mod);
3120                     t2 = cd2.type.castMod(t2.mod);
3121                 }
3122                 else if (cd1)
3123                     t1 = cd1.type;
3124                 else if (cd2)
3125                     t2 = cd2.type;
3126                 else
3127                     return Lincompatible();
3128             }
3129             else if (t1.ty == Tstruct && (cast(TypeStruct)t1).sym.aliasthis)
3130             {
3131                 if (att1 && e1.type == att1)
3132                     return Lincompatible();
3133                 if (!att1 && e1.type.checkAliasThisRec())
3134                     att1 = e1.type;
3135                 //printf("att tmerge(c || c) e1 = %s\n", e1.type.toChars());
3136                 e1 = resolveAliasThis(sc, e1);
3137                 t1 = e1.type;
3138                 continue;
3139             }
3140             else if (t2.ty == Tstruct && (cast(TypeStruct)t2).sym.aliasthis)
3141             {
3142                 if (att2 && e2.type == att2)
3143                     return Lincompatible();
3144                 if (!att2 && e2.type.checkAliasThisRec())
3145                     att2 = e2.type;
3146                 //printf("att tmerge(c || c) e2 = %s\n", e2.type.toChars());
3147                 e2 = resolveAliasThis(sc, e2);
3148                 t2 = e2.type;
3149                 continue;
3150             }
3151             else
3152                 return Lincompatible();
3153         }
3154     }
3155     else if (t1.ty == Tstruct && t2.ty == Tstruct)
3156     {
3157         if (t1.mod != t2.mod)
3158         {
3159             if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
3160                 return Lincompatible();
3161             ubyte mod = MODmerge(t1.mod, t2.mod);
3162             t1 = t1.castMod(mod);
3163             t2 = t2.castMod(mod);
3164             t = t1;
3165             goto Lagain;
3166         }
3167 
3168         TypeStruct ts1 = cast(TypeStruct)t1;
3169         TypeStruct ts2 = cast(TypeStruct)t2;
3170         if (ts1.sym != ts2.sym)
3171         {
3172             if (!ts1.sym.aliasthis && !ts2.sym.aliasthis)
3173                 return Lincompatible();
3174 
3175             MATCH i1 = MATCH.nomatch;
3176             MATCH i2 = MATCH.nomatch;
3177 
3178             Expression e1b = null;
3179             Expression e2b = null;
3180             if (ts2.sym.aliasthis)
3181             {
3182                 if (att2 && e2.type == att2)
3183                     return Lincompatible();
3184                 if (!att2 && e2.type.checkAliasThisRec())
3185                     att2 = e2.type;
3186                 //printf("att tmerge(s && s) e2 = %s\n", e2.type.toChars());
3187                 e2b = resolveAliasThis(sc, e2);
3188                 i1 = e2b.implicitConvTo(t1);
3189             }
3190             if (ts1.sym.aliasthis)
3191             {
3192                 if (att1 && e1.type == att1)
3193                     return Lincompatible();
3194                 if (!att1 && e1.type.checkAliasThisRec())
3195                     att1 = e1.type;
3196                 //printf("att tmerge(s && s) e1 = %s\n", e1.type.toChars());
3197                 e1b = resolveAliasThis(sc, e1);
3198                 i2 = e1b.implicitConvTo(t2);
3199             }
3200             if (i1 && i2)
3201                 return Lincompatible();
3202 
3203             if (i1)
3204                 return Lt1();
3205             else if (i2)
3206                 return Lt2();
3207 
3208             if (e1b)
3209             {
3210                 e1 = e1b;
3211                 t1 = e1b.type.toBasetype();
3212             }
3213             if (e2b)
3214             {
3215                 e2 = e2b;
3216                 t2 = e2b.type.toBasetype();
3217             }
3218             t = t1;
3219             goto Lagain;
3220         }
3221     }
3222     else if (t1.ty == Tstruct || t2.ty == Tstruct)
3223     {
3224         if (t1.ty == Tstruct && (cast(TypeStruct)t1).sym.aliasthis)
3225         {
3226             if (att1 && e1.type == att1)
3227                 return Lincompatible();
3228             if (!att1 && e1.type.checkAliasThisRec())
3229                 att1 = e1.type;
3230             //printf("att tmerge(s || s) e1 = %s\n", e1.type.toChars());
3231             e1 = resolveAliasThis(sc, e1);
3232             t1 = e1.type;
3233             t = t1;
3234             goto Lagain;
3235         }
3236         if (t2.ty == Tstruct && (cast(TypeStruct)t2).sym.aliasthis)
3237         {
3238             if (att2 && e2.type == att2)
3239                 return Lincompatible();
3240             if (!att2 && e2.type.checkAliasThisRec())
3241                 att2 = e2.type;
3242             //printf("att tmerge(s || s) e2 = %s\n", e2.type.toChars());
3243             e2 = resolveAliasThis(sc, e2);
3244             t2 = e2.type;
3245             t = t2;
3246             goto Lagain;
3247         }
3248         return Lincompatible();
3249     }
3250     else if ((e1.op == TOK.string_ || e1.op == TOK.null_) && e1.implicitConvTo(t2))
3251     {
3252         return Lt2();
3253     }
3254     else if ((e2.op == TOK.string_ || e2.op == TOK.null_) && e2.implicitConvTo(t1))
3255     {
3256         return Lt1();
3257     }
3258     else if (t1.ty == Tsarray && t2.ty == Tsarray && e2.implicitConvTo(t1.nextOf().arrayOf()))
3259     {
3260     Lx1:
3261         t = t1.nextOf().arrayOf(); // T[]
3262         e1 = e1.castTo(sc, t);
3263         e2 = e2.castTo(sc, t);
3264     }
3265     else if (t1.ty == Tsarray && t2.ty == Tsarray && e1.implicitConvTo(t2.nextOf().arrayOf()))
3266     {
3267     Lx2:
3268         t = t2.nextOf().arrayOf();
3269         e1 = e1.castTo(sc, t);
3270         e2 = e2.castTo(sc, t);
3271     }
3272     else if (t1.ty == Tvector && t2.ty == Tvector)
3273     {
3274         // https://issues.dlang.org/show_bug.cgi?id=13841
3275         // all vector types should have no common types between
3276         // different vectors, even though their sizes are same.
3277         auto tv1 = cast(TypeVector)t1;
3278         auto tv2 = cast(TypeVector)t2;
3279         if (!tv1.basetype.equals(tv2.basetype))
3280             return Lincompatible();
3281 
3282         goto LmodCompare;
3283     }
3284     else if (t1.ty == Tvector && t2.ty != Tvector && e2.implicitConvTo(t1))
3285     {
3286         e2 = e2.castTo(sc, t1);
3287         t2 = t1;
3288         t = t1;
3289         goto Lagain;
3290     }
3291     else if (t2.ty == Tvector && t1.ty != Tvector && e1.implicitConvTo(t2))
3292     {
3293         e1 = e1.castTo(sc, t2);
3294         t1 = t2;
3295         t = t1;
3296         goto Lagain;
3297     }
3298     else if (t1.isintegral() && t2.isintegral())
3299     {
3300         if (t1.ty != t2.ty)
3301         {
3302             if (t1.ty == Tvector || t2.ty == Tvector)
3303                 return Lincompatible();
3304             e1 = integralPromotions(e1, sc);
3305             e2 = integralPromotions(e2, sc);
3306             t1 = e1.type;
3307             t2 = e2.type;
3308             goto Lagain;
3309         }
3310         assert(t1.ty == t2.ty);
3311 LmodCompare:
3312         if (!t1.isImmutable() && !t2.isImmutable() && t1.isShared() != t2.isShared())
3313             return Lincompatible();
3314         ubyte mod = MODmerge(t1.mod, t2.mod);
3315 
3316         t1 = t1.castMod(mod);
3317         t2 = t2.castMod(mod);
3318         t = t1;
3319         e1 = e1.castTo(sc, t);
3320         e2 = e2.castTo(sc, t);
3321         goto Lagain;
3322     }
3323     else if (t1.ty == Tnull && t2.ty == Tnull)
3324     {
3325         ubyte mod = MODmerge(t1.mod, t2.mod);
3326 
3327         t = t1.castMod(mod);
3328         e1 = e1.castTo(sc, t);
3329         e2 = e2.castTo(sc, t);
3330         return Lret();
3331     }
3332     else if (t2.ty == Tnull && (t1.ty == Tpointer || t1.ty == Taarray || t1.ty == Tarray))
3333     {
3334         return Lt1();
3335     }
3336     else if (t1.ty == Tnull && (t2.ty == Tpointer || t2.ty == Taarray || t2.ty == Tarray))
3337     {
3338         return Lt2();
3339     }
3340     else if (t1.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e1))
3341     {
3342         if (e2.implicitConvTo(t1.nextOf()))
3343         {
3344             // T[] op T
3345             // T[] op cast(T)U
3346             e2 = e2.castTo(sc, t1.nextOf());
3347             t = t1.nextOf().arrayOf();
3348         }
3349         else if (t1.nextOf().implicitConvTo(e2.type))
3350         {
3351             // (cast(T)U)[] op T    (https://issues.dlang.org/show_bug.cgi?id=12780)
3352             // e1 is left as U[], it will be handled in arrayOp() later.
3353             t = e2.type.arrayOf();
3354         }
3355         else if (t2.ty == Tarray && isArrayOpOperand(e2))
3356         {
3357             if (t1.nextOf().implicitConvTo(t2.nextOf()))
3358             {
3359                 // (cast(T)U)[] op T[]  (https://issues.dlang.org/show_bug.cgi?id=12780)
3360                 t = t2.nextOf().arrayOf();
3361                 // if cast won't be handled in arrayOp() later
3362                 if (!isArrayOpImplicitCast(t1.isTypeDArray(), t2.isTypeDArray()))
3363                     e1 = e1.castTo(sc, t);
3364             }
3365             else if (t2.nextOf().implicitConvTo(t1.nextOf()))
3366             {
3367                 // T[] op (cast(T)U)[]  (https://issues.dlang.org/show_bug.cgi?id=12780)
3368                 // e2 is left as U[], it will be handled in arrayOp() later.
3369                 t = t1.nextOf().arrayOf();
3370                 // if cast won't be handled in arrayOp() later
3371                 if (!isArrayOpImplicitCast(t2.isTypeDArray(), t1.isTypeDArray()))
3372                     e2 = e2.castTo(sc, t);
3373             }
3374             else
3375                 return Lincompatible();
3376         }
3377         else
3378             return Lincompatible();
3379     }
3380     else if (t2.ty == Tarray && isBinArrayOp(op) && isArrayOpOperand(e2))
3381     {
3382         if (e1.implicitConvTo(t2.nextOf()))
3383         {
3384             // T op T[]
3385             // cast(T)U op T[]
3386             e1 = e1.castTo(sc, t2.nextOf());
3387             t = t2.nextOf().arrayOf();
3388         }
3389         else if (t2.nextOf().implicitConvTo(e1.type))
3390         {
3391             // T op (cast(T)U)[]    (https://issues.dlang.org/show_bug.cgi?id=12780)
3392             // e2 is left as U[], it will be handled in arrayOp() later.
3393             t = e1.type.arrayOf();
3394         }
3395         else
3396             return Lincompatible();
3397 
3398         //printf("test %s\n", Token::toChars(op));
3399         e1 = e1.optimize(WANTvalue);
3400         if (isCommutative(op) && e1.isConst())
3401         {
3402             /* Swap operands to minimize number of functions generated
3403              */
3404             //printf("swap %s\n", Token::toChars(op));
3405             Expression tmp = e1;
3406             e1 = e2;
3407             e2 = tmp;
3408         }
3409     }
3410     else
3411     {
3412         return Lincompatible();
3413     }
3414     return Lret();
3415 }
3416 
3417 /************************************
3418  * Bring leaves to common type.
3419  * Returns:
3420  *    null on success, ErrorExp if error occurs
3421  */
3422 Expression typeCombine(BinExp be, Scope* sc)
3423 {
3424     Expression errorReturn()
3425     {
3426         Expression ex = be.incompatibleTypes();
3427         if (ex.op == TOK.error)
3428             return ex;
3429         return new ErrorExp();
3430     }
3431 
3432     Type t1 = be.e1.type.toBasetype();
3433     Type t2 = be.e2.type.toBasetype();
3434 
3435     if (be.op == TOK.min || be.op == TOK.add)
3436     {
3437         // struct+struct, and class+class are errors
3438         if (t1.ty == Tstruct && t2.ty == Tstruct)
3439             return errorReturn();
3440         else if (t1.ty == Tclass && t2.ty == Tclass)
3441             return errorReturn();
3442         else if (t1.ty == Taarray && t2.ty == Taarray)
3443             return errorReturn();
3444     }
3445 
3446     if (!typeMerge(sc, be.op, &be.type, &be.e1, &be.e2))
3447         return errorReturn();
3448 
3449     // If the types have no value, return an error
3450     if (be.e1.op == TOK.error)
3451         return be.e1;
3452     if (be.e2.op == TOK.error)
3453         return be.e2;
3454     return null;
3455 }
3456 
3457 /***********************************
3458  * Do integral promotions (convertchk).
3459  * Don't convert <array of> to <pointer to>
3460  */
3461 Expression integralPromotions(Expression e, Scope* sc)
3462 {
3463     //printf("integralPromotions %s %s\n", e.toChars(), e.type.toChars());
3464     switch (e.type.toBasetype().ty)
3465     {
3466     case Tvoid:
3467         e.error("void has no value");
3468         return new ErrorExp();
3469 
3470     case Tint8:
3471     case Tuns8:
3472     case Tint16:
3473     case Tuns16:
3474     case Tbool:
3475     case Tchar:
3476     case Twchar:
3477         e = e.castTo(sc, Type.tint32);
3478         break;
3479 
3480     case Tdchar:
3481         e = e.castTo(sc, Type.tuns32);
3482         break;
3483 
3484     default:
3485         break;
3486     }
3487     return e;
3488 }
3489 
3490 /******************************************************
3491  * This provides a transition from the non-promoting behavior
3492  * of unary + - ~ to the C-like integral promotion behavior.
3493  * Params:
3494  *    sc = context
3495  *    ue = NegExp, UAddExp, or ComExp which is revised per rules
3496  * References:
3497  *      https://issues.dlang.org/show_bug.cgi?id=16997
3498  */
3499 
3500 void fix16997(Scope* sc, UnaExp ue)
3501 {
3502     if (global.params.fix16997)
3503         ue.e1 = integralPromotions(ue.e1, sc);          // desired C-like behavor
3504     else
3505     {
3506         switch (ue.e1.type.toBasetype.ty)
3507         {
3508             case Tint8:
3509             case Tuns8:
3510             case Tint16:
3511             case Tuns16:
3512             //case Tbool:       // these operations aren't allowed on bool anyway
3513             case Tchar:
3514             case Twchar:
3515             case Tdchar:
3516                 ue.deprecation("integral promotion not done for `%s`, use '-preview=intpromote' switch or `%scast(int)(%s)`",
3517                     ue.toChars(), Token.toChars(ue.op), ue.e1.toChars());
3518                 break;
3519 
3520             default:
3521                 break;
3522         }
3523     }
3524 }
3525 
3526 /***********************************
3527  * See if both types are arrays that can be compared
3528  * for equality. Return true if so.
3529  * If they are arrays, but incompatible, issue error.
3530  * This is to enable comparing things like an immutable
3531  * array with a mutable one.
3532  */
3533 extern (C++) bool arrayTypeCompatible(Loc loc, Type t1, Type t2)
3534 {
3535     t1 = t1.toBasetype().merge2();
3536     t2 = t2.toBasetype().merge2();
3537 
3538     if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer))
3539     {
3540         if (t1.nextOf().implicitConvTo(t2.nextOf()) < MATCH.constant && t2.nextOf().implicitConvTo(t1.nextOf()) < MATCH.constant && (t1.nextOf().ty != Tvoid && t2.nextOf().ty != Tvoid))
3541         {
3542             error(loc, "array equality comparison type mismatch, `%s` vs `%s`", t1.toChars(), t2.toChars());
3543         }
3544         return true;
3545     }
3546     return false;
3547 }
3548 
3549 /***********************************
3550  * See if both types are arrays that can be compared
3551  * for equality without any casting. Return true if so.
3552  * This is to enable comparing things like an immutable
3553  * array with a mutable one.
3554  */
3555 extern (C++) bool arrayTypeCompatibleWithoutCasting(Type t1, Type t2)
3556 {
3557     t1 = t1.toBasetype();
3558     t2 = t2.toBasetype();
3559 
3560     if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && t2.ty == t1.ty)
3561     {
3562         if (t1.nextOf().implicitConvTo(t2.nextOf()) >= MATCH.constant || t2.nextOf().implicitConvTo(t1.nextOf()) >= MATCH.constant)
3563             return true;
3564     }
3565     return false;
3566 }
3567 
3568 /******************************************************************/
3569 /* Determine the integral ranges of an expression.
3570  * This is used to determine if implicit narrowing conversions will
3571  * be allowed.
3572  */
3573 IntRange getIntRange(Expression e)
3574 {
3575     extern (C++) final class IntRangeVisitor : Visitor
3576     {
3577         alias visit = Visitor.visit;
3578 
3579     public:
3580         IntRange range;
3581 
3582         override void visit(Expression e)
3583         {
3584             range = IntRange.fromType(e.type);
3585         }
3586 
3587         override void visit(IntegerExp e)
3588         {
3589             range = IntRange(SignExtendedNumber(e.getInteger()))._cast(e.type);
3590         }
3591 
3592         override void visit(CastExp e)
3593         {
3594             range = getIntRange(e.e1)._cast(e.type);
3595         }
3596 
3597         override void visit(AddExp e)
3598         {
3599             IntRange ir1 = getIntRange(e.e1);
3600             IntRange ir2 = getIntRange(e.e2);
3601             range = (ir1 + ir2)._cast(e.type);
3602         }
3603 
3604         override void visit(MinExp e)
3605         {
3606             IntRange ir1 = getIntRange(e.e1);
3607             IntRange ir2 = getIntRange(e.e2);
3608             range = (ir1 - ir2)._cast(e.type);
3609         }
3610 
3611         override void visit(DivExp e)
3612         {
3613             IntRange ir1 = getIntRange(e.e1);
3614             IntRange ir2 = getIntRange(e.e2);
3615 
3616             range = (ir1 / ir2)._cast(e.type);
3617         }
3618 
3619         override void visit(MulExp e)
3620         {
3621             IntRange ir1 = getIntRange(e.e1);
3622             IntRange ir2 = getIntRange(e.e2);
3623 
3624             range = (ir1 * ir2)._cast(e.type);
3625         }
3626 
3627         override void visit(ModExp e)
3628         {
3629             IntRange ir1 = getIntRange(e.e1);
3630             IntRange ir2 = getIntRange(e.e2);
3631 
3632             // Modding on 0 is invalid anyway.
3633             if (!ir2.absNeg().imin.negative)
3634             {
3635                 visit(cast(Expression)e);
3636                 return;
3637             }
3638             range = (ir1 % ir2)._cast(e.type);
3639         }
3640 
3641         override void visit(AndExp e)
3642         {
3643             IntRange result;
3644             bool hasResult = false;
3645             result.unionOrAssign(getIntRange(e.e1) & getIntRange(e.e2), hasResult);
3646 
3647             assert(hasResult);
3648             range = result._cast(e.type);
3649         }
3650 
3651         override void visit(OrExp e)
3652         {
3653             IntRange result;
3654             bool hasResult = false;
3655             result.unionOrAssign(getIntRange(e.e1) | getIntRange(e.e2), hasResult);
3656 
3657             assert(hasResult);
3658             range = result._cast(e.type);
3659         }
3660 
3661         override void visit(XorExp e)
3662         {
3663             IntRange result;
3664             bool hasResult = false;
3665             result.unionOrAssign(getIntRange(e.e1) ^ getIntRange(e.e2), hasResult);
3666 
3667             assert(hasResult);
3668             range = result._cast(e.type);
3669         }
3670 
3671         override void visit(ShlExp e)
3672         {
3673             IntRange ir1 = getIntRange(e.e1);
3674             IntRange ir2 = getIntRange(e.e2);
3675 
3676             range = (ir1 << ir2)._cast(e.type);
3677         }
3678 
3679         override void visit(ShrExp e)
3680         {
3681             IntRange ir1 = getIntRange(e.e1);
3682             IntRange ir2 = getIntRange(e.e2);
3683 
3684             range = (ir1 >> ir2)._cast(e.type);
3685         }
3686 
3687         override void visit(UshrExp e)
3688         {
3689             IntRange ir1 = getIntRange(e.e1).castUnsigned(e.e1.type);
3690             IntRange ir2 = getIntRange(e.e2);
3691 
3692             range = (ir1 >>> ir2)._cast(e.type);
3693         }
3694 
3695         override void visit(AssignExp e)
3696         {
3697             range = getIntRange(e.e2)._cast(e.type);
3698         }
3699 
3700         override void visit(CondExp e)
3701         {
3702             // No need to check e.econd; assume caller has called optimize()
3703             IntRange ir1 = getIntRange(e.e1);
3704             IntRange ir2 = getIntRange(e.e2);
3705             range = ir1.unionWith(ir2)._cast(e.type);
3706         }
3707 
3708         override void visit(VarExp e)
3709         {
3710             Expression ie;
3711             VarDeclaration vd = e.var.isVarDeclaration();
3712             if (vd && vd.range)
3713                 range = vd.range._cast(e.type);
3714             else if (vd && vd._init && !vd.type.isMutable() && (ie = vd.getConstInitializer()) !is null)
3715                 ie.accept(this);
3716             else
3717                 visit(cast(Expression)e);
3718         }
3719 
3720         override void visit(CommaExp e)
3721         {
3722             e.e2.accept(this);
3723         }
3724 
3725         override void visit(ComExp e)
3726         {
3727             IntRange ir = getIntRange(e.e1);
3728             range = IntRange(SignExtendedNumber(~ir.imax.value, !ir.imax.negative), SignExtendedNumber(~ir.imin.value, !ir.imin.negative))._cast(e.type);
3729         }
3730 
3731         override void visit(NegExp e)
3732         {
3733             IntRange ir = getIntRange(e.e1);
3734             range = (-ir)._cast(e.type);
3735         }
3736     }
3737 
3738     scope IntRangeVisitor v = new IntRangeVisitor();
3739     e.accept(v);
3740     return v.range;
3741 }