Pārlūkot izejas kodu

Investigate some ctx.m mutations (#11840)

* what does this actually do?

* but how about this?

* how far can we take this?

* I finally broke something

* one more?
Simon Krajewski 9 mēneši atpakaļ
vecāks
revīzija
d989ab3055

+ 2 - 1
src/context/display/displayTexpr.ml

@@ -62,7 +62,8 @@ let actually_check_display_field ctx c cff p =
 	let cff = TypeloadFields.transform_field (ctx,cctx) c cff (ref []) (pos cff.cff_name) in
 	let display_modifier = Typeload.check_field_access ctx cff in
 	let fctx = TypeloadFields.create_field_context ctx cctx cff true display_modifier in
-	let cf = TypeloadFields.init_field (ctx,cctx,fctx) cff in
+	let cf = TypeloadFields.create_class_field cctx cff in
+	TypeloadFields.init_field (ctx,cctx,fctx) cff cf;
 	flush_pass ctx.g PTypeField ("check_display_field",(fst c.cl_path @ [snd c.cl_path;fst cff.cff_name]));
 	ignore(follow cf.cf_type)
 

+ 3 - 3
src/context/typecore.ml

@@ -76,7 +76,7 @@ type typer_module = {
 }
 
 type typer_class = {
-	mutable curclass : tclass; (* TODO: should not be mutable *)
+	curclass : tclass;
 	mutable tthis : t;
 	mutable get_build_infos : unit -> (module_type * t list * class_field list) option;
 }
@@ -150,7 +150,7 @@ and typer_expr = {
 }
 
 and typer_field = {
-	mutable curfield : tclass_field;
+	curfield : tclass_field;
 	mutable locals : (string, tvar) PMap.t;
 	mutable vthis : tvar option;
 	mutable untyped : bool;
@@ -165,7 +165,7 @@ and typer = {
 	com : context;
 	t : basic_types;
 	g : typer_globals;
-	mutable m : typer_module;
+	m : typer_module;
 	c : typer_class;
 	f : typer_field;
 	e : typer_expr;

+ 57 - 55
src/filters/filters.ml

@@ -251,27 +251,29 @@ let mark_switch_break_loops e =
 	in
 	run e
 
-let rec fix_return_dynamic_from_void_function return_is_void e =
-	match e.eexpr with
-	| TFunction fn ->
-		let is_void = ExtType.is_void (follow fn.tf_type) in
-		let body = fix_return_dynamic_from_void_function is_void fn.tf_expr in
-		{ e with eexpr = TFunction { fn with tf_expr = body } }
-	| TReturn (Some return_expr) when return_is_void && t_dynamic == follow return_expr.etype ->
-		let return_pos = { e.epos with pmax = return_expr.epos.pmin - 1 } in
-		let exprs = [
-			fix_return_dynamic_from_void_function return_is_void return_expr;
-			{ e with eexpr = TReturn None; epos = return_pos };
-		] in
-		{ e with
-			eexpr = TMeta (
-				(Meta.MergeBlock, [], null_pos),
-				mk (TBlock exprs) e.etype e.epos
-			);
-		}
-	| _ -> Type.map_expr (fix_return_dynamic_from_void_function return_is_void) e
-
-let check_abstract_as_value e =
+let fix_return_dynamic_from_void_function _ e =
+	let rec loop return_is_void e = match e.eexpr with
+		| TFunction fn ->
+			let is_void = ExtType.is_void (follow fn.tf_type) in
+			let body = loop is_void fn.tf_expr in
+			{ e with eexpr = TFunction { fn with tf_expr = body } }
+		| TReturn (Some return_expr) when return_is_void && t_dynamic == follow return_expr.etype ->
+			let return_pos = { e.epos with pmax = return_expr.epos.pmin - 1 } in
+			let exprs = [
+				loop return_is_void return_expr;
+				{ e with eexpr = TReturn None; epos = return_pos };
+			] in
+			{ e with
+				eexpr = TMeta (
+					(Meta.MergeBlock, [], null_pos),
+					mk (TBlock exprs) e.etype e.epos
+				);
+			}
+		| _ -> Type.map_expr (loop return_is_void) e
+	in
+	loop true e
+
+let check_abstract_as_value _ e =
 	let rec loop e =
 		match e.eexpr with
 		| TField ({ eexpr = TTypeExpr _ }, _) -> ()
@@ -489,30 +491,30 @@ let destruction tctx detail_times main locals =
 			tctx
 			detail_times
 			(* This has to run after DCE, or otherwise its condition always holds. *)
-			["insert_save_stacks",Exceptions.insert_save_stacks tctx]
+			["insert_save_stacks",Exceptions.insert_save_stacks]
 		)
 		com.types;
 	let type_filters = [
-		Exceptions.patch_constructors tctx; (* TODO: I don't believe this should load_instance anything at this point... *)
-		check_private_path com;
-		Naming.apply_native_paths;
-		add_rtti com;
-		(match com.platform with | Jvm -> (fun _ -> ()) | _ -> (fun mt -> AddFieldInits.add_field_inits tctx.c.curclass.cl_path locals com mt));
-		(match com.platform with Hl -> (fun _ -> ()) | _ -> add_meta_field com);
-		check_void_field;
-		(match com.platform with | Cpp -> promote_first_interface_to_super | _ -> (fun _ -> ()));
-		commit_features com;
-		(if com.config.pf_reserved_type_paths <> [] then check_reserved_type_paths com else (fun _ -> ()));
+		Exceptions.patch_constructors; (* TODO: I don't believe this should load_instance anything at this point... *)
+		(fun _ -> check_private_path com);
+		(fun _ -> Naming.apply_native_paths);
+		(fun _ -> add_rtti com);
+		(match com.platform with | Jvm -> (fun _ _ -> ()) | _ -> (fun tctx mt -> AddFieldInits.add_field_inits tctx.c.curclass.cl_path locals com mt));
+		(match com.platform with Hl -> (fun _ _ -> ()) | _ -> (fun _ -> add_meta_field com));
+		(fun _ -> check_void_field);
+		(fun _ -> (match com.platform with | Cpp -> promote_first_interface_to_super | _ -> (fun _ -> ())));
+		(fun _ -> commit_features com);
+		(fun _ -> (if com.config.pf_reserved_type_paths <> [] then check_reserved_type_paths com else (fun _ -> ())));
 	] in
 	with_timer detail_times "type 3" None (fun () ->
 		List.iter (fun t ->
-			begin match t with
-			| TClassDecl c ->
-				tctx.c.curclass <- c
-			| _ ->
-				()
-			end;
-			List.iter (fun f -> f t) type_filters
+			let tctx = match t with
+				| TClassDecl c ->
+					TyperManager.clone_for_class tctx c
+				| _ ->
+					tctx
+			in
+			List.iter (fun f -> f tctx t) type_filters
 		) com.types;
 	);
 	com.callbacks#run com.error_ext com.callbacks#get_after_filters;
@@ -705,20 +707,20 @@ let run tctx main before_destruction =
 	NullSafety.run com new_types;
 	(* PASS 1: general expression filters *)
 	let filters = [
-		"ForRemap",ForRemap.apply tctx;
-		"handle_abstract_casts",AbstractCast.handle_abstract_casts tctx;
+		"ForRemap",ForRemap.apply;
+		"handle_abstract_casts",AbstractCast.handle_abstract_casts;
 	] in
 	List.iter (run_expression_filters tctx detail_times filters) new_types;
 	let filters = [
-		"local_statics",LocalStatic.run tctx;
-		"fix_return_dynamic_from_void_function",fix_return_dynamic_from_void_function true;
-		"check_local_vars_init",check_local_vars_init tctx;
+		"local_statics",LocalStatic.run;
+		"fix_return_dynamic_from_void_function",fix_return_dynamic_from_void_function;
+		"check_local_vars_init",check_local_vars_init;
 		"check_abstract_as_value",check_abstract_as_value;
-		"Tre",if defined com Define.AnalyzerOptimize then Tre.run tctx else (fun e -> e);
-		"reduce_expression",Optimizer.reduce_expression tctx;
-		"inline_constructors",InlineConstructors.inline_constructors tctx;
-		"Exceptions_filter",Exceptions.filter tctx;
-		"captured_vars",CapturedVars.captured_vars com;
+		"Tre",if defined com Define.AnalyzerOptimize then Tre.run else (fun _ e -> e);
+		"reduce_expression",Optimizer.reduce_expression;
+		"inline_constructors",InlineConstructors.inline_constructors;
+		"Exceptions_filter",Exceptions.filter;
+		"captured_vars",(fun _ -> CapturedVars.captured_vars com);
 	] in
 	List.iter (run_expression_filters tctx detail_times filters) new_types;
 	(* PASS 1.5: pre-analyzer type filters *)
@@ -739,13 +741,13 @@ let run tctx main before_destruction =
 	enter_stage com CAnalyzerDone;
 	let locals = RenameVars.init com in
 	let filters = [
-		"sanitize",Optimizer.sanitize com;
-		"add_final_return",if com.config.pf_add_final_return then add_final_return else (fun e -> e);
+		"sanitize",(fun _ e -> Optimizer.sanitize com e);
+		"add_final_return",(fun _ -> if com.config.pf_add_final_return then add_final_return else (fun e -> e));
 		"RenameVars",(match com.platform with
-		| Eval -> (fun e -> e)
-		| Jvm -> (fun e -> e)
-		| _ -> (fun e -> RenameVars.run tctx.c.curclass.cl_path locals e));
-		"mark_switch_break_loops",mark_switch_break_loops;
+		| Eval -> (fun _ e -> e)
+		| Jvm -> (fun _ e -> e)
+		| _ -> (fun tctx e -> RenameVars.run tctx.c.curclass.cl_path locals e));
+		"mark_switch_break_loops",(fun _ -> mark_switch_break_loops);
 	] in
 	List.iter (run_expression_filters tctx detail_times filters) new_types;
 	with_timer detail_times "callbacks" None (fun () ->

+ 13 - 13
src/filters/filtersCommon.ml

@@ -55,26 +55,26 @@ let is_overridden cls field =
 
 let run_expression_filters ?(ignore_processed_status=false) ctx detail_times filters t =
 	let com = ctx.com in
-	let run identifier e =
+	let run (ctx : typer) identifier e =
 		List.fold_left (fun e (filter_name,f) ->
-			FilterContext.with_timer detail_times filter_name identifier (fun () -> f e)
+			FilterContext.with_timer detail_times filter_name identifier (fun () -> f ctx e)
 		) e filters
 	in
 	match t with
 	| TClassDecl c when is_removable_class c -> ()
 	| TClassDecl c ->
-		ctx.c.curclass <- c;
-		ctx.m <- TypeloadModule.make_curmod ctx.com ctx.g c.cl_module;
-		let rec process_field f =
-			if ignore_processed_status || not (has_class_field_flag f CfPostProcessed) then begin
-				ctx.f.curfield <- f;
-				(match f.cf_expr with
-				| Some e when not (is_removable_field com f) ->
-					let identifier = Printf.sprintf "%s.%s" (s_type_path c.cl_path) f.cf_name in
-					f.cf_expr <- Some (rec_stack_loop AbstractCast.cast_stack f (run (Some identifier)) e);
+		let ctx = TyperManager.clone_for_module ctx (TypeloadModule.make_curmod ctx.com ctx.g c.cl_module) in
+		let ctx = TyperManager.clone_for_class ctx c in
+		let rec process_field cf =
+			if ignore_processed_status || not (has_class_field_flag cf CfPostProcessed) then begin
+				let ctx = TyperManager.clone_for_field ctx cf cf.cf_params in
+				(match cf.cf_expr with
+				| Some e when not (is_removable_field com cf) ->
+					let identifier = Printf.sprintf "%s.%s" (s_type_path c.cl_path) cf.cf_name in
+					cf.cf_expr <- Some (rec_stack_loop AbstractCast.cast_stack cf (run ctx (Some identifier)) e);
 				| _ -> ());
 			end;
-			List.iter process_field f.cf_overloads
+			List.iter process_field cf.cf_overloads
 		in
 		List.iter process_field c.cl_ordered_fields;
 		List.iter process_field c.cl_ordered_statics;
@@ -85,7 +85,7 @@ let run_expression_filters ?(ignore_processed_status=false) ctx detail_times fil
 		| None -> ()
 		| Some e ->
 			let identifier = Printf.sprintf "%s.__init__" (s_type_path c.cl_path) in
-			TClass.set_cl_init c (run (Some identifier) e))
+			TClass.set_cl_init c (run ctx (Some identifier) e))
 	| TEnumDecl _ -> ()
 	| TTypeDecl _ -> ()
 	| TAbstractDecl _ -> ()

+ 8 - 9
src/typing/macroContext.ml

@@ -608,10 +608,10 @@ and flush_macro_context mint mctx =
 	mctx.com.Common.modules <- modules;
 	(* we should maybe ensure that all filters in Main are applied. Not urgent atm *)
 	let expr_filters = [
-		"handle_abstract_casts",AbstractCast.handle_abstract_casts mctx;
-		"local_statics",LocalStatic.run mctx;
-		"Exceptions",Exceptions.filter mctx;
-		"captured_vars",CapturedVars.captured_vars mctx.com;
+		"handle_abstract_casts",AbstractCast.handle_abstract_casts;
+		"local_statics",LocalStatic.run;
+		"Exceptions",Exceptions.filter;
+		"captured_vars",(fun _ -> CapturedVars.captured_vars mctx.com);
 	] in
 	(*
 		some filters here might cause side effects that would break compilation server.
@@ -752,7 +752,7 @@ let load_macro_module mctx com cpath display p =
 	let old = mctx.com.display in
 	if display then mctx.com.display <- com.display;
 	let mloaded = TypeloadModule.load_module ~origin:MDepFromMacro mctx m p in
-	mctx.m <- {
+	(* mctx.m <- {
 		curmod = mloaded;
 		import_resolution = new resolution_list ["import";s_type_path cpath];
 		own_resolution = None;
@@ -760,7 +760,7 @@ let load_macro_module mctx com cpath display p =
 		module_using = [];
 		import_statements = [];
 		is_display_file = (com.display.dms_kind <> DMNone && DisplayPosition.display_position#is_in_file (Path.UniqueKey.lazy_key mloaded.m_extra.m_file));
-	};
+	}; *)
 	mloaded,(fun () -> mctx.com.display <- old)
 
 let load_macro'' com mctx display cpath f p =
@@ -794,7 +794,7 @@ let load_macro'' com mctx display cpath f p =
 		restore();
 		if not com.is_macro_context then flush_macro_context mint mctx;
 		mctx.com.cached_macros#add (cpath,f) meth;
-		mctx.m <- {
+		(* mctx.m <- {
 			curmod = null_module;
 			import_resolution = new resolution_list ["import";s_type_path cpath];
 			own_resolution = None;
@@ -802,7 +802,7 @@ let load_macro'' com mctx display cpath f p =
 			module_using = [];
 			import_statements = [];
 			is_display_file = false;
-		};
+		}; *)
 		t();
 		meth
 
@@ -1017,7 +1017,6 @@ let type_macro ctx mode cpath f (el:Ast.expr list) p =
 	e
 
 let call_macro mctx args margs call p =
-	mctx.c.curclass <- null_class;
 	let el, _ = CallUnification.unify_call_args mctx args margs t_dynamic p false false false in
 	call (List.map (fun e -> try Interp.make_const e with Exit -> raise_typing_error "Argument should be a constant" e.epos) el)
 

+ 29 - 36
src/typing/typeloadFields.ml

@@ -538,10 +538,10 @@ let create_field_context ctx cctx cff is_display_file display_modifier =
 	if fctx.is_display_field then cctx.has_display_field <- true;
 	fctx
 
-let create_typer_context_for_field ctx cctx fctx cff =
+let create_typer_context_for_field ctx cctx fctx cff cf =
 	DeprecationCheck.check_is ctx.com ctx.m.curmod ctx.c.curclass.cl_meta cff.cff_meta (fst cff.cff_name) cff.cff_meta (snd cff.cff_name);
 	let params = if fctx.is_static && not fctx.is_abstract_member && not (Meta.has Meta.LibType cctx.tclass.cl_meta) (* TODO: remove this *) then [] else ctx.type_params in
-	let ctx = TyperManager.clone_for_field ctx null_field params in
+	let ctx = TyperManager.clone_for_field ctx cf params in
 
 	let c = cctx.tclass in
 	if (fctx.is_abstract && not (has_meta Meta.LibType c.cl_meta)) then begin
@@ -560,7 +560,7 @@ let create_typer_context_for_field ctx cctx fctx cff =
 	end;
 	ctx
 
-let is_public (ctx,cctx) access parent =
+let is_public cctx access parent =
 	let c = cctx.tclass in
 	if List.mem_assoc APrivate access then
 		false
@@ -890,7 +890,7 @@ let load_variable_type_hint ctx fctx eo p = function
 	| Some t ->
 		load_type_hint ctx p LoadNormal (Some t)
 
-let create_variable (ctx,cctx,fctx) c f t eo p =
+let create_variable (ctx,cctx,fctx) c f cf t eo p =
 	let is_abstract_enum_field = List.mem_assoc AEnum f.cff_access in
 	if fctx.is_abstract_member && not is_abstract_enum_field then raise_typing_error "Cannot declare member variable in abstract" p;
 	if fctx.is_inline && not fctx.is_static then invalid_modifier ctx.com fctx "inline" "non-static variable" p;
@@ -910,12 +910,8 @@ let create_variable (ctx,cctx,fctx) c f t eo p =
 	else
 		{ v_read = AccNormal ; v_write = AccNormal }
 	in
-	let cf = {
-		(mk_field (fst f.cff_name) ~public:(is_public (ctx,cctx) f.cff_access None) t f.cff_pos (pos f.cff_name)) with
-		cf_doc = f.cff_doc;
-		cf_meta = f.cff_meta;
-		cf_kind = Var kind;
-	} in
+	cf.cf_type <- t;
+	cf.cf_kind <- Var kind;
 	if fctx.is_final then begin
 		if missing_initialization && not fctx.is_static then
 			cctx.uninitialized_final <- cf :: cctx.uninitialized_final;
@@ -927,7 +923,6 @@ let create_variable (ctx,cctx,fctx) c f t eo p =
 		add_class_field_flag cf CfImpl;
 	end;
 	if is_abstract_enum_field then add_class_field_flag cf CfEnum;
-	ctx.f.curfield <- cf;
 	TypeBinding.bind_var ctx cctx fctx cf eo;
 	cf
 
@@ -1180,7 +1175,7 @@ let setup_args_ret ctx cctx fctx name fd p =
 	let args = new FunctionArguments.function_arguments ctx.com type_arg is_extern fctx.is_display_field abstract_this fd.f_args in
 	args,ret
 
-let create_method (ctx,cctx,fctx) c f fd p =
+let create_method (ctx,cctx,fctx) c f cf fd p =
 	let name = fst f.cff_name in
 	let params = TypeloadFunction.type_function_params ctx fd TPHMethod name p in
 	if fctx.is_generic then begin
@@ -1257,13 +1252,10 @@ let create_method (ctx,cctx,fctx) c f fd p =
 	ctx.type_params <- params @ ctx.type_params;
 	let args,ret = setup_args_ret ctx cctx fctx (fst f.cff_name) fd p in
 	let t = TFun (args#for_type,ret) in
-	let cf = {
-		(mk_field name ~public:(is_public (ctx,cctx) f.cff_access parent) t f.cff_pos (pos f.cff_name)) with
-		cf_doc = f.cff_doc;
-		cf_meta = f.cff_meta;
-		cf_kind = Method (if fctx.is_macro then MethMacro else if fctx.is_inline then MethInline else if dynamic then MethDynamic else MethNormal);
-		cf_params = params;
-	} in
+	cf.cf_type <- t;
+	cf.cf_kind <- Method (if fctx.is_macro then MethMacro else if fctx.is_inline then MethInline else if dynamic then MethDynamic else MethNormal);
+	cf.cf_params <- params;
+	if is_public cctx f.cff_access parent then add_class_field_flag cf CfPublic;
 	if fctx.is_final then add_class_field_flag cf CfFinal;
 	if fctx.is_extern then add_class_field_flag cf CfExtern;
 	if fctx.is_abstract then begin
@@ -1325,7 +1317,6 @@ let create_method (ctx,cctx,fctx) c f fd p =
 			if fctx.field_kind = CfrConstructor then FunConstructor else if fctx.is_static then FunStatic else FunMember
 	in
 	init_meta_overloads ctx (Some c) cf;
-	ctx.f.curfield <- cf;
 	if fctx.do_bind then
 		TypeBinding.bind_method ctx cctx fctx fmode cf t args ret fd.f_expr (match fd.f_expr with Some e -> snd e | None -> f.cff_pos)
 	else begin
@@ -1348,13 +1339,14 @@ let create_method (ctx,cctx,fctx) c f fd p =
 	end;
 	cf
 
-let create_property (ctx,cctx,fctx) c f (get,set,t,eo) p =
+let create_property (ctx,cctx,fctx) c f cf (get,set,t,eo) p =
 	let name = fst f.cff_name in
 	let ret = (match t, eo with
 		| None, None -> raise_typing_error "Property requires type-hint or initialization" p;
 		| None, _ -> mk_mono()
 		| Some t, _ -> load_type_hint ctx p LoadNormal (Some t)
 	) in
+	cf.cf_type <- ret;
 	let t_get,t_set = match cctx.abstract with
 		| Some a when fctx.is_abstract_member ->
 			if Meta.has Meta.IsVar f.cff_meta then raise_typing_error "Abstract properties cannot be real variables" f.cff_pos;
@@ -1369,11 +1361,6 @@ let create_property (ctx,cctx,fctx) c f (get,set,t,eo) p =
 		end else
 			get_overloads ctx.com c m
 	in
-	let cf = {
-		(mk_field name ~public:(is_public (ctx,cctx) f.cff_access None) ret f.cff_pos (pos f.cff_name)) with
-		cf_doc = f.cff_doc;
-		cf_meta = f.cff_meta;
-	} in
 	if fctx.is_abstract_member then add_class_field_flag cf CfImpl;
 	let check_method m t is_getter =
 		try
@@ -1488,7 +1475,6 @@ let create_property (ctx,cctx,fctx) c f (get,set,t,eo) p =
 	cf.cf_kind <- Var { v_read = get; v_write = set };
 	if fctx.is_extern then add_class_field_flag cf CfExtern;
 	if List.mem_assoc AEnum f.cff_access then add_class_field_flag cf CfEnum;
-	ctx.f.curfield <- cf;
 	TypeBinding.bind_var ctx cctx fctx cf eo;
 	cf
 
@@ -1507,10 +1493,10 @@ let reject_final_static_method ctx cctx fctx f =
 		in
 		invalid_modifier_combination fctx ctx.com fctx "final" "static" p
 
-let init_field (ctx,cctx,fctx) f =
+let init_field (ctx,cctx,fctx) f cf =
 	let c = cctx.tclass in
 	let name = fst f.cff_name in
-	TypeloadCheck.check_global_metadata ctx f.cff_meta (fun m -> f.cff_meta <- m :: f.cff_meta) c.cl_module.m_path c.cl_path (Some name);
+	TypeloadCheck.check_global_metadata ctx f.cff_meta (fun m -> cf.cf_meta <- m :: cf.cf_meta) c.cl_module.m_path c.cl_path (Some name);
 	let p = f.cff_pos in
 	if not (has_class_flag c CExtern) && not (Meta.has Meta.Native f.cff_meta) then Naming.check_field_name ctx.com name p;
 	List.iter (fun acc ->
@@ -1539,17 +1525,16 @@ let init_field (ctx,cctx,fctx) f =
 	let cf =
 		match f.cff_kind with
 		| FVar (t,e) ->
-			create_variable (ctx,cctx,fctx) c f t e p
+			create_variable (ctx,cctx,fctx) c f cf t e p
 		| FFun fd ->
 			reject_final_static_method ctx cctx fctx f;
-			create_method (ctx,cctx,fctx) c f fd p
+			create_method (ctx,cctx,fctx) c f cf fd p
 		| FProp (get,set,t,eo) ->
-			create_property (ctx,cctx,fctx) c f (get,set,t,eo) p
+			create_property (ctx,cctx,fctx) c f cf (get,set,t,eo) p
 	in
 	(if (fctx.is_static || fctx.is_macro && ctx.com.is_macro_context) then add_class_field_flag cf CfStatic);
 	if Meta.has Meta.InheritDoc cf.cf_meta then
-		delay ctx.g PTypeField (fun() -> InheritDoc.build_class_field_doc ctx (Some c) cf);
-	cf
+		delay ctx.g PTypeField (fun() -> InheritDoc.build_class_field_doc ctx (Some c) cf)
 
 let check_overload ctx f fs is_extern_class =
 	try
@@ -1612,6 +1597,13 @@ let check_functional_interface ctx c =
 		add_class_flag c CFunctionalInterface;
 		ctx.com.functional_interface_lut#add c.cl_path (c,cf)
 
+let create_class_field cctx f  =
+	let cf = {(mk_field (fst f.cff_name) ~public:(is_public cctx f.cff_access None) t_dynamic f.cff_pos (pos f.cff_name)) with
+		cf_doc = f.cff_doc;
+		cf_meta = f.cff_meta
+	} in
+	cf
+
 let init_class ctx_c cctx c p herits fields =
 	let com = ctx_c.com in
 	if cctx.is_class_debug then print_endline ("Created class context: " ^ dump_class_context cctx);
@@ -1658,10 +1650,11 @@ let init_class ctx_c cctx c p herits fields =
 		let p = f.cff_pos in
 		let display_modifier = Typeload.check_field_access ctx_c f in
 		let fctx = create_field_context ctx_c cctx f ctx_c.m.is_display_file display_modifier in
-		let ctx = create_typer_context_for_field ctx_c cctx fctx f in
+		let cf = create_class_field cctx f in
+		let ctx = create_typer_context_for_field ctx_c cctx fctx f cf in
 		try
 			if fctx.is_field_debug then print_endline ("Created field context: " ^ dump_field_context fctx);
-			let cf = init_field (ctx,cctx,fctx) f in
+			init_field (ctx,cctx,fctx) f cf;
 			if fctx.field_kind = CfrInit then begin
 				if !has_init then
 					display_error ctx.com ("Duplicate class field declaration : " ^ (s_type_path c.cl_path) ^ "." ^ cf.cf_name) cf.cf_name_pos