瀏覽代碼

run analyzer when a constant expression is required (closes #4977)

Simon Krajewski 9 年之前
父節點
當前提交
9883c8f8c9

+ 15 - 13
src/optimization/analyzer.ml

@@ -1113,6 +1113,18 @@ module Run = struct
 		) ctx.graph.g_var_infos;
 		let e = with_timer "analyzer-fusion" (fun () -> Fusion.apply ctx.com ctx.config e) in
 		let e = with_timer "analyzer-cleanup" (fun () -> Cleanup.apply ctx.com e) in
+		let e = if ctx.is_real_function then
+			e
+		else begin
+			(* Get rid of the wrapping function and its return expressions. *)
+			let rec loop first e = match e.eexpr with
+				| TReturn (Some e) -> e
+				| TFunction tf when first -> loop false tf.tf_expr
+				| TFunction _ -> e
+				| _ -> Type.map_expr (loop first) e
+			in
+			loop true e
+		end in
 		e
 
 	let roundtrip com config e =
@@ -1143,18 +1155,6 @@ module Run = struct
 			let actx,e = run_on_expr ctx.Typecore.com config e in
 			let e = Cleanup.reduce_control_flow ctx e in
 			if config.dot_debug then Debug.dot_debug actx c cf;
-			let e = if actx.is_real_function then
-				e
-			else begin
-				(* Get rid of the wrapping function and its return expressions. *)
-				let rec loop first e = match e.eexpr with
-					| TReturn (Some e) -> e
-					| TFunction tf when first -> loop false tf.tf_expr
-					| TFunction _ -> e
-					| _ -> Type.map_expr (loop first) e
-				in
-				loop true e
-			end in
 			cf.cf_expr <- Some e;
 		| _ -> ()
 
@@ -1197,4 +1197,6 @@ module Run = struct
 		let cfl = if config.optimize && config.purity_inference then Purity.infer com else [] in
 		List.iter (run_on_type ctx config) types;
 		List.iter (fun cf -> cf.cf_meta <- List.filter (fun (m,_,_) -> m <> Meta.Pure) cf.cf_meta) cfl
-end
+end
+;;
+Typecore.analyzer_run_on_expr_ref := (fun com e -> snd (Run.run_on_expr com (AnalyzerConfig.get_base_config com) e))

+ 4 - 1
src/optimization/analyzerTypes.ml

@@ -215,7 +215,10 @@ module Graph = struct
 
 	let get_var_info g v = match v.v_extra with
 		| Some(_,Some {eexpr = TConst (TInt i32)}) -> DynArray.get g.g_var_infos (Int32.to_int i32)
-		| _ -> assert false
+		| _ ->
+			prerr_endline "Unbound variable, please report this";
+			prerr_endline (Printer.s_tvar v);
+			assert false
 
 	let declare_var g v bb =
 		create_var_info g bb v

+ 1 - 0
src/typing/typecore.ml

@@ -156,6 +156,7 @@ let get_pattern_locals_ref : (typer -> Ast.expr -> Type.t -> (string, tvar * pos
 let get_constructor_ref : (typer -> tclass -> t list -> Ast.pos -> (t * tclass_field)) ref = ref (fun _ _ _ _ -> assert false)
 let cast_or_unify_ref : (typer -> t -> texpr -> Ast.pos -> texpr) ref = ref (fun _ _ _ _ -> assert false)
 let find_array_access_raise_ref : (typer -> tabstract -> tparams -> texpr -> texpr option -> pos -> (tclass_field * t * t * texpr * texpr option)) ref = ref (fun _ _ _ _ _ _ -> assert false)
+let analyzer_run_on_expr_ref : (Common.context -> texpr -> texpr) ref = ref (fun _ _ -> assert false)
 
 let string_source t = match follow t with
 	| TInst(c,_) -> List.map (fun cf -> cf.cf_name) c.cl_ordered_fields

+ 6 - 2
src/typing/typeload.ml

@@ -2182,7 +2182,11 @@ module ClassInitializer = struct
 					cctx.context_init();
 					if ctx.com.verbose then Common.log ctx.com ("Typing " ^ (if ctx.in_macro then "macro " else "") ^ s_type_path c.cl_path ^ "." ^ cf.cf_name);
 					let e = type_var_field ctx t e fctx.is_static p in
-					let require_constant_expression e msg = match Optimizer.make_constant_expression ctx e with
+					let maybe_run_analyzer e = match e.eexpr with
+						| TConst _ | TLocal _ | TFunction _ -> e
+						| _ -> !analyzer_run_on_expr_ref ctx.com e
+					in
+					let require_constant_expression e msg = match Optimizer.make_constant_expression ctx (maybe_run_analyzer e) with
 						| Some e -> e
 						| None -> display_error ctx msg p; e
 					in
@@ -2199,7 +2203,7 @@ module ClassInitializer = struct
 						(* disallow initialization of non-physical fields (issue #1958) *)
 						display_error ctx "This field cannot be initialized because it is not a real variable" p; e
 					| Var v when not fctx.is_static ->
-						let e = match Optimizer.make_constant_expression ctx e with
+						let e = match Optimizer.make_constant_expression ctx (maybe_run_analyzer e) with
 							| Some e -> e
 							| None ->
 								let rec has_this e = match e.eexpr with

+ 31 - 0
tests/unit/src/unit/issues/Issue4977.hx

@@ -0,0 +1,31 @@
+package unit.issues;
+
+private abstract Progress(Int) to Int {
+	public var isEof(get, never):Bool;
+
+	inline function get_isEof()
+		return this < 0;
+
+	public var bytes(get, never):Int;
+
+	inline function get_bytes():Int
+		return (this < 0) ? 0 : this;
+
+	inline function new(v) this = v;
+
+	static public inline function by(amount:Int)
+		return new Progress(amount);
+
+	@:to inline function toBool():Bool
+		return this > 0;
+
+	static public inline var EOF:Progress = new Progress(-1);
+	static public inline var NONE:Progress = new Progress(0);
+}
+
+class Issue4977 extends Test {
+	function test() {
+		eq(-1, Progress.EOF);
+		eq(0, Progress.NONE);
+	}
+}