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 }