* reduce sequential unsafe casts * fix & test * "fix" cs & cpp * keep at least one cast for cpp, flash, jvm and cs+erase_generics * move to optimizer
@@ -532,4 +532,24 @@ let collect_captured_vars e =
Type.iter loop e
in
loop e;
- List.rev !unknown,!accesses_this
+ List.rev !unknown,!accesses_this
+
+(**
+ If `e` contains a sequence of unsafe casts, then look if that sequence
+ already has casts to `t` and return the bottom-most of such casts.
+ If `require_cast` is `false` and the first non-cast expression has type `t`, then return that expression without any casts.
+ In other cases return `e` as-is.
+*)
+let reduce_unsafe_casts ?(require_cast=false) e t =
+ let t = follow t in
+ let same_type etype = fast_eq t (follow etype) in
+ let rec loop e result =
+ match e.eexpr with
+ | TCast(subject,None) ->
+ if same_type e.etype then loop subject e
+ else loop subject result
+ | _ ->
+ if not require_cast && same_type e.etype then e
+ else result
+ in
+ loop e e
@@ -264,6 +264,15 @@ let reduce_control_flow ctx e = match e.eexpr with
| TEnumParameter({eexpr = TParenthesis {eexpr = TCall({eexpr = TField(_,FEnum(_,ef1))},el)}},ef2,i)
when ef1 == ef2 && check_enum_construction_args el i ->
(try List.nth el i with Failure _ -> e)
+ | TCast(e1,None) ->
+ (* TODO: figure out what's wrong with these targets *)
+ let require_cast = match ctx.com.platform with
+ | Cpp | Flash -> true
+ | Java -> defined ctx.com Define.Jvm
+ | Cs -> defined ctx.com Define.EraseGenerics
+ | _ -> false
+ Texpr.reduce_unsafe_casts ~require_cast e e.etype
| _ ->
e
@@ -547,8 +547,23 @@ class TestJs {
static function testIssue7874() {
if (v && v) {}
}
+ @:js('')
+ static function testIssue8751() {
+ (2:Issue8751Int) * 3;
+ }
extern class Extern {
static public function test(e:haxe.extern.AsVar<String>):Void;
+}
+abstract Issue8751Int(Int) from Int {
+ @:op(A * B) static public inline function add(a:Issue8751Int, b:Issue8751Int):Issue8751Int {
+ return a.toInt() * b.toInt();
+ inline public function toInt():Int {
+ return this;