Browse Source

[typer] allow uninitialized final on abstract classes

see #10139
Simon Krajewski 4 years ago
parent
commit
a1fd2f705c
3 changed files with 24 additions and 2 deletions
  1. 4 1
      src/typing/fields.ml
  2. 1 1
      src/typing/typeloadFields.ml
  3. 19 0
      tests/unit/src/unit/issues/Issue10139.hx

+ 4 - 1
src/typing/fields.ml

@@ -240,8 +240,11 @@ let field_access ctx mode f fh e pfield =
 		| AccInline ->
 			normal true
 		| AccCtor ->
+			let is_child_of_abstract c =
+				has_class_flag c CAbstract && extends ctx.curclass c
+			in
 			(match ctx.curfun, fh with
-				| FunConstructor, FHInstance(c,_) when c == ctx.curclass -> normal false
+				| FunConstructor, FHInstance(c,_) when c == ctx.curclass || is_child_of_abstract c -> normal false
 				| _ -> AKNo f.cf_name
 			)
 		| AccRequire (r,msg) ->

+ 1 - 1
src/typing/typeloadFields.ml

@@ -1721,7 +1721,7 @@ let init_class ctx c p context_init herits fields =
 		else
 			ensure_struct_init_constructor ctx c fields p;
 	begin match cctx.uninitialized_final with
-		| cf :: cfl when c.cl_constructor = None ->
+		| cf :: cfl when c.cl_constructor = None && not (has_class_flag c CAbstract) ->
 			if Diagnostics.is_diagnostics_run ctx.com cf.cf_name_pos then begin
 				let diag = {
 					mf_pos = c.cl_name_pos;

+ 19 - 0
tests/unit/src/unit/issues/Issue10139.hx

@@ -0,0 +1,19 @@
+package unit.issues;
+
+import utest.Assert;
+
+private abstract class A { // This class has uninitialized final vars, which requires a constructor
+	public final x:Int; // Example of an uninitialized final var
+}
+
+private class B extends A {
+	public function new() {
+		x = 10; // Cannot access field or identifier x for writing
+	}
+}
+
+class Issue10139 extends Test {
+	function test() {
+		eq(10, new B().x);
+	}
+}