浏览代码

disallow explicit calls to constructors that only exist due to field initialization (closes #3596)

Simon Krajewski 10 年之前
父节点
当前提交
a45a46401c
共有 3 个文件被更改,包括 75 次插入1 次删除
  1. 73 0
      tests/unit/src/unit/issues/Issue3596.hx
  2. 1 1
      typeload.ml
  3. 1 0
      typer.ml

+ 73 - 0
tests/unit/src/unit/issues/Issue3596.hx

@@ -0,0 +1,73 @@
+package unit.issues;
+
+private class ClassWithInitButNoConstructor {
+	public var a = 1;
+}
+
+private class ClassWithInitButNoConstructorChild extends ClassWithInitButNoConstructor {
+	public var b = 2;
+}
+
+private class ClassWithInitAndConstructorChild extends ClassWithInitButNoConstructor {
+	public var b = 2;
+	public function new() {
+		super();
+	}
+}
+
+private class ClassWithConstructor {
+	public var a = 1;
+	public function new() {
+		a = 2;
+	}
+}
+
+private class ClassWithConstructorChild extends ClassWithConstructor {
+	public var b = 2;
+}
+
+private class ClassWithConstructorThatCalls {
+	public var a = 1;
+	public var b:Int;
+	public function new() {
+		init();
+	}
+
+	function init() {
+		b = a;
+	}
+}
+
+private class ClassWithConstructorThatCallsChild extends ClassWithConstructorThatCalls {
+	public var c = 2;
+	override function init() {
+		b = c;
+	}
+}
+
+class Issue3596 extends Test {
+	function test() {
+		t(unit.TestType.typeError(new ClassWithInitButNoConstructor()));
+		t(unit.TestType.typeError(new ClassWithInitButNoConstructorChild()));
+
+		var c = new ClassWithInitAndConstructorChild();
+		eq(1, c.a);
+		eq(2, c.b);
+
+		var c = new ClassWithConstructor();
+		eq(2, c.a);
+
+		var c = new ClassWithConstructorChild();
+		eq(2, c.a);
+		eq(2, c.b);
+
+		var c = new ClassWithConstructorThatCalls();
+		eq(1, c.a);
+		eq(1, c.b);
+
+		var c = new ClassWithConstructorThatCallsChild();
+		eq(1, c.a);
+		eq(2, c.b);
+		eq(2, c.c);
+	}
+}

+ 1 - 1
typeload.ml

@@ -1024,7 +1024,7 @@ let check_extends ctx c t p = match follow t with
 
 
 let rec add_constructor ctx c force_constructor p =
 let rec add_constructor ctx c force_constructor p =
 	match c.cl_constructor, c.cl_super with
 	match c.cl_constructor, c.cl_super with
-	| None, Some ({ cl_constructor = Some cfsup } as csup,cparams) when not c.cl_extern ->
+	| None, Some ({ cl_constructor = Some cfsup } as csup,cparams) when not c.cl_extern && not (Meta.has Meta.CompilerGenerated cfsup.cf_meta) ->
 		let cf = {
 		let cf = {
 			cfsup with
 			cfsup with
 			cf_pos = p;
 			cf_pos = p;

+ 1 - 0
typer.ml

@@ -3292,6 +3292,7 @@ and type_expr ctx (e,p) (with_type:with_type) =
 		in
 		in
 		let build_constructor_call c tl =
 		let build_constructor_call c tl =
 			let ct, f = get_constructor ctx c tl p in
 			let ct, f = get_constructor ctx c tl p in
+			if (Meta.has Meta.CompilerGenerated f.cf_meta) then display_error ctx (s_type_path c.cl_path ^ " does not have a constructor") p;
 			if not (can_access ctx c f true || is_parent c ctx.curclass) && not ctx.untyped then display_error ctx "Cannot access private constructor" p;
 			if not (can_access ctx c f true || is_parent c ctx.curclass) && not ctx.untyped then display_error ctx "Cannot access private constructor" p;
 			(match f.cf_kind with
 			(match f.cf_kind with
 			| Var { v_read = AccRequire (r,msg) } -> (match msg with Some msg -> error msg p | None -> error_require r p)
 			| Var { v_read = AccRequire (r,msg) } -> (match msg with Some msg -> error msg p | None -> error_require r p)