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