ソースを参照

[typer] bring back previous int iterator restrictions

closes #7734
fixes nadako
Simon Krajewski 6 年 前
コミット
3c77e0f0c8

+ 18 - 0
src/typing/forLoop.ml

@@ -162,6 +162,19 @@ module IterationKind = struct
 		let get_array_length arr p =
 		let get_array_length arr p =
 			mk (mk_field arr "length") ctx.com.basic.tint p
 			mk (mk_field arr "length") ctx.com.basic.tint p
 		in
 		in
+		let check_loop_var_modification vl e =
+			let rec loop e =
+				match e.eexpr with
+				| TBinop (OpAssign,{ eexpr = TLocal l },_)
+				| TBinop (OpAssignOp _,{ eexpr = TLocal l },_)
+				| TUnop (Increment,_,{ eexpr = TLocal l })
+				| TUnop (Decrement,_,{ eexpr = TLocal l })  when List.memq l vl ->
+					error "Loop variable cannot be modified" e.epos
+				| _ ->
+					Type.iter loop e
+			in
+			loop e
+		in
 		let gen_int_iter e1 pt f_get f_length =
 		let gen_int_iter e1 pt f_get f_length =
 			let index = gen_local ctx t_int v.v_pos in
 			let index = gen_local ctx t_int v.v_pos in
 			index.v_meta <- (Meta.ForLoopVariable,[],null_pos) :: index.v_meta;
 			index.v_meta <- (Meta.ForLoopVariable,[],null_pos) :: index.v_meta;
@@ -192,6 +205,8 @@ module IterationKind = struct
 		in
 		in
 		match iterator.it_kind with
 		match iterator.it_kind with
 		| IteratorIntUnroll(offset,length,ascending) ->
 		| IteratorIntUnroll(offset,length,ascending) ->
+			check_loop_var_modification [v] e2;
+			if not ascending then error "Cannot iterate backwards" p;
 			let el = ExtList.List.init length (fun i ->
 			let el = ExtList.List.init length (fun i ->
 				let ei = make_int ctx.t (if ascending then i + offset else offset - i) p in
 				let ei = make_int ctx.t (if ascending then i + offset else offset - i) p in
 				let rec loop e = match e.eexpr with
 				let rec loop e = match e.eexpr with
@@ -203,6 +218,8 @@ module IterationKind = struct
 			) in
 			) in
 			mk (TBlock el) t_void p
 			mk (TBlock el) t_void p
 		| IteratorIntConst(a,b,ascending) ->
 		| IteratorIntConst(a,b,ascending) ->
+			check_loop_var_modification [v] e2;
+			if not ascending then error "Cannot iterate backwards" p;
 			let v_index = gen_local ctx t_int p in
 			let v_index = gen_local ctx t_int p in
 			let evar_index = mk (TVar(v_index,Some a)) t_void p in
 			let evar_index = mk (TVar(v_index,Some a)) t_void p in
 			let ev_index = make_local v_index p in
 			let ev_index = make_local v_index p in
@@ -217,6 +234,7 @@ module IterationKind = struct
 				ewhile;
 				ewhile;
 			]) t_void p
 			]) t_void p
 		| IteratorInt(a,b) ->
 		| IteratorInt(a,b) ->
+			check_loop_var_modification [v] e2;
 			let v_index = gen_local ctx t_int p in
 			let v_index = gen_local ctx t_int p in
 			let evar_index = mk (TVar(v_index,Some a)) t_void p in
 			let evar_index = mk (TVar(v_index,Some a)) t_void p in
 			let ev_index = make_local v_index p in
 			let ev_index = make_local v_index p in

+ 7 - 0
tests/misc/projects/Issue7734/Main.hx

@@ -0,0 +1,7 @@
+class Main {
+	static public function main() {
+		for (i in 0...10) {
+			i++;
+		}
+	}
+}

+ 2 - 0
tests/misc/projects/Issue7734/compile-fail.hxml

@@ -0,0 +1,2 @@
+--main Main
+--interp

+ 1 - 0
tests/misc/projects/Issue7734/compile-fail.hxml.stderr

@@ -0,0 +1 @@
+Main.hx:4: characters 4-7 : Loop variable cannot be modified