ソースを参照

[typer] deal with `extern` on enum abstract vars

Also deal with visibility conflicts while we're at it.

closes #8828
Simon Krajewski 6 年 前
コミット
f2aafacec4

+ 30 - 1
src/typing/typeloadFields.ml

@@ -326,6 +326,11 @@ type enum_abstract_mode =
 	| EAInt of int ref
 	| EAOther
 
+type enum_constructor_visibility =
+	| VUnknown
+	| VPublic of placed_access
+	| VPrivate of placed_access
+
 let build_enum_abstract ctx c a fields p =
 	let mode =
 		if does_unify a.a_this ctx.t.tint then EAInt (ref 0)
@@ -335,7 +340,31 @@ let build_enum_abstract ctx c a fields p =
 	List.iter (fun field ->
 		match field.cff_kind with
 		| FVar(ct,eo) when not (List.mem_assoc AStatic field.cff_access) ->
-			field.cff_access <- [AStatic,null_pos; if (List.mem_assoc APrivate field.cff_access) then (APrivate,null_pos) else (APublic,null_pos)];
+			let check_visibility_conflict visibility p1 =
+				match visibility with
+				| VUnknown ->
+					()
+				| VPublic(access,p2) | VPrivate(access,p2) ->
+					display_error ctx (Printf.sprintf "Conflicting access modifier %s" (Ast.s_access access)) p1;
+					display_error ctx "Conflicts with this" p2;
+			in
+			let rec loop visibility acc = match acc with
+				| (AExtern,p) :: acc ->
+					display_error ctx "extern modifier is not allowed on enum abstract fields" p;
+					loop visibility acc
+				| (APrivate,p) as access :: acc ->
+					check_visibility_conflict visibility p;
+					loop (VPrivate access) acc
+				| (APublic,p) as access :: acc ->
+					check_visibility_conflict visibility p;
+					loop (VPublic access) acc
+				| _ :: acc ->
+					loop visibility acc
+				| [] ->
+					visibility
+			in
+			let visibility = loop VUnknown field.cff_access in
+			field.cff_access <- [AStatic,null_pos; match visibility with VPublic acc | VPrivate acc -> acc | VUnknown -> (APublic,null_pos)];
 			field.cff_meta <- (Meta.Enum,[],null_pos) :: (Meta.Impl,[],null_pos) :: field.cff_meta;
 			let ct = match ct with
 				| Some _ -> ct

+ 3 - 0
tests/misc/projects/Issue8828/Main1.hx

@@ -0,0 +1,3 @@
+enum abstract A(Int) {
+	extern var x = 1;
+}

+ 3 - 0
tests/misc/projects/Issue8828/Main2.hx

@@ -0,0 +1,3 @@
+enum abstract A(Int) {
+	public private var x = 1;
+}

+ 3 - 0
tests/misc/projects/Issue8828/Main3.hx

@@ -0,0 +1,3 @@
+enum abstract A(Int) {
+	private public var x = 1;
+}

+ 2 - 0
tests/misc/projects/Issue8828/compile1-fail.hxml

@@ -0,0 +1,2 @@
+-main Main1
+-js bin/test.js

+ 1 - 0
tests/misc/projects/Issue8828/compile1-fail.hxml.stderr

@@ -0,0 +1 @@
+Main1.hx:2: characters 2-8 : extern modifier is not allowed on enum abstract fields

+ 2 - 0
tests/misc/projects/Issue8828/compile2-fail.hxml

@@ -0,0 +1,2 @@
+-main Main2
+-js bin/test.js

+ 2 - 0
tests/misc/projects/Issue8828/compile2-fail.hxml.stderr

@@ -0,0 +1,2 @@
+Main2.hx:2: characters 9-16 : Conflicting access modifier public
+Main2.hx:2: characters 2-8 : Conflicts with this

+ 2 - 0
tests/misc/projects/Issue8828/compile3-fail.hxml

@@ -0,0 +1,2 @@
+-main Main3
+-js bin/test.js

+ 2 - 0
tests/misc/projects/Issue8828/compile3-fail.hxml.stderr

@@ -0,0 +1,2 @@
+Main3.hx:2: characters 10-16 : Conflicting access modifier private
+Main3.hx:2: characters 2-9 : Conflicts with this