Browse Source

allow catching abstracts by using their underlying type (closes #2619)

Simon Krajewski 11 years ago
parent
commit
b990544e46
2 changed files with 42 additions and 5 deletions
  1. 34 0
      tests/unit/issues/Issue2619.hx
  2. 8 5
      typer.ml

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

@@ -0,0 +1,34 @@
+package unit.issues;
+import unit.Test;
+
+private abstract A(String) {
+	public function new(s) this = s;
+}
+
+private abstract B(String) {
+	public function new(s) this = s;
+}
+
+class Issue2619 extends Test {
+	function test() {
+		var s:String = try {
+			throw "foo";
+		} catch(e:A) {
+			e;
+		}
+		eq("foo", s);
+		
+		var s:String = try {
+			throw new A("foo");
+		} catch(e:String) {
+			e;
+		}
+		eq("foo", s);
+		
+		t(unit.TestType.typeError(
+			try { }
+			catch(e:A) { }
+			catch(e:B) { }
+		));
+	}
+}

+ 8 - 5
typer.ml

@@ -2825,17 +2825,20 @@ and type_expr ctx (e,p) (with_type:with_type) =
 		in
 		in
 		let catches = List.fold_left (fun acc (v,t,e) ->
 		let catches = List.fold_left (fun acc (v,t,e) ->
 			let t = Typeload.load_complex_type ctx (pos e) t in
 			let t = Typeload.load_complex_type ctx (pos e) t in
-			let name = (match follow t with
+			let rec loop t = match follow t with
 				| TInst ({ cl_path = path },params) | TEnum ({ e_path = path },params) ->
 				| TInst ({ cl_path = path },params) | TEnum ({ e_path = path },params) ->
 					List.iter (fun pt ->
 					List.iter (fun pt ->
 						if pt != t_dynamic then error "Catch class parameter must be Dynamic" p;
 						if pt != t_dynamic then error "Catch class parameter must be Dynamic" p;
 					) params;
 					) params;
 					(match path with
 					(match path with
 					| x :: _ , _ -> x
 					| x :: _ , _ -> x
-					| [] , name -> name)
-				| TDynamic _ -> ""
-				| _ -> error "Catch type must be a class" p
-			) in
+					| [] , name -> name),t
+				| TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) ->
+					loop (Codegen.Abstract.get_underlying_type a tl)
+				| TDynamic _ -> "",t
+				| _ -> error "Catch type must be a class, an enum or Dynamic" (pos e)
+			in
+			let name,t = loop t in
 			if v.[0] = '$' then display_error ctx "Catch variable names starting with a dollar are not allowed" p;
 			if v.[0] = '$' then display_error ctx "Catch variable names starting with a dollar are not allowed" p;
 			check_unreachable acc t (pos e);
 			check_unreachable acc t (pos e);
 			let locals = save_locals ctx in
 			let locals = save_locals ctx in