瀏覽代碼

[filters] recurse into expressions of local statics

closes #11469
Simon Krajewski 1 年之前
父節點
當前提交
938aaa95f0
共有 2 個文件被更改,包括 46 次插入14 次删除
  1. 37 14
      src/filters/localStatic.ml
  2. 9 0
      tests/unit/src/unit/issues/Issue11469.hx

+ 37 - 14
src/filters/localStatic.ml

@@ -3,11 +3,18 @@ open Type
 open Typecore
 open Error
 
-let promote_local_static ctx lut v eo =
-	let name = Printf.sprintf "%s_%s" ctx.curfield.cf_name v.v_name in
+type lscontext = {
+	ctx : typer;
+	lut : (int,tclass_field) Hashtbl.t;
+	mutable added_fields : tclass_field list;
+}
+
+let promote_local_static lsctx run v eo =
+	let name = Printf.sprintf "%s_%s" lsctx.ctx.curfield.cf_name v.v_name in
+	let c = lsctx.ctx.curclass in
 	begin try
-		let cf = PMap.find name ctx.curclass.cl_statics in
-		display_error ctx.com (Printf.sprintf "The expanded name of this local (%s) conflicts with another static field" name) v.v_pos;
+		let cf = PMap.find name c.cl_statics in
+		display_error lsctx.ctx.com (Printf.sprintf "The expanded name of this local (%s) conflicts with another static field" name) v.v_pos;
 		raise_typing_error ~depth:1 "Conflicting field was found here" cf.cf_name_pos;
 	with Not_found ->
 		let cf = mk_field name ~static:true v.v_type v.v_pos v.v_pos in
@@ -16,34 +23,45 @@ let promote_local_static ctx lut v eo =
 		| None ->
 			()
 		| Some e ->
+			let no_local_in_static p =
+				raise_typing_error "Accessing local variables in static initialization is not allowed" p
+			in
 			let rec loop e = match e.eexpr with
-				| TLocal _ | TFunction _ ->
-					raise_typing_error "Accessing local variables in static initialization is not allowed" e.epos
+				| TLocal v when has_var_flag v VStatic ->
+					run e
+				| TFunction _ | TLocal _ ->
+					no_local_in_static e.epos
 				| TConst (TThis | TSuper) ->
 					raise_typing_error "Accessing `this` in static initialization is not allowed" e.epos
 				| TReturn _ | TBreak | TContinue ->
 					raise_typing_error "This kind of control flow in static initialization is not allowed" e.epos
 				| _ ->
-					iter loop e
+					map_expr loop e
 			in
-			loop e;
+			let e = loop e in
 			cf.cf_expr <- Some e
 		end;
-		TClass.add_field ctx.curclass cf;
-		Hashtbl.add lut v.v_id cf
+		lsctx.added_fields <- cf :: lsctx.added_fields;
+		(* Add to lookup early so that the duplication check works. *)
+		c.cl_statics <- PMap.add cf.cf_name cf c.cl_statics;
+		Hashtbl.add lsctx.lut v.v_id cf
 	end
 
 let find_local_static lut v =
 	Hashtbl.find lut v.v_id
 
 let run ctx e =
-	let local_static_lut = Hashtbl.create 0 in
+	let lsctx = {
+		ctx = ctx;
+		lut = Hashtbl.create 0;
+		added_fields = [];
+	} in
 	let c = ctx.curclass in
 	let rec run e = match e.eexpr with
 		| TBlock el ->
 			let el = ExtList.List.filter_map (fun e -> match e.eexpr with
 				| TVar(v,eo) when has_var_flag v VStatic ->
-					promote_local_static ctx local_static_lut v eo;
+					promote_local_static lsctx run v eo;
 					None
 				| _ ->
 					Some (run e)
@@ -51,7 +69,7 @@ let run ctx e =
 			{ e with eexpr = TBlock el }
 		| TLocal v when has_var_flag v VStatic ->
 			begin try
-				let cf = find_local_static local_static_lut v in
+				let cf = find_local_static lsctx.lut v in
 				Texpr.Builder.make_static_field c cf e.epos
 			with Not_found ->
 				raise_typing_error (Printf.sprintf "Could not find local static %s (id %i)" v.v_name v.v_id) e.epos
@@ -59,4 +77,9 @@ let run ctx e =
 		| _ ->
 			Type.map_expr run e
 	in
-	run e
+	let e = run e in
+	(* Add to ordered list in reverse order *)
+	List.iter (fun cf ->
+		c.cl_ordered_statics <- cf :: c.cl_ordered_statics
+	) lsctx.added_fields;
+	e

+ 9 - 0
tests/unit/src/unit/issues/Issue11469.hx

@@ -0,0 +1,9 @@
+package unit.issues;
+
+class Issue11469 extends Test {
+	function test() {
+		static var c = 10;
+		static var d = c + 1;
+		eq(11, d);
+	}
+}