1 module d.semantic.caster;
2 
3 import d.semantic.semantic;
4 import d.semantic.typepromotion;
5 
6 import d.ir.expression;
7 import d.ir.symbol;
8 import d.ir.type;
9 
10 import source.location;
11 
12 import source.exception;
13 
14 Expression buildImplicitCast(SemanticPass pass, Location location, Type to,
15                              Expression e) {
16 	return buildCast!false(pass, location, to, e);
17 }
18 
19 Expression buildExplicitCast(SemanticPass pass, Location location, Type to,
20                              Expression e) {
21 	return buildCast!true(pass, location, to, e);
22 }
23 
24 CastKind implicitCastFrom(SemanticPass pass, Type from, Type to) {
25 	return ImplicitCaster(pass, to).castFrom(from);
26 }
27 
28 CastKind explicitCastFrom(SemanticPass pass, Type from, Type to) {
29 	return ExplicitCaster(pass, to).castFrom(from);
30 }
31 
32 private:
33 
34 // Conflict with Interface in object.di
35 alias Interface = d.ir.symbol.Interface;
36 
37 Expression buildCast(bool isExplicit)(SemanticPass pass, Location location,
38                                       Type to, Expression e) in {
39 	assert(e, "Expression must not be null");
40 } do {
41 	// If the expression is polysemous, we try the several meaning and
42 	// exclude the ones that make no sense.
43 	if (auto asPolysemous = cast(PolysemousExpression) e) {
44 		Expression casted;
45 		foreach (candidate; asPolysemous.expressions) {
46 			candidate = buildCast!isExplicit(pass, location, to, candidate);
47 
48 			import d.ir.error;
49 			if (cast(ErrorExpression) candidate) {
50 				continue;
51 			}
52 
53 			if (casted) {
54 				return new CompileError(location, "Ambiguous").expression;
55 			}
56 
57 			casted = candidate;
58 		}
59 
60 		if (casted) {
61 			return casted;
62 		}
63 
64 		import d.ir.error;
65 		return new CompileError(location, "No match found").expression;
66 	}
67 
68 	// When casting an array literal, we try to push down the
69 	// cast to each element of the literal.
70 	if (auto al = cast(ArrayLiteral) e) {
71 		switch (to.kind) with (TypeKind) {
72 			case Array:
73 				if (al.values.length != to.size) {
74 					import d.ir.error;
75 					return
76 						new CompileError(al.location, "Incorrect element count")
77 							.expression;
78 				}
79 
80 				goto case;
81 
82 			case Slice:
83 				import std.algorithm, std.array;
84 				auto et = to.element;
85 				auto values = al.values
86 					.map!(v => buildCast!isExplicit(pass, location, et, v))
87 					.array();
88 				return build!ArrayLiteral(e.location, to, values);
89 
90 			default:
91 				break;
92 		}
93 	}
94 
95 	auto kind = Caster!(isExplicit, delegate CastKind(c, t) {
96 		alias T = typeof(t);
97 		static if (is(T : Aggregate)) {
98 			static struct AliasThisResult {
99 				Expression expr;
100 				CastKind level;
101 			}
102 
103 			auto level = CastKind.Invalid;
104 			enum InvalidResult = AliasThisResult(null, CastKind.Invalid);
105 
106 			import d.semantic.aliasthis;
107 			import std.algorithm;
108 			auto results = AliasThisResolver!((identified) {
109 				alias T = typeof(identified);
110 				static if (is(T : Expression)) {
111 					auto oldE = e;
112 					scope(exit) e = oldE;
113 					e = identified;
114 
115 					auto cLevel = c.castFrom(identified.type, to);
116 					if (cLevel == CastKind.Invalid || cLevel < level) {
117 						return InvalidResult;
118 					}
119 
120 					level = cLevel;
121 					return AliasThisResult(identified, cLevel);
122 				} else {
123 					return InvalidResult;
124 				}
125 			})(pass).resolve(e, t).filter!(r => r.level == level);
126 
127 			if (level == CastKind.Invalid) {
128 				return CastKind.Invalid;
129 			}
130 
131 			Expression candidate;
132 			foreach (r; results) {
133 				if (candidate !is null) {
134 					return CastKind.Invalid;
135 				}
136 
137 				candidate = r.expr;
138 			}
139 
140 			assert(candidate,
141 			       "if no candidate are found, level should be Invalid");
142 
143 			e = candidate;
144 			return level;
145 		} else static if (is(T : BuiltinType)) {
146 			auto to = c.to;
147 			if (to.kind != TypeKind.Builtin
148 				    || !canConvertToIntegral(to.builtin)) {
149 				return CastKind.Invalid;
150 			}
151 
152 			assert(getSize(to.builtin) < getSize(t));
153 
154 			import d.semantic.vrp;
155 			return ValueRangePropagator!uint(pass).canFit(e, to)
156 				? CastKind.Trunc
157 				: CastKind.Invalid;
158 		} else {
159 			return CastKind.Invalid;
160 		}
161 	})(pass, to).castFrom(e.type);
162 
163 	switch (kind) with (CastKind) {
164 		case Exact:
165 			// FIXME: Because we don't cast type qualifier the proper
166 			// way, we need to make sure they match.
167 			e.type = e.type.qualify(to.qualifier);
168 			return e;
169 
170 		default:
171 			return new CastExpression(location, kind, to, e);
172 
173 		case Invalid:
174 			if (to.kind == TypeKind.Error) {
175 				return to.error.expression;
176 			}
177 
178 			import d.ir.error;
179 			if (auto ee = cast(ErrorExpression) e) {
180 				return ee;
181 			}
182 
183 			return new CompileError(location, "Can't cast "
184 				~ e.type.toString(pass.context) ~ " to "
185 				~ to.toString(pass.context)).expression;
186 	}
187 }
188 
189 alias ExplicitCaster = Caster!true;
190 alias ImplicitCaster = Caster!false;
191 
192 struct Caster(bool isExplicit, alias bailoutOverride = null) {
193 	// XXX: Used only to get to super class, should probably go away.
194 	private SemanticPass pass;
195 	alias pass this;
196 
197 	Type to;
198 
199 	this(SemanticPass pass, Type to) {
200 		this.pass = pass;
201 		this.to = to;
202 	}
203 
204 	enum hasBailoutOverride = !is(typeof(bailoutOverride) : typeof(null));
205 
206 	CastKind bailout(T)(T t) {
207 		static if (hasBailoutOverride) {
208 			return bailoutOverride(this, t);
209 		} else {
210 			return CastKind.Invalid;
211 		}
212 	}
213 
214 	CastKind bailoutDefault(T)(T t) {
215 		return CastKind.Invalid;
216 	}
217 
218 	CastKind castFrom(ParamType from, ParamType to) {
219 		if (from.isRef != to.isRef) {
220 			return CastKind.Invalid;
221 		}
222 
223 		auto k = castFrom(from.getType(), to.getType());
224 		if (from.isRef && k < CastKind.Qual) {
225 			return CastKind.Invalid;
226 		}
227 
228 		return k;
229 	}
230 
231 	// FIXME: handle qualifiers.
232 	CastKind castFrom(Type from) {
233 		from = from.getCanonical();
234 		to = to.getCanonical();
235 
236 		if (from == to) {
237 			return CastKind.Exact;
238 		}
239 
240 		return from.accept(this);
241 	}
242 
243 	CastKind castFrom(Type from, Type to) {
244 		this.to = to;
245 		return castFrom(from);
246 	}
247 
248 	CastKind visit(BuiltinType t) {
249 		if (isExplicit && to.kind == TypeKind.Enum) {
250 			to = to.getCanonicalAndPeelEnum();
251 			auto k = visit(t);
252 			return (k == CastKind.Exact) ? CastKind.Bit : k;
253 		}
254 
255 		// Can cast typeof(null) to class, pointer and function.
256 		if (t == BuiltinType.Null && to.hasPointerABI()) {
257 			return CastKind.Bit;
258 		}
259 
260 		// Can explicitely cast integral to pointer.
261 		if (isExplicit
262 			    && (to.kind == TypeKind.Pointer && canConvertToIntegral(t))) {
263 			return CastKind.IntToPtr;
264 		}
265 
266 		if (to.kind != TypeKind.Builtin) {
267 			return CastKind.Invalid;
268 		}
269 
270 		auto bt = to.builtin;
271 		if (t == bt) {
272 			return CastKind.Exact;
273 		}
274 
275 		final switch (t) with (BuiltinType) {
276 			case None:
277 			case Void:
278 				return CastKind.Invalid;
279 
280 			case Bool:
281 				if (isIntegral(bt)) {
282 					return CastKind.UPad;
283 				}
284 
285 				return CastKind.Invalid;
286 
287 			case Char:
288 				t = integralOfChar(t);
289 				goto case Ubyte;
290 
291 			case Wchar:
292 				t = integralOfChar(t);
293 				goto case Ushort;
294 
295 			case Dchar:
296 				t = integralOfChar(t);
297 				goto case Uint;
298 
299 			case Byte, Ubyte, Short, Ushort, Int, Uint, Long, Ulong, Cent,
300 			     Ucent:
301 				if (isExplicit && bt == Bool) {
302 					return CastKind.IntToBool;
303 				}
304 
305 				if (!isIntegral(bt)) {
306 					return CastKind.Invalid;
307 				}
308 
309 				auto ut = unsigned(t);
310 				bt = unsigned(bt);
311 				if (ut == bt) {
312 					return CastKind.Bit;
313 				} else if (ut < bt) {
314 					return isSigned(t) ? CastKind.SPad : CastKind.UPad;
315 				} else static if (isExplicit) {
316 					return CastKind.Trunc;
317 				} else {
318 					return bailout(t);
319 				}
320 
321 			case Float, Double, Real:
322 				assert(0, "Floating point casts are not implemented");
323 
324 			case Null:
325 				return CastKind.Invalid;
326 		}
327 	}
328 
329 	CastKind visitPointerOf(Type t) {
330 		// You can explicitely cast pointer to class, function.
331 		if (isExplicit && to.kind != TypeKind.Pointer && to.hasPointerABI()) {
332 			return CastKind.Bit;
333 		}
334 
335 		// It is also possible to cast to integral explicitely.
336 		if (isExplicit && to.kind == TypeKind.Builtin) {
337 			if (canConvertToIntegral(to.builtin)) {
338 				return CastKind.PtrToInt;
339 			}
340 		}
341 
342 		if (to.kind != TypeKind.Pointer) {
343 			return CastKind.Invalid;
344 		}
345 
346 		auto e = to.element.getCanonical();
347 
348 		// Cast to void* is kind of special.
349 		if (e.kind == TypeKind.Builtin && e.builtin == BuiltinType.Void) {
350 			return (isExplicit || canConvert(t.qualifier, e.qualifier))
351 				? CastKind.Bit
352 				: CastKind.Invalid;
353 		}
354 
355 		auto subCast = castFrom(t, e);
356 		switch (subCast) with (CastKind) {
357 			case Qual:
358 				if (canConvert(t.qualifier, e.qualifier)) {
359 					return Qual;
360 				}
361 
362 				goto default;
363 
364 			case Exact:
365 				return Qual;
366 
367 			static if (isExplicit) {
368 				default:
369 					return Bit;
370 			} else {
371 				case Bit:
372 					if (canConvert(t.qualifier, e.qualifier)) {
373 						return subCast;
374 					}
375 
376 					goto default;
377 
378 				default:
379 					return Invalid;
380 			}
381 		}
382 	}
383 
384 	CastKind visitSliceOf(Type t) {
385 		if (to.kind != TypeKind.Slice) {
386 			return CastKind.Invalid;
387 		}
388 
389 		auto e = to.element.getCanonical();
390 
391 		auto subCast = castFrom(t, e);
392 		switch (subCast) with (CastKind) {
393 			case Qual:
394 				if (canConvert(t.qualifier, e.qualifier)) {
395 					return Qual;
396 				}
397 
398 				goto default;
399 
400 			case Exact:
401 				return Qual;
402 
403 			static if (isExplicit) {
404 				default:
405 					return Bit;
406 			} else {
407 				case Bit:
408 					if (canConvert(t.qualifier, e.qualifier)) {
409 						return subCast;
410 					}
411 
412 					goto default;
413 
414 				default:
415 					return Invalid;
416 			}
417 		}
418 	}
419 
420 	CastKind visitArrayOf(uint size, Type t) {
421 		if (to.kind != TypeKind.Array) {
422 			return CastKind.Invalid;
423 		}
424 
425 		if (size != to.size) {
426 			return CastKind.Invalid;
427 		}
428 
429 		auto e = to.element.getCanonical();
430 
431 		auto subCast = castFrom(t, e);
432 		switch (subCast) with (CastKind) {
433 			case Qual:
434 				if (canConvert(t.qualifier, e.qualifier)) {
435 					return Qual;
436 				}
437 
438 				goto default;
439 
440 			case Exact:
441 				return Exact;
442 
443 			static if (isExplicit) {
444 				default:
445 					return Bit;
446 			} else {
447 				case Bit:
448 					if (canConvert(t.qualifier, e.qualifier)) {
449 						return subCast;
450 					}
451 
452 					goto default;
453 
454 				default:
455 					return Invalid;
456 			}
457 		}
458 	}
459 
460 	CastKind visit(Struct s) {
461 		if (to.kind == TypeKind.Struct) {
462 			if (to.dstruct is s) {
463 				return CastKind.Exact;
464 			}
465 		}
466 
467 		return bailout(s);
468 	}
469 
470 	private auto castClass(Class from, Class to) {
471 		if (from is to) {
472 			return CastKind.Exact;
473 		}
474 
475 		auto upcast = from;
476 
477 		// Stop at object.
478 		while (upcast !is upcast.base) {
479 			// Automagically promote to base type.
480 			upcast = upcast.base;
481 
482 			if (upcast is to) {
483 				return CastKind.Bit;
484 			}
485 		}
486 
487 		static if (isExplicit) {
488 			auto downcast = to;
489 
490 			// Stop at object.
491 			while (downcast !is downcast.base) {
492 				// Automagically promote to base type.
493 				downcast = downcast.base;
494 
495 				if (downcast is from) {
496 					return CastKind.Down;
497 				}
498 			}
499 		}
500 
501 		return CastKind.Invalid;
502 	}
503 
504 	CastKind visit(Class c) {
505 		if (isExplicit && to.kind == TypeKind.Pointer) {
506 			auto et = to.element.getCanonical();
507 			if (et.kind == TypeKind.Builtin && et.builtin == BuiltinType.Void) {
508 				return CastKind.Bit;
509 			}
510 		}
511 
512 		if (to.kind == TypeKind.Class) {
513 			scheduler.require(c, Step.Signed);
514 			auto kind = castClass(c, to.dclass);
515 			if (kind > CastKind.Invalid) {
516 				return kind;
517 			}
518 		}
519 
520 		return bailout(c);
521 	}
522 
523 	CastKind visit(Enum e) {
524 		if (to.kind == TypeKind.Enum) {
525 			if (e is to.denum) {
526 				return CastKind.Exact;
527 			}
528 		}
529 
530 		// Automagically promote to base type.
531 		return castFrom(e.type);
532 	}
533 
534 	CastKind visit(TypeAlias a) {
535 		return castFrom(a.type);
536 	}
537 
538 	CastKind visit(Interface i) {
539 		return CastKind.Invalid;
540 	}
541 
542 	CastKind visit(Union u) {
543 		return (to.kind == TypeKind.Union && to.dunion is u)
544 			? CastKind.Exact
545 			: CastKind.Invalid;
546 	}
547 
548 	CastKind visit(Function f) {
549 		assert(0, "Cast to context type do not make any sense.");
550 	}
551 
552 	CastKind visit(Type[] seq) {
553 		assert(0, "Cast to sequence type do not make any sense.");
554 	}
555 
556 	CastKind visit(FunctionType f) {
557 		if (to.kind == TypeKind.Pointer && f.contexts.length == 0) {
558 			auto e = to.element.getCanonical();
559 			static if (isExplicit) {
560 				return CastKind.Bit;
561 			} else if (e.kind == TypeKind.Builtin
562 				           && e.builtin == BuiltinType.Void) {
563 				// FIXME: qualifier.
564 				return CastKind.Bit;
565 			} else {
566 				return CastKind.Invalid;
567 			}
568 		}
569 
570 		if (to.kind != TypeKind.Function) {
571 			return CastKind.Invalid;
572 		}
573 
574 		auto tf = to.asFunctionType();
575 
576 		if (f.contexts.length != tf.contexts.length) {
577 			return CastKind.Invalid;
578 		}
579 
580 		enum onFail = isExplicit ? CastKind.Bit : CastKind.Invalid;
581 
582 		if (f.parameters.length != tf.parameters.length) {
583 			return onFail;
584 		}
585 
586 		if (f.isVariadic != tf.isVariadic) {
587 			return onFail;
588 		}
589 
590 		if (f.linkage != tf.linkage) {
591 			return onFail;
592 		}
593 
594 		auto k = castFrom(f.returnType, tf.returnType);
595 		if (k < CastKind.Bit) {
596 			return onFail;
597 		}
598 
599 		import std.range;
600 		foreach (fromc, toc; lockstep(f.contexts, tf.contexts)) {
601 			// ref context decay to void*
602 			if (fromc.isRef && !toc.isRef && toc.kind == TypeKind.Pointer) {
603 				auto e = toc.getType().element;
604 				if (e.kind == TypeKind.Builtin
605 					    && e.builtin == BuiltinType.Void) {
606 					k = CastKind.Bit;
607 					continue;
608 				}
609 			}
610 
611 			// Contexts are covariant.
612 			auto kc = castFrom(fromc, toc);
613 			if (kc < CastKind.Bit) {
614 				return onFail;
615 			}
616 
617 			import std.algorithm;
618 			k = min(k, kc);
619 		}
620 
621 		foreach (fromp, top; lockstep(f.parameters, tf.parameters)) {
622 			// Parameters are contrevariant.
623 			auto kp = castFrom(top, fromp);
624 			if (kp < CastKind.Bit) {
625 				return onFail;
626 			}
627 
628 			import std.algorithm;
629 			k = min(k, kp);
630 		}
631 
632 		return (k < CastKind.Exact) ? CastKind.Bit : CastKind.Exact;
633 	}
634 
635 	CastKind visit(Pattern p) {
636 		assert(0, "Pattern cannot be casted.");
637 	}
638 
639 	import d.ir.error;
640 	CastKind visit(CompileError e) {
641 		return CastKind.Invalid;
642 	}
643 }