Skip to content

Commit

Permalink
[typer] do not apply abstract field casts on static extensions
Browse files Browse the repository at this point in the history
closes #5924
  • Loading branch information
Simn committed Sep 10, 2018
1 parent adcb432 commit 109048e
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 19 deletions.
1 change: 1 addition & 0 deletions extra/CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ XXXX-XX-XX:
all : reworked CLI usage/help output (#6862)
all : implemented `for` loop unrolling (#3784)
all : metadata can now use `.`, e.g. `@:a.b`. This is represented as a string (#3959)
all : [breaking] disallow static extensions through abstract field casts (#5924)
all : [breaking] disallow static extensions on implicit `this` (#6036)
all : allow true and false expressions as type parameters (#6958)
all : improved display support in many areas
Expand Down
4 changes: 2 additions & 2 deletions src/context/display/displayFields.ml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ let collect_static_extensions ctx items e p =
| TFun((_,_,TType({t_path=["haxe";"macro"], "ExprOf"}, [t])) :: args, ret)
| TFun((_,_,t) :: args, ret) ->
begin try
unify_raise ctx (dup e.etype) t e.epos;
let e = TyperBase.unify_static_extension ctx {e with etype = dup e.etype} t p in
List.iter2 (fun m (name,t) -> match follow t with
| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] ->
List.iter (fun tc -> unify_raise ctx m (map tc) e.epos) constr
Expand All @@ -80,7 +80,7 @@ let collect_static_extensions ctx items e p =
let item = make_ci_class_field (CompletionClassField.make f CFSMember origin true) (f.cf_type,ct) in
PMap.add f.cf_name item acc
end
with Error (Unify _,_) ->
with Error (Unify _,_) | Unify_error _ ->
acc
end
| _ ->
Expand Down
2 changes: 1 addition & 1 deletion src/typing/fields.ml
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ let rec using_field ctx mode e i p =
begin match follow t with
| TFun((_,_,(TType({t_path = ["haxe";"macro"],"ExprOf"},[t0]) | t0)) :: args,r) ->
if is_dynamic && follow t0 != t_dynamic then raise Not_found;
let e = AbstractCast.cast_or_unify_raise ctx t0 e p in
let e = unify_static_extension ctx e t0 p in
(* early constraints check is possible because e.etype has no monomorphs *)
List.iter2 (fun m (name,t) -> match follow t with
| TInst ({ cl_kind = KTypeParameter constr },_) when constr <> [] && not (has_mono m) ->
Expand Down
17 changes: 16 additions & 1 deletion src/typing/typerBase.ml
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,19 @@ let has_constructible_constraint ctx tl el p =
| TInst({cl_kind = KTypeParameter tl},_) -> List.exists loop tl
| _ -> false
in
List.exists loop tl
List.exists loop tl

let unify_static_extension ctx e t p =
let multitype_involed t1 t2 =
let check t = match follow t with
| TAbstract(a,_) when Meta.has Meta.MultiType a.a_meta -> true
| _ -> false
in
check t1 || check t2
in
if multitype_involed e.etype t then
AbstractCast.cast_or_unify_raise ctx t e p
else begin
Type.unify e.etype t;
e
end
47 changes: 47 additions & 0 deletions tests/display/src/cases/StaticExtension.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package cases;

class StaticExtension extends DisplayTestCase {
/**
using cases.StaticExtension.MyStaticExtension;
class Something {
static function test() {
var map = ["a" => 1];
map.{-1-}
}
}
class MyStaticExtension {
static public function doSomething(sm:haxe.ds.StringMap<Int>):Void { }
static public function doSomethingElse(sm:Map<String, Int>):Void { }
}
**/
function test1() {
var fields = fields(pos(1));
eq(true, hasField(fields, "doSomething", "Void -> Void"));
eq(true, hasField(fields, "doSomethingElse", "Void -> Void"));
}

/**
using cases.StaticExtension.MyStaticExtension;
class Something {
static function test() {
var map = new haxe.ds.StringMap();
map.{-1-}
}
}
class MyStaticExtension {
static public function doSomething(sm:haxe.ds.StringMap<Int>):Void { }
static public function doSomethingElse(sm:Map<String, Int>):Void { }
}
**/
function test2() {
var fields = fields(pos(1));
eq(true, hasField(fields, "doSomething", "Void -> Void"));
eq(true, hasField(fields, "doSomethingElse", "Void -> Void"));
}
}
21 changes: 21 additions & 0 deletions tests/misc/projects/Issue5924/Main.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Main;

class Main {
static function main() {
0.bar();
}

static function bar(f:Foo)
f.bar();
}

abstract Foo(String) {

inline function new(v) this = v;

@:from static function ofInt(i:Int)
return new Foo('$i');

public function bar() {};
public function baz() {};
}
2 changes: 2 additions & 0 deletions tests/misc/projects/Issue5924/compile-fail.hxml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-main Main
--interp
1 change: 1 addition & 0 deletions tests/misc/projects/Issue5924/compile-fail.hxml.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Main.hx:5: characters 9-14 : Int has no field bar
15 changes: 0 additions & 15 deletions tests/unit/src/unit/issues/Issue2152.hx

This file was deleted.

24 changes: 24 additions & 0 deletions tests/unit/src/unit/issues/Issue7142.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package unit.issues;

using unit.issues.Issue7142;

class Issue7142 extends unit.Test {
function test() {
var map = ["test" => 1];
var smap = new haxe.ds.StringMap();
smap.set("test", 1);

eq(1, map.doSomething());
eq(1, smap.doSomething());
eq(1, map.doSomethingElse());
eq(1, smap.doSomethingElse());
}

static function doSomething(sm:haxe.ds.StringMap<Int>) {
return sm.get("test");
}

static function doSomethingElse(sm:Map<String, Int>) {
return sm.get("test");
}
}

0 comments on commit 109048e

Please sign in to comment.