2
0
Эх сурвалжийг харах

[hxb] generate proper warnings for unbound type parameters

Rudy Ges 1 жил өмнө
parent
commit
e44d22f557

+ 10 - 2
src-json/warning.json

@@ -117,6 +117,14 @@
 		"name": "WConstructorInliningCancelled",
 		"doc": "Constructor call could not be inlined because a field is uninitialized",
 		"parent": "WTyper"
+	},
+	{
+		"name": "WHxb",
+		"doc": "Hxb (either --hxb output or haxe compiler cache) related warnings"
+	},
+	{
+		"name": "WUnboundTypeParameter",
+		"doc": "Hxb (either --hxb output or haxe compiler cache) failed to link a type parameter to an actual type",
+		"parent": "WHxb"
 	}
-
-]
+]

+ 2 - 2
src/compiler/compilationCache.ml

@@ -69,12 +69,12 @@ class context_cache (index : int) (sign : Digest.t) = object(self)
 	method find_module_extra path =
 		try (Hashtbl.find modules path).m_extra with Not_found -> (Hashtbl.find binary_cache path).mc_extra
 
-	method cache_module display_source_at anon_identification hxb_writer_stats path m =
+	method cache_module display_source_at warn anon_identification hxb_writer_stats path m =
 		match m.m_extra.m_kind with
 		| MImport ->
 			Hashtbl.add modules m.m_path m
 		| _ ->
