瀏覽代碼

[typer] map `this` when restoring typed expressions

see #11212
Simon Krajewski 1 年之前
父節點
當前提交
6de366cef5

+ 0 - 4
src/context/typecore.ml

@@ -739,10 +739,6 @@ let get_next_stored_typed_expr_id =
 	let uid = ref 0 in
 	(fun() -> incr uid; !uid)
 
-let get_stored_typed_expr com id =
-	let e = com.stored_typed_exprs#find id in
-	Texpr.duplicate_tvars e
-
 let store_typed_expr com te p =
 	let id = get_next_stored_typed_expr_id() in
 	com.stored_typed_exprs#add id te;

+ 5 - 1
src/core/texpr.ml

@@ -307,7 +307,9 @@ let rec equal e1 e2 = match e1.eexpr,e2.eexpr with
 	| TEnumParameter(e1,ef1,i1),TEnumParameter(e2,ef2,i2) -> equal e1 e2 && ef1 == ef2 && i1 = i2
 	| _ -> false
 
-let duplicate_tvars e =
+let e_identity e = e
+
+let duplicate_tvars f_this e =
 	let vars = Hashtbl.create 0 in
 	let copy_var v =
 		let v2 = alloc_var v.v_kind v.v_name v.v_type v.v_pos in
@@ -344,6 +346,8 @@ let duplicate_tvars e =
 				{e with eexpr = TLocal v2}
 			with _ ->
 				e)
+		| TConst TThis ->
+			f_this e
 		| _ ->
 			map_expr build_expr e
 	in

+ 1 - 1
src/optimization/analyzerTexpr.ml

@@ -240,7 +240,7 @@ module TexprFilter = struct
 			let e_if eo = mk (TIf(e_not,e_break,eo)) com.basic.tvoid p in
 			let rec map_continue e = match e.eexpr with
 				| TContinue ->
-					Texpr.duplicate_tvars (e_if (Some e))
+					Texpr.duplicate_tvars e_identity (e_if (Some e))
 				| TWhile _ | TFor _ ->
 					e
 				| _ ->

+ 2 - 2
src/optimization/inline.ml

@@ -506,14 +506,14 @@ class inline_state ctx ethis params cf f p = object(self)
 						| VIInline ->
 							begin match e'.eexpr with
 								(* If we inline a function expression, we have to duplicate its locals. *)
-								| TFunction _ -> Texpr.duplicate_tvars e'
+								| TFunction _ -> Texpr.duplicate_tvars e_identity e'
 								| TCast(e1,None) when in_assignment -> e1
 								| _ -> e'
 							end
 						| VIInlineIfCalled when in_call ->
 							(* We allow inlining function expressions into call-places. However, we have to substitute
 							   their locals to avoid duplicate declarations. *)
-							Texpr.duplicate_tvars e'
+							Texpr.duplicate_tvars e_identity e'
 						| _ -> e
 					end
 				with Not_found ->

+ 2 - 2
src/typing/forLoop.ml

@@ -326,7 +326,7 @@ module IterationKind = struct
 					| _ -> map_expr loop e
 				in
 				let e2 = loop e2 in
-				Texpr.duplicate_tvars e2
+				Texpr.duplicate_tvars e_identity e2
 			) in
 			mk (TBlock el) t_void p
 		| IteratorIntConst(a,b,ascending) ->
@@ -367,7 +367,7 @@ module IterationKind = struct
 			let el = List.map (fun e ->
 				let ev = mk (TVar(v,Some e)) t_void e.epos in
 				let e = concat ev e2 in
-				Texpr.duplicate_tvars e
+				Texpr.duplicate_tvars e_identity e
 			) el in
 			mk (TBlock el) t_void p
 		| IteratorArray | IteratorArrayAccess ->

+ 1 - 1
src/typing/macroContext.ml

@@ -1058,4 +1058,4 @@ let setup() =
 
 let type_stored_expr ctx e1 =
 	let id = match e1 with (EConst (Int (s, _)),_) -> int_of_string s | _ -> die "" __LOC__ in
-	get_stored_typed_expr ctx.com id
+	TyperBase.get_stored_typed_expr ctx id

+ 1 - 1
src/typing/matcher/texprConverter.ml

@@ -393,4 +393,4 @@ let to_texpr ctx t_switch with_type dt =
 	| None ->
 		raise_typing_error "Unmatched patterns: _" p;
 	| Some e ->
-		Texpr.duplicate_tvars e
+		Texpr.duplicate_tvars e_identity e

+ 4 - 0
src/typing/typerBase.ml

@@ -173,6 +173,10 @@ let get_this ctx p =
 	| FunConstructor | FunMember ->
 		mk (TConst TThis) ctx.tthis p
 
+let get_stored_typed_expr ctx id =
+	let e = ctx.com.stored_typed_exprs#find id in
+	Texpr.duplicate_tvars (fun e -> get_this ctx e.epos) e
+
 let assign_to_this_is_allowed ctx =
 	match ctx.curclass.cl_kind with
 		| KAbstractImpl _ ->

+ 19 - 0
tests/unit/src/unit/issues/Issue11212.hx

@@ -0,0 +1,19 @@
+package unit.issues;
+
+class Issue11212 extends Test {
+	var value = 123;
+
+	function test() {
+		#if !macro
+		var foo:Foo = value; // on JS this generates `let foo = function() { return this.value; };` on JS
+		eq(123, foo());
+		#end
+	}
+}
+
+@:callable
+private abstract Foo(() -> Int) from () -> Int {
+	@:from macro static function ofExpr(e) {
+		return macro @:pos(e.pos) (function():Int return $e : Foo);
+	}
+}