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