-			let writer = new HxbWriter.hxb_writer display_source_at anon_identification hxb_writer_stats in
+			let writer = new HxbWriter.hxb_writer display_source_at warn anon_identification hxb_writer_stats in
 			writer#write_module m;
 			let chunks = writer#get_chunks in
 			Hashtbl.replace binary_cache path {

+ 2 - 1
src/compiler/generate.ml

@@ -41,7 +41,8 @@ let export_hxb com cc platform zip m =
 				zip#add_entry data path;
 			with Not_found ->
 				let anon_identification = new tanon_identification in
-				let writer = new HxbWriter.hxb_writer (MessageReporting.display_source_at com) anon_identification com.hxb_writer_stats in
+				let warn w s p = com.Common.warning w com.warning_options s p in
+				let writer = new HxbWriter.hxb_writer (MessageReporting.display_source_at com) warn anon_identification com.hxb_writer_stats in
 				writer#write_module m;
 				let out = IO.output_string () in
 				writer#export out;

+ 65 - 63
src/compiler/hxb/hxbWriter.ml

@@ -511,6 +511,7 @@ let create_field_writer_context pos_writer = {
 
 class hxb_writer
 	(display_source_at : Globals.pos -> unit)
+	(warn : Warning.warning -> string -> Globals.pos -> unit)
 	(anon_id : Type.t Tanon_identification.tanon_identification)
 	(stats : hxb_writer_stats)
 = object(self)
@@ -946,7 +947,7 @@ class hxb_writer
 		let i = abstracts#get_or_add a.a_path a in
 		IOChunk.write_uleb128 chunk.io i
 
-	method write_anon_ref (an : tanon) (ttp : type_params) =
+	method write_anon_ref (an : tanon) (ttp : type_params) (p : Globals.pos) =
 		let pfm = Option.get (anon_id#identify_anon ~strict:true an) in
 		try
 			let index = anons#get pfm.pfm_path in
@@ -956,7 +957,7 @@ class hxb_writer
 			let index = anons#add pfm.pfm_path an in
 			IOChunk.write_u8 chunk.io 1;
 			IOChunk.write_uleb128 chunk.io index;
-			self#write_anon an ttp
+			self#write_anon an ttp p
 
 	method write_tmono_ref (mono : tmono) =
 		let index = try tmonos#get mono with Not_found -> tmonos#add mono () in
@@ -1019,9 +1020,9 @@ class hxb_writer
 
 	(* Type instances *)
 
-	val warn_strings = Hashtbl.create 0
+	val unbound_ttp = new identity_pool
 
-	method write_type_parameter_ref (ttp : typed_type_param) =
+	method write_type_parameter_ref (ttp : typed_type_param) (p : Globals.pos) =
 		begin try
 			begin match ttp.ttp_host with
 			| TPHType ->
@@ -1037,10 +1038,11 @@ class hxb_writer
 				IOChunk.write_u8 chunk.io 3;
 				IOChunk.write_uleb128 chunk.io index;
 		end with Not_found ->
-			let msg = Printf.sprintf "[%s] %s Unbound type parameter %s" (s_type_path current_module.m_path) todo_error (s_type_path ttp.ttp_class.cl_path) in
-			if not (Hashtbl.mem warn_strings msg) then begin
-				Hashtbl.add warn_strings msg ();
-				prerr_endline msg;
+			try ignore(unbound_ttp#get ttp) with Not_found -> begin
+				let msg = Printf.sprintf "Unbound type parameter %s" (s_type_path ttp.ttp_class.cl_path) in
+				ignore(unbound_ttp#add ttp ());
+				(* if p = null_pos then trace_call_stack ~n:20 (); *)
+				warn WUnboundTypeParameter msg p
 			end;
 			(* TODO: handle unbound type parameters? *)
 			IOChunk.write_u8 chunk.io 4; (* TDynamic None *)
@@ -1116,7 +1118,7 @@ class hxb_writer
 		   103: Bool
 		   104: String
 	*)
-	method write_type_instance_simple (rings : t_rings) (t : Type.t) =
+	method write_type_instance_simple (rings : t_rings) (t : Type.t) (p : Globals.pos) =
 		match t with
 		| TAbstract ({a_path = ([],"Void")},[]) ->
 			self#write_type_instance_byte 100;
@@ -1142,12 +1144,12 @@ class hxb_writer
 				None
 			| Some t ->
 				(* Don't write bound monomorphs, write underlying type directly *)
-				self#write_type_instance_simple rings t
+				self#write_type_instance_simple rings t p
 			end
 		| TLazy f ->
-			self#write_type_instance_simple rings (lazy_type f)
+			self#write_type_instance_simple rings (lazy_type f) p
 		| TInst({cl_kind = KTypeParameter ttp},[]) ->
-			self#write_type_parameter_ref ttp;
+			self#write_type_parameter_ref ttp p;
 			None
 		| TInst({cl_kind = KExpr _},_) ->
 			Some (t,rings#ring_inst)
@@ -1223,11 +1225,11 @@ class hxb_writer
 			) l
 		end
 
-	method write_type_instance_not_simple t =
+	method write_type_instance_not_simple t p =
 		let write_function_arg (n,o,t) =
 			Chunk.write_string chunk n;
 			IOChunk.write_bool chunk.io o;
-			self#write_type_instance t;
+			self#write_type_instance t p;
 		in
 		let write_inlined_list offset max f_first f_elt l =
 			self#write_inlined_list offset max self#write_type_instance_byte f_first f_elt l
@@ -1242,33 +1244,33 @@ class hxb_writer
 			write_inlined_list 20 4 (fun () -> ()) write_function_arg args;
 		| TFun(args,t) ->
 			write_inlined_list 30 4 (fun () -> ()) write_function_arg args;
-			self#write_type_instance t;
+			self#write_type_instance t p;
 		| TInst(c,tl) ->
-			write_inlined_list 40 2 (fun () -> self#write_class_ref c) self#write_type_instance tl;
+			write_inlined_list 40 2 (fun () -> self#write_class_ref c) (fun t -> self#write_type_instance t p) tl;
 		| TEnum(en,tl) ->
-			write_inlined_list 50 2 (fun () -> self#write_enum_ref en) self#write_type_instance tl;
+			write_inlined_list 50 2 (fun () -> self#write_enum_ref en) (fun t -> self#write_type_instance t p) tl;
 		| TType(td,tl) ->
-			write_inlined_list 60 2 (fun () -> self#write_typedef_ref td) self#write_type_instance tl;
+			write_inlined_list 60 2 (fun () -> self#write_typedef_ref td) (fun t -> self#write_type_instance t p) tl;
 		| TAbstract(a,tl) ->
-			write_inlined_list 70 2 (fun () -> self#write_abstract_ref a) self#write_type_instance tl;
+			write_inlined_list 70 2 (fun () -> self#write_abstract_ref a) (fun t -> self#write_type_instance t p) tl;
 		| TAnon an when PMap.is_empty an.a_fields ->
 			self#write_type_instance_byte 80;
 		| TAnon an ->
 			self#write_type_instance_byte 81;
-			self#write_anon_ref an []
+			self#write_anon_ref an [] p
 		| TDynamic (Some t) ->
 			self#write_type_instance_byte 89;
-			self#write_type_instance t;
+			self#write_type_instance t p;
 
-	method write_type_instance (t: Type.t) =
-		match self#write_type_instance_simple dummy_rings t with
+	method write_type_instance (t: Type.t) (p: Globals.pos) =
+		match self#write_type_instance_simple dummy_rings t p with
 			| None ->
 				()
 			| Some(t,_) ->
-				self#write_type_instance_not_simple t
+				self#write_type_instance_not_simple t p
 
-	method write_types tl =
-		Chunk.write_list chunk tl self#write_type_instance
+	method write_types tl p =
+		Chunk.write_list chunk tl (fun t -> self#write_type_instance t p)
 
 	(* texpr *)
 
@@ -1296,9 +1298,9 @@ class hxb_writer
 		self#write_metadata v.v_meta;
 		self#write_pos v.v_pos
 
-	method write_texpr_type_instance (fctx : field_writer_context) (t: Type.t) =
+	method write_texpr_type_instance (fctx : field_writer_context) (t: Type.t) (p: Globals.pos) =
 		let restore = self#start_temporary_chunk 32 in
-		let r = self#write_type_instance_simple fctx.t_rings t in
+		let r = self#write_type_instance_simple fctx.t_rings t p in
 		let index = match r with
 		| None ->
 			let t_bytes = restore (fun new_chunk -> IOChunk.get_bytes new_chunk.io) in
@@ -1312,7 +1314,7 @@ class hxb_writer
 				index
 			with Not_found ->
 				let restore = self#start_temporary_chunk 32 in
-				self#write_type_instance_not_simple t;
+				self#write_type_instance_not_simple t p;
 				let t_bytes = restore (fun new_chunk ->
 					IOChunk.get_bytes new_chunk.io
 				) in
@@ -1343,11 +1345,11 @@ class hxb_writer
 				);
 				Chunk.write_option chunk ve.v_expr (self#write_texpr fctx);
 			);
-			self#write_type_instance v.v_type;
+			self#write_type_instance v.v_type v.v_pos;
 		in
 		let rec loop e =
 
-			self#write_texpr_type_instance fctx e.etype;
+			self#write_texpr_type_instance fctx e.etype e.epos;
 			fctx.pos_writer#write_pos chunk true 0 e.epos;
 
 			match e.eexpr with
@@ -1421,7 +1423,7 @@ class hxb_writer
 					declare_var v;
 					Chunk.write_option chunk eo loop;
 				);
-				self#write_type_instance tf.tf_type;
+				self#write_type_instance tf.tf_type e.epos;
 				loop tf.tf_expr;
 			(* texpr compounds 60-79 *)
 			| TArray(e1,e2) ->
@@ -1520,13 +1522,13 @@ class hxb_writer
 				self#write_texpr_byte 111;
 				fctx.pos_writer#write_pos chunk true 0 p1;
 				self#write_class_ref c;
-				self#write_types tl;
+				self#write_types tl e.epos;
 				self#write_field_ref c CfrMember cf;
 			| TField(e1,FInstance(c,tl,cf)) ->
 				self#write_texpr_byte 102;
 				loop e1;
 				self#write_class_ref c;
-				self#write_types tl;
+				self#write_types tl e.epos;
 				self#write_field_ref c CfrMember cf;
 			| TField({eexpr = TTypeExpr (TClassDecl c'); epos = p1},FStatic(c,cf)) when c == c' ->
 				self#write_texpr_byte 110;
@@ -1546,7 +1548,7 @@ class hxb_writer
 				self#write_texpr_byte 105;
 				loop e1;
 				self#write_class_ref c;
-				self#write_types tl;
+				self#write_types tl e.epos;
 				self#write_field_ref c CfrMember cf
 			| TField(e1,FClosure(None,cf)) ->
 				self#write_texpr_byte 106;
@@ -1564,7 +1566,7 @@ class hxb_writer
 			(* module types 120-139 *)
 			| TTypeExpr (TClassDecl ({cl_kind = KTypeParameter ttp})) ->
 				self#write_texpr_byte 128;
-				self#write_type_parameter_ref ttp
+				self#write_type_parameter_ref ttp e.epos
 			| TTypeExpr (TClassDecl c) ->
 				self#write_texpr_byte 120;
 				self#write_class_ref c;
@@ -1588,13 +1590,13 @@ class hxb_writer
 				self#write_full_path (fst m.m_path) (snd m.m_path) (snd infos.mt_path);
 			| TNew(({cl_kind = KTypeParameter ttp}),tl,el) ->
 				self#write_texpr_byte 127;
-				self#write_type_parameter_ref ttp;
-				self#write_types tl;
+				self#write_type_parameter_ref ttp e.epos;
+				self#write_types tl e.epos;
 				loop_el el;
 			| TNew(c,tl,el) ->
 				self#write_texpr_byte 126;
 				self#write_class_ref c;
-				self#write_types tl;
+				self#write_types tl e.epos;
 				loop_el el;
 			(* unops 140-159 *)
 			| TUnop(op,flag,e1) ->
@@ -1620,11 +1622,11 @@ class hxb_writer
 		self#write_path ttp.ttp_class.cl_path;
 		self#write_pos ttp.ttp_class.cl_name_pos
 
-	method write_type_parameter_data ttp =
+	method write_type_parameter_data ttp p =
 		let c = ttp.ttp_class in
 		self#write_metadata c.cl_meta;
-		self#write_types (get_constraints ttp);
-		Chunk.write_option chunk ttp.ttp_default self#write_type_instance
+		self#write_types (get_constraints ttp) p;
+		Chunk.write_option chunk ttp.ttp_default (fun t -> self#write_type_instance t p)
 
 	method write_field_kind = function
 		| Method MethNormal -> IOChunk.write_u8 chunk.io 0;
@@ -1709,17 +1711,17 @@ class hxb_writer
 			)
 		)
 
-	method commit_field_type_parameters (params : type_params) =
+	method commit_field_type_parameters (params : type_params) (p : Globals.pos) =
 		IOChunk.write_uleb128 chunk.io (List.length params);
 		if not self#in_nested_scope then begin
 			let ftp = List.map fst field_type_parameters#to_list in
 			Chunk.write_list chunk ftp self#write_type_parameter_forward;
-			Chunk.write_list chunk ftp self#write_type_parameter_data;
+			Chunk.write_list chunk ftp (fun ftp -> self#write_type_parameter_data ftp p);
 		end
 
 	method write_class_field_data cf =
 		let restore = self#start_temporary_chunk 512 in
-		(try self#write_type_instance cf.cf_type with e -> begin
+		(try self#write_type_instance cf.cf_type cf.cf_pos with e -> begin
 			prerr_endline (Printf.sprintf "%s while writing type instance for field %s" todo_error cf.cf_name);
 			raise e
 		end);
@@ -1739,11 +1741,11 @@ class hxb_writer
 		end;
 
 		restore (fun new_chunk ->
-			self#commit_field_type_parameters cf.cf_params;
+			self#commit_field_type_parameters cf.cf_params cf.cf_pos;
 			if not self#in_nested_scope then begin
 				let ltp = List.map fst local_type_parameters#to_list in
 				Chunk.write_list chunk ltp self#write_type_parameter_forward;
-				Chunk.write_list chunk ltp self#write_type_parameter_data;
+				Chunk.write_list chunk ltp (fun ltp -> self#write_type_parameter_data ltp cf.cf_pos);
 			end;
 			Chunk.export_data new_chunk chunk
 		)
@@ -1767,13 +1769,13 @@ class hxb_writer
 		Chunk.write_option chunk infos.mt_doc self#write_documentation;
 		self#write_metadata infos.mt_meta;
 		Chunk.write_list chunk infos.mt_params self#write_type_parameter_forward;
-		Chunk.write_list chunk infos.mt_params self#write_type_parameter_data;
+		Chunk.write_list chunk infos.mt_params (fun mtp -> self#write_type_parameter_data mtp infos.mt_pos);
 		Chunk.write_list chunk infos.mt_using (fun (c,p) ->
 			self#write_class_ref c;
 			self#write_pos p;
 		);
 
-	method write_class_kind = function
+	method write_class_kind k p = match k with
 		| KNormal ->
 			IOChunk.write_u8 chunk.io 0
 		| KTypeParameter ttp ->
@@ -1786,7 +1788,7 @@ class hxb_writer
 		| KGenericInstance(c,tl) ->
 			IOChunk.write_u8 chunk.io 4;
 			self#write_class_ref c;
-			self#write_types tl
+			self#write_types tl p
 		| KMacroType ->
 			IOChunk.write_u8 chunk.io 5;
 		| KGenericBuild l ->
@@ -1806,18 +1808,18 @@ class hxb_writer
 			self#select_type c.cl_path;
 		end;
 		self#write_common_module_type (Obj.magic c);
-		self#write_class_kind c.cl_kind;
+		self#write_class_kind c.cl_kind c.cl_pos;
 		IOChunk.write_uleb128 chunk.io c.cl_flags;
 		Chunk.write_option chunk c.cl_super (fun (c,tl) ->
 			self#write_class_ref c;
-			self#write_types tl
+			self#write_types tl c.cl_pos
 		);
 		Chunk.write_list chunk c.cl_implements (fun (c,tl) ->
 			self#write_class_ref c;
-			self#write_types tl
+			self#write_types tl c.cl_pos
 		);
-		Chunk.write_option chunk c.cl_dynamic self#write_type_instance;
-		Chunk.write_option chunk c.cl_array_access self#write_type_instance;
+		Chunk.write_option chunk c.cl_dynamic (fun t -> self#write_type_instance t c.cl_pos);
+		Chunk.write_option chunk c.cl_array_access (fun t -> self#write_type_instance t c.cl_pos);
 
 	method write_abstract (a : tabstract) =
 		begin try
@@ -1831,10 +1833,10 @@ class hxb_writer
 			IOChunk.write_u8 chunk.io 0
 		else begin
 			IOChunk.write_u8 chunk.io 1;
-			self#write_type_instance a.a_this;
+			self#write_type_instance a.a_this a.a_pos;
 		end;
-		Chunk.write_list chunk a.a_from self#write_type_instance;
-		Chunk.write_list chunk a.a_to self#write_type_instance;
+		Chunk.write_list chunk a.a_from (fun t -> self#write_type_instance t a.a_pos);
+		Chunk.write_list chunk a.a_to (fun t -> self#write_type_instance t a.a_pos);
 		IOChunk.write_bool chunk.io a.a_enum
 
 	method write_abstract_fields (a : tabstract) =
@@ -1877,9 +1879,9 @@ class hxb_writer
 	method write_typedef (td : tdef) =
 		self#select_type td.t_path;
 		self#write_common_module_type (Obj.magic td);
-		self#write_type_instance td.t_type;
+		self#write_type_instance td.t_type td.t_pos;
 
-	method write_anon (an : tanon) (ttp : type_params) =
+	method write_anon (an : tanon) (ttp : type_params) (p : Globals.pos) =
 		let write_fields () =
 			Chunk.write_list chunk (PMap.foldi (fun s f acc -> (s,f) :: acc) an.a_fields []) (fun (_,cf) ->
 				self#write_anon_field_ref cf
@@ -1895,7 +1897,7 @@ class hxb_writer
 			write_fields ()
 		| Extend tl ->
 			IOChunk.write_u8 chunk.io 2;
-			self#write_types tl;
+			self#write_types tl p;
 			write_fields ()
 		| ClassStatics _ ->
 			assert false
@@ -2021,9 +2023,9 @@ class hxb_writer
 					let close = self#open_field_scope ef.ef_params in
 					Chunk.write_string chunk s;
 					let restore = self#start_temporary_chunk 32 in
-					self#write_type_instance ef.ef_type;
+					self#write_type_instance ef.ef_type ef.ef_pos;
 					let t_bytes = restore (fun new_chunk -> IOChunk.get_bytes new_chunk.io) in
-					self#commit_field_type_parameters ef.ef_params;
+					self#commit_field_type_parameters ef.ef_params ef.ef_pos;
 					IOChunk.write_bytes chunk.io t_bytes;
 					Chunk.write_option chunk ef.ef_doc self#write_documentation;
 					self#write_metadata ef.ef_meta;

+ 2 - 1
src/context/commonCache.ml

@@ -80,7 +80,8 @@ let rec cache_context cs com =
 	let cache_module m =
 		(* If we have a signature mismatch, look-up cache for module. Physical equality check is fine as a heueristic. *)
 		let cc = if m.m_extra.m_sign = sign then cc else cs#get_context m.m_extra.m_sign in
-		cc#cache_module (MessageReporting.display_source_at com) anon_identification com.hxb_writer_stats m.m_path m;
+		let warn w s p = com.warning w com.warning_options s p in
+		cc#cache_module (MessageReporting.display_source_at com) warn anon_identification com.hxb_writer_stats m.m_path m;
 	in
 	List.iter cache_module com.modules;
 	begin match com.get_macros() with