Browse Source

infer CfModifiesThis field flag (fixes #9067)

Aleksandr Kuzmenko 5 years ago
parent
commit
078c3579f7

+ 6 - 0
extra/CHANGES.txt

@@ -1,3 +1,9 @@
+2020-XX-XX: 4.0.X
+
+	Bugfixes:
+
+	all : emit an error on an attempt to modify abstract `this` through a chain of inlined calls in a non-inlined method (#9067)
+
 2019-12-17: 4.0.5
 2019-12-17: 4.0.5
 
 
 	Bugfixes:
 	Bugfixes:

+ 5 - 2
src/typing/calls.ml

@@ -71,10 +71,13 @@ let make_call ctx e params t ?(force_inline=false) p =
 				if
 				if
 					f.cf_name <> "_new"
 					f.cf_name <> "_new"
 					&& has_meta Meta.This v_meta
 					&& has_meta Meta.This v_meta
-					&& not (assign_to_this_is_allowed ctx)
 					&& has_class_field_flag f CfModifiesThis
 					&& has_class_field_flag f CfModifiesThis
 				then
 				then
-					error ("Abstract 'this' value can only be modified inside an inline function. '" ^ f.cf_name ^ "' modifies 'this'") p;
+					if assign_to_this_is_allowed ctx then
+						(* Current method needs to infer CfModifiesThis flag, since we are calling a method, which modifies `this` *)
+						add_class_field_flag ctx.curfield CfModifiesThis
+					else
+						error ("Abstract 'this' value can only be modified inside an inline function. '" ^ f.cf_name ^ "' modifies 'this'") p;
 			| _ -> ()
 			| _ -> ()
 		);
 		);
 		let params = List.map (ctx.g.do_optimize ctx) params in
 		let params = List.map (ctx.g.do_optimize ctx) params in

+ 27 - 0
tests/misc/projects/Issue9067/Main.hx

@@ -0,0 +1,27 @@
+class Main {
+	static function main() {
+		trace(Foo.make());
+	}
+}
+
+abstract Foo(Int) from Int {
+	public static function make():Foo {
+		var foo:Foo = 0;
+		foo.init();
+		return foo;
+	}
+
+	var a(never, set):Int;
+	var b(never, set):Int;
+
+	function init():Foo {
+		a = 1;
+		return this;
+	}
+
+	inline function set_a(v)
+		return b = v;
+
+	inline function set_b(v)
+		return this = v;
+}

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

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

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

@@ -0,0 +1 @@
+Main.hx:18: characters 3-8 : Abstract 'this' value can only be modified inside an inline function. 'set_a' modifies 'this'