Browse Source

properly deal with unification in type patterns (closes #2776)

Simon Krajewski 11 years ago
parent
commit
ae663c934c
3 changed files with 62 additions and 9 deletions
  1. 27 8
      matcher.ml
  2. 1 1
      tests/unit/TestType.hx
  3. 34 0
      tests/unit/issues/Issue2776.hx

+ 27 - 8
matcher.ml

@@ -170,6 +170,25 @@ let any = mk_any t_dynamic Ast.null_pos
 
 let fake_tuple_type = TInst(mk_class null_module ([],"-Tuple") null_pos, [])
 
+let mk_type_pat ctx mt t p =
+	let rec loop = function
+		| TClassDecl _ -> "Class"
+		| TEnumDecl _ -> "Enum"
+		| TAbstractDecl a when Meta.has Meta.RuntimeValue a.a_meta -> "Class"
+		| TTypeDecl t ->
+			begin match follow (monomorphs t.t_types t.t_type) with
+				| TInst(c,_) -> loop (TClassDecl c)
+				| TEnum(en,_) -> loop (TEnumDecl en)
+				| TAbstract(a,_) -> loop (TAbstractDecl a)
+				| _ -> error "Cannot use this type as a value" p
+			end
+		| _ -> error "Cannot use this type as a value" p
+	in
+	let tcl = Typeload.load_instance ctx {tname=loop mt;tpackage=[];tsub=None;tparams=[]} p true in
+	let t2 = match tcl with TAbstract(a,_) -> TAbstract(a,[mk_mono()]) | _ -> assert false in
+	unify ctx t t2 p;
+	mk_con_pat (CType mt) [] t2 p
+
 let mk_subs st con =
 	let map = match follow st.st_type with
 		| TInst(c,pl) -> apply_params c.cl_types pl
@@ -327,8 +346,10 @@ let to_pattern ctx e t =
 			let e = type_expr ctx e (WithType t) in
 			let e = match Optimizer.make_constant_expression ctx ~concat_strings:true e with Some e -> e | None -> e in
 			(match e.eexpr with
-			| TConst c | TCast({eexpr = TConst c},None) -> mk_con_pat (CConst c) [] t p
-			| TTypeExpr mt -> mk_con_pat (CType mt) [] t p
+			| TConst c | TCast({eexpr = TConst c},None) ->
+				mk_con_pat (CConst c) [] t p
+			| TTypeExpr mt ->
+				mk_type_pat ctx mt t p
 			| TField(_, FStatic(_,cf)) when is_value_type cf.cf_type ->
 				mk_con_pat (CExpr e) [] cf.cf_type p
 			| TField(_, FEnum(en,ef)) ->
@@ -427,14 +448,12 @@ let to_pattern ctx e t =
 							error (error_msg (Unify l)) p
 						end;
 						mk_con_pat (CEnum(en,ef)) [] t p
-                    | TConst c | TCast({eexpr = TConst c},None) ->
-                    	begin try unify_raise ctx ec.etype t ec.epos with Error (Unify _,_) -> raise Not_found end;
-                        unify ctx ec.etype t p;
+					| TConst c | TCast({eexpr = TConst c},None) ->
+						begin try unify_raise ctx ec.etype t ec.epos with Error (Unify _,_) -> raise Not_found end;
+						unify ctx ec.etype t p;
                         mk_con_pat (CConst c) [] t p
 					| TTypeExpr mt ->
-						let tcl = Typeload.load_instance ctx {tname="Class";tpackage=[];tsub=None;tparams=[]} p true in
-						let t2 = match tcl with TAbstract(a,_) -> TAbstract(a,[mk_mono()]) | _ -> assert false in
-						mk_con_pat (CType mt) [] t2 p
+						mk_type_pat ctx mt t p
 					| _ ->
 						raise Not_found);
 			with Not_found ->

+ 1 - 1
tests/unit/TestType.hx

@@ -19,7 +19,7 @@ class TestType extends Test {
 	static public macro function typedAs(actual:haxe.macro.Expr, expected:haxe.macro.Expr) {
 		var tExpected = haxe.macro.Context.typeof(expected);
 		var tActual = haxe.macro.Context.typeof(actual);
-		return haxe.macro.Context.parse("{Test.count++; eq('" +Std.string(tActual) + "', '" +Std.string(tExpected) + "');}", haxe.macro.Context.currentPos());
+		return haxe.macro.Context.parse("eq('" +Std.string(tActual) + "', '" +Std.string(tExpected) + "')", haxe.macro.Context.currentPos());
 	}
 
 	static public macro function typeError(e:haxe.macro.Expr) {

+ 34 - 0
tests/unit/issues/Issue2776.hx

@@ -0,0 +1,34 @@
+package unit.issues;
+import unit.Test;
+
+class Issue2776 extends Test {
+	function test() {
+		var type = null;
+		switch(type) {
+			case String:
+			case Int:
+		}
+		unit.TestType.typedAs(type, getClassT());
+		
+		var type = null;
+		switch(type) {
+			case haxe.macro.Expr.ExprDef:
+			case haxe.macro.Expr.Constant:
+		}
+		unit.TestType.typedAs(type, getEnumT());
+		
+		var type = null;
+		t(unit.TestType.typeError(switch(type) {
+			case String:
+			case haxe.macro.Expr.ExprDef:
+		}));
+	}
+	
+	static function getClassT<T>():Class<T> {
+		return (null : Class<T>);
+	}
+	
+	static function getEnumT<T>():Enum<T> {
+		return (null : Enum<T>);
+	}
+}