Pārlūkot izejas kodu

[typer] clean up field-level errors (#10896)

Simon Krajewski 2 gadi atpakaļ
vecāks
revīzija
34ecf0eb70

+ 1 - 1
src/compiler/retyper.ml

@@ -66,7 +66,7 @@ let pair_class_field rctx ctx cctx fctx cf cff p =
 		)
 	| FVar(th,eo) | FProp(_,_,th,eo) ->
 		let th = Some (pair_type th cf.cf_type) in
-		let t = disable_typeloading rctx ctx (fun () -> load_variable_type_hint ctx eo (pos cff.cff_name) th) in
+		let t = disable_typeloading rctx ctx (fun () -> load_variable_type_hint ctx fctx eo (pos cff.cff_name) th) in
 		(fun () ->
 			cf.cf_type <- t;
 			TypeBinding.bind_var ctx cctx fctx cf eo;

+ 85 - 55
src/typing/typeloadFields.ml

@@ -83,6 +83,7 @@ type field_init_ctx = {
 	(* If true, cf_expr = None makes a difference in the logic. We insert a dummy expression in
 	   display mode in order to address this. *)
 	mutable expr_presence_matters : bool;
+	mutable had_error : bool;
 }
 
 type method_kind =
@@ -90,6 +91,31 @@ type method_kind =
 	| MKGetter
 	| MKSetter
 
+module FieldError = struct
+	let maybe_display_error com fctx s p =
+		if not fctx.had_error then begin
+			fctx.had_error <- true;
+			display_error com s p
+		end
+
+	let invalid_modifier_combination fctx com fctx a b p =
+		maybe_display_error com fctx (Printf.sprintf "Invalid modifier combination: %s + %s" a b) p
+
+	let invalid_modifier com fctx m c p =
+		maybe_display_error com fctx (Printf.sprintf "Invalid modifier: %s on %s" m c) p
+
+	let invalid_modifier_only com fctx m c p =
+		maybe_display_error com fctx (Printf.sprintf "Invalid modifier: %s is only supported %s" m c) p
+
+	let missing_expression com fctx reason p =
+		maybe_display_error com fctx (Printf.sprintf "%s" reason) p
+
+	let unexpected_expression com fctx reason p =
+		maybe_display_error com fctx (Printf.sprintf "%s" reason) p
+end
+
+open FieldError
+
 let dump_class_context cctx =
 	Printer.s_record_fields "" [
 		"tclass",Printer.s_tclass "\t" cctx.tclass;
@@ -122,7 +148,6 @@ let dump_field_context fctx =
 		"expr_presence_matters",string_of_bool fctx.expr_presence_matters;
 	]
 
-
 let is_java_native_function ctx meta pos = try
 	match Meta.get Meta.Native meta with
 		| (Meta.Native,[],_) ->
@@ -253,13 +278,13 @@ let transform_abstract_field com this_t a_t a f =
 		let ret p = (EReturn (Some (cast (EConst (Ident "this"),p))),p) in
 		let meta = (Meta.NoCompletion,[],null_pos) :: f.cff_meta in
 		if Meta.has Meta.MultiType a.a_meta then begin
-			if List.mem_assoc AInline f.cff_access then typing_error "MultiType constructors cannot be inline" f.cff_pos;
-			if fu.f_expr <> None then typing_error "MultiType constructors cannot have a body" f.cff_pos;
+			if List.mem_assoc AInline f.cff_access then typing_error "inline on MultiType constructor" f.cff_pos;
+			if fu.f_expr <> None then display_error com "MultiType constructors cannot have a body" f.cff_pos;
 			f.cff_access <- (AExtern,null_pos) :: f.cff_access;
 		end;
 		(try
 			let _, p = List.find (fun (acc, _) -> acc = AMacro) f.cff_access in
-			typing_error "Macro abstract constructors are not supported" p
+			typing_error "Invalid modifier: macro on abstract constructor" p
 		with Not_found -> ());
 		(* We don't want the generated expression positions to shadow the real code. *)
 		let p = { p with pmax = p.pmin } in
@@ -397,7 +422,7 @@ let build_enum_abstract ctx c a fields p =
 			in
 			let rec loop visibility acc = match acc with
 				| (AExtern,p) :: acc ->
-					display_error ctx.com "extern modifier is not allowed on enum abstract fields" p;
+					display_error ctx.com "Invalid modifier: extern on field of enum abstract" p;
 					loop visibility acc
 				| (APrivate,p) as access :: acc ->
 					check_visibility_conflict visibility p;
@@ -426,7 +451,7 @@ let build_enum_abstract ctx c a fields p =
 							set_field field ct (EConst (Int (string_of_int !i, None)),null_pos);
 							incr i;
 						| EAOther ->
-							typing_error "Value required" field.cff_pos
+							display_error ctx.com "Value required" field.cff_pos
 					end else field.cff_kind <- FProp(("default",null_pos),("never",null_pos),ct,None)
 				| Some e ->
 					begin match mode,e with
@@ -620,6 +645,7 @@ let create_field_context cctx cff is_display_file display_modifier =
 		do_bind = (((not ((has_class_flag c CExtern) || !is_extern) || is_inline) && not is_abstract && not (has_class_flag c CInterface)) || field_kind = FKInit);
 		do_add = true;
 		expr_presence_matters = false;
+		had_error = false;
 	} in
 	if fctx.is_display_field then cctx.has_display_field <- true;
 	fctx
@@ -638,11 +664,11 @@ let create_typer_context_for_field ctx cctx fctx cff =
 	let c = cctx.tclass in
 	if (fctx.is_abstract && not (has_meta Meta.LibType c.cl_meta)) then begin
 		if fctx.is_static then
-			display_error ctx.com "Static methods may not be abstract" (pos cff.cff_name)
+			invalid_modifier_combination fctx ctx.com fctx "abstract" "static" (pos cff.cff_name)
 		else if fctx.is_final then
-			display_error ctx.com "Abstract methods may not be final" (pos cff.cff_name)
+			invalid_modifier_combination fctx ctx.com fctx "abstract" "final" (pos cff.cff_name)
 		else if fctx.is_inline then
-			display_error ctx.com "Abstract methods may not be inline" (pos cff.cff_name)
+			invalid_modifier_combination fctx ctx.com fctx "abstract" "inline" (pos cff.cff_name)
 		else if not (has_class_flag c CAbstract) then begin
 			display_error ctx.com "This class should be declared abstract because it has at least one abstract field" c.cl_name_pos;
 			display_error ctx.com "First abstract field was here" (pos cff.cff_name);
@@ -830,7 +856,7 @@ module TypeBinding = struct
 		let c = cctx.tclass in
 		let t = cf.cf_type in
 		let p = cf.cf_pos in
-		if (has_class_flag c CInterface) then display_error ctx.com "Default values on interfaces are not allowed" (pos e);
+		if (has_class_flag c CInterface) then unexpected_expression ctx.com fctx "Initialization on field of interface" (pos e);
 		cf.cf_meta <- ((Meta.Value,[e],null_pos) :: cf.cf_meta);
 		let check_cast e =
 			(* insert cast to keep explicit field type (issue #1901) *)
@@ -863,15 +889,15 @@ module TypeBinding = struct
 				let e = (match cf.cf_kind with
 				| Var v when (has_class_flag c CExtern) || fctx.is_extern ->
 					if not fctx.is_static then begin
-						display_error ctx.com "Extern non-static variables may not be initialized" p;
+						unexpected_expression ctx.com fctx "on extern non-static variable" p;
 						e
 					end else if not fctx.is_inline then begin
-						display_error ctx.com "Extern non-inline variables may not be initialized" p;
+						unexpected_expression ctx.com fctx "on extern non-inline variable" p;
 						e
 					end else require_constant_expression e "Extern variable initialization must be a constant value"
 				| Var v when not (is_physical_field cf) ->
 					(* disallow initialization of non-physical fields (issue #1958) *)
-					display_error ctx.com "This field cannot be initialized because it is not a real variable" p; e
+					unexpected_expression ctx.com fctx "on field that is not a real variable" p; e
 				| Var v when not fctx.is_static ->
 					let e = begin
 						let rec check_this e = match e.eexpr with
@@ -973,9 +999,10 @@ module TypeBinding = struct
 		bind_type ctx cctx fctx cf r p
 end
 
-let load_variable_type_hint ctx eo p = function
+let load_variable_type_hint ctx fctx eo p = function
 	| None when eo = None ->
-		typing_error ("Variable requires type-hint or initialization") p;
+		missing_expression ctx.com fctx "Variable requires type-hint or initialization" p;
+		t_dynamic
 	| None ->
 		mk_mono()
 	| Some t ->
@@ -983,17 +1010,17 @@ let load_variable_type_hint ctx eo p = function
 
 let create_variable (ctx,cctx,fctx) c f t eo p =
 	let is_abstract_enum_field = Meta.has Meta.Enum f.cff_meta in
-	if fctx.is_abstract_member && not is_abstract_enum_field then typing_error (fst f.cff_name ^ ": Cannot declare member variable in abstract") p;
-	if fctx.is_inline && not fctx.is_static then typing_error (fst f.cff_name ^ ": Inline variable must be static") p;
-	if fctx.is_inline && eo = None then typing_error (fst f.cff_name ^ ": Inline variable must be initialized") p;
+	if fctx.is_abstract_member && not is_abstract_enum_field then 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;
+	if fctx.is_inline && eo = None then missing_expression ctx.com fctx "Inline variable must be initialized" p;
 	let missing_initialization =
 		fctx.is_final
 		&& not (fctx.is_extern || (has_class_flag c CExtern) || (has_class_flag c CInterface))
 		&& eo = None
 	in
 	if missing_initialization && fctx.is_static && fctx.is_final then
-		typing_error (fst f.cff_name ^ ": Static final variable must be initialized") p;
-	let t = load_variable_type_hint ctx eo (pos f.cff_name) t in
+		missing_expression ctx.com fctx "Static final variable must be initialized" p;
+	let t = load_variable_type_hint ctx fctx eo (pos f.cff_name) t in
 	let kind = if fctx.is_inline then
 		{ v_read = AccInline ; v_write = AccNever }
 	else if fctx.is_final then
@@ -1043,11 +1070,11 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
 						match t with
 							| TFun([_,_,t],_) -> t
 							| TFun([(_,_,t1);(_,true,t2)],_) when is_pos_infos t2 -> t1
-							| _ -> typing_error (cf.cf_name ^ ": @:from cast functions must accept exactly one argument") p
+							| _ -> typing_error ("@:from cast functions must accept exactly one argument") p
 					) "@:from" in
 					a.a_from_field <- (TLazy r,cf) :: a.a_from_field;
 				| (Meta.To,_,_) :: _ ->
-					if fctx.is_macro then typing_error (cf.cf_name ^ ": Macro cast functions are not supported") p;
+					if fctx.is_macro then invalid_modifier ctx.com fctx "macro" "cast function" p;
 					let are_valid_args args =
 						match args with
 						| [_] -> true
@@ -1056,10 +1083,10 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
 					in
 					(match cf.cf_kind, cf.cf_type with
 					| Var _, _ ->
-						typing_error "@:to meta should be used on methods" p
+						typing_error "Invalid metadata: @:to must be used on method of abstract" p
 					| Method _, TFun(args, _) when not fctx.is_abstract_member && not (are_valid_args args) ->
 						if not (Meta.has Meta.MultiType a.a_meta) then (* TODO: get rid of this check once multitype is removed *)
-						typing_error ("static @:to method should have one argument") p
+						typing_error "static @:to method should have one argument" p
 					| Method _, TFun(args, _) when fctx.is_abstract_member && not (are_valid_args args) ->
 						if not (Meta.has Meta.MultiType a.a_meta) then (* TODO: get rid of this check once multitype is removed *)
 						typing_error "@:to method should have no arguments" p
@@ -1100,18 +1127,18 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
 					) "@:to" in
 					a.a_to_field <- (TLazy r, cf) :: a.a_to_field
 				| ((Meta.ArrayAccess,_,_) | (Meta.Op,[(EArrayDecl _),_],_)) :: _ ->
-					if fctx.is_macro then typing_error (cf.cf_name ^ ": Macro array-access functions are not supported") p;
+					if fctx.is_macro then invalid_modifier ctx.com fctx "macro" "array-access function" p;
 					a.a_array <- cf :: a.a_array;
 					allow_no_expr();
 				| (Meta.Op,[EBinop(OpAssign,_,_),_],_) :: _ ->
-					typing_error (cf.cf_name ^ ": Assignment overloading is not supported") p;
+					typing_error "Assignment overloading is not supported" p;
 				| (Meta.Op,[EBinop(OpAssignOp OpNullCoal,_,_),_],_) :: _
 				| (Meta.Op,[EBinop(OpNullCoal,_,_),_],_) :: _ ->
-					typing_error (cf.cf_name ^ ": Null coalescing overloading is not supported") p;
+					typing_error "Null coalescing overloading is not supported" p;
 				| (Meta.Op,[ETernary(_,_,_),_],_) :: _ ->
-					typing_error (cf.cf_name ^ ": Ternary overloading is not supported") p;
+					typing_error "Ternary overloading is not supported" p;
 				| (Meta.Op,[EBinop(op,_,_),_],_) :: _ ->
-					if fctx.is_macro then typing_error (cf.cf_name ^ ": Macro operator functions are not supported") p;
+					if fctx.is_macro then invalid_modifier ctx.com fctx "macro" "operator function" p;
 					let targ = if fctx.is_abstract_member then tthis else ta in
 					let left_eq,right_eq =
 						match follow t with
@@ -1121,16 +1148,16 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
 							type_iseq targ t1,type_iseq targ t2
 						| _ ->
 							if fctx.is_abstract_member then
-								typing_error (cf.cf_name ^ ": Member @:op functions must accept exactly one argument") cf.cf_pos
+								typing_error ("Member @:op functions must accept exactly one argument") cf.cf_pos
 							else
-								typing_error (cf.cf_name ^ ": Static @:op functions must accept exactly two arguments") cf.cf_pos
+								typing_error ("Static @:op functions must accept exactly two arguments") cf.cf_pos
 					in
-					if not (left_eq || right_eq) then typing_error (cf.cf_name ^ ": The left or right argument type must be " ^ (s_type (print_context()) targ)) cf.cf_pos;
-					if right_eq && Meta.has Meta.Commutative cf.cf_meta then typing_error (cf.cf_name ^ ": @:commutative is only allowed if the right argument is not " ^ (s_type (print_context()) targ)) cf.cf_pos;
+					if not (left_eq || right_eq) then typing_error ("The left or right argument type must be " ^ (s_type (print_context()) targ)) cf.cf_pos;
+					if right_eq && Meta.has Meta.Commutative cf.cf_meta then typing_error ("Invalid metadata: @:commutative is only allowed if the right argument is not " ^ (s_type (print_context()) targ)) cf.cf_pos;
 					a.a_ops <- (op,cf) :: a.a_ops;
 					allow_no_expr();
 				| (Meta.Op,[EUnop(op,flag,_),_],_) :: _ ->
-					if fctx.is_macro then typing_error (cf.cf_name ^ ": Macro operator functions are not supported") p;
+					if fctx.is_macro then invalid_modifier ctx.com fctx "macro" "operator function" p;
 					let targ = if fctx.is_abstract_member then tthis else ta in
 					(try type_eq EqStrict t (tfun [targ] (mk_mono())) with Unify_error l -> raise (Error ((Unify l),cf.cf_pos)));
 					a.a_unops <- (op,flag,cf) :: a.a_unops;
@@ -1171,8 +1198,8 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
 			loop cf.cf_meta;
 			if cf.cf_name = "_new" && Meta.has Meta.MultiType a.a_meta then fctx.do_bind <- false;
 			if fd.f_expr = None then begin
-				if fctx.is_inline then typing_error (cf.cf_name ^ ": Inline functions must have an expression") cf.cf_pos;
-				if fd.f_type = None then typing_error (cf.cf_name ^ ": Functions without expressions must have an explicit return type") cf.cf_pos;
+				if fctx.is_inline then missing_expression ctx.com fctx "Inline functions must have an expression" cf.cf_pos;
+				if fd.f_type = None then typing_error ("Functions without expressions must have an explicit return type") cf.cf_pos;
 				if !allows_no_expr then begin
 					cf.cf_meta <- (Meta.NoExpr,[],null_pos) :: cf.cf_meta;
 					fctx.do_bind <- false;
@@ -1262,7 +1289,7 @@ let create_method (ctx,cctx,fctx) c f fd p =
 	let name = fst f.cff_name in
 	let params = TypeloadFunction.type_function_params ctx fd name p in
 	if fctx.is_generic then begin
-		if params = [] then typing_error (fst f.cff_name ^ ": Generic functions must have type parameters") p;
+		if params = [] then typing_error "Generic functions must have type parameters" p;
 	end;
 	let fd = if fctx.is_macro && not ctx.com.is_macro_context && not fctx.is_static then
 		(* remove display of first argument which will contain the "this" expression *)
@@ -1308,26 +1335,29 @@ let create_method (ctx,cctx,fctx) c f fd p =
 		| true,FKConstructor ->
 			typing_error "An interface cannot have a constructor" p;
 		| true,_ ->
-			if not fctx.is_static && fd.f_expr <> None then typing_error (fst f.cff_name ^ ": An interface method cannot have a body") p;
-			if fctx.is_inline && (has_class_flag c CInterface) then typing_error (fst f.cff_name ^ ": You can't declare inline methods in interfaces") p;
+			if not fctx.is_static && fd.f_expr <> None then unexpected_expression ctx.com fctx ("An interface method cannot have a body") p;
+			if fctx.is_inline && (has_class_flag c CInterface) then invalid_modifier ctx.com fctx "inline" "method of interface" p;
 		| false,FKConstructor ->
-			if fctx.is_static then typing_error "A constructor must not be static" p;
+			if fctx.is_static then invalid_modifier ctx.com fctx "static" "constructor" p;
 			begin match fd.f_type with
 				| None -> ()
 				| Some (CTPath ({ tpackage = []; tname = "Void" } as tp),p) ->
 					if ctx.is_display_file && DisplayPosition.display_position#enclosed_in p then
 						ignore(load_instance ~allow_display:true ctx (tp,p) false);
-				| _ -> typing_error "A class constructor can't have a return value" p;
+				| _ -> typing_error "A class constructor can't have a return type" p;
 			end
 		| false,_ ->
 			()
 	end;
 	let parent = (if not fctx.is_static then get_parent c name else None) in
 	let dynamic = List.mem_assoc ADynamic f.cff_access || (match parent with Some { cf_kind = Method MethDynamic } -> true | _ -> false) in
-	if fctx.is_abstract && dynamic then display_error ctx.com "Abstract methods may not be dynamic" p;
-	if fctx.is_inline && dynamic then typing_error (fst f.cff_name ^ ": 'inline' is not allowed on 'dynamic' functions") p;
+	if dynamic then begin
+		if fctx.is_abstract then invalid_modifier_combination fctx ctx.com fctx "abstract" "dynamic" p;
+		if fctx.is_inline then invalid_modifier_combination fctx ctx.com fctx "dynamic" "inline" p;
+		if fctx.is_abstract_member then invalid_modifier ctx.com fctx "dynamic" "method of abstract" p;
+	end;
 	let is_override = Option.is_some fctx.override in
-	if (is_override && fctx.is_static) then typing_error (fst f.cff_name ^ ": 'override' is not allowed on 'static' functions") p;
+	if (is_override && fctx.is_static) then invalid_modifier_combination fctx ctx.com fctx "override" "static" p;
 
 	ctx.type_params <- if fctx.is_static && not fctx.is_abstract_member then params else params @ ctx.type_params;
 	(* TODO is_lib: avoid forcing the return type to be typed *)
@@ -1348,7 +1378,7 @@ let create_method (ctx,cctx,fctx) c f fd p =
 				try List.assoc AAbstract f.cff_access
 				with Not_found -> p
 			in
-			display_error ctx.com "Constructors cannot be abstract" p
+			invalid_modifier ctx.com fctx "abstract" "constructor" p
 		end;
 		add_class_field_flag cf CfAbstract;
 	end;
@@ -1358,10 +1388,10 @@ let create_method (ctx,cctx,fctx) c f fd p =
 	| Some p ->
 		begin match ctx.com.platform with
 		| Java ->
-			if not (has_class_flag ctx.curclass CExtern) || not (has_class_flag c CInterface) then display_error ctx.com "The default modifier is only allowed on extern interfaces" p;
+			if not (has_class_flag ctx.curclass CExtern) || not (has_class_flag c CInterface) then invalid_modifier_only ctx.com fctx "default" "on extern interfaces" p;
 			add_class_field_flag cf CfDefault;
 		| _ ->
-			display_error ctx.com "The default modifier is only supported on the Java target" p
+			invalid_modifier_only ctx.com fctx "default" "on the Java target" p
 		end;
 	| None ->
 		()
@@ -1371,11 +1401,11 @@ let create_method (ctx,cctx,fctx) c f fd p =
 		if ctx.com.config.pf_overload then
 			add_class_field_flag cf CfOverload
 		else if fctx.field_kind = FKConstructor then
-			display_error ctx.com "Constructors cannot be overloaded on this target" p
+			invalid_modifier ctx.com fctx "overload" "constructor" p
 		else begin
 			add_class_field_flag cf CfOverload;
 			if not (has_class_flag c CExtern || fctx.is_extern) then
-				display_error ctx.com "Only extern functions may be overloaded on this target" p
+				invalid_modifier_only ctx.com fctx "overload" "on extern functions" p
 		end
 	| None ->
 		()
@@ -1408,7 +1438,7 @@ let create_method (ctx,cctx,fctx) c f fd p =
 		end else
 			delay ctx PTypeField (fun () -> args#verify_extern);
 		if fd.f_expr <> None then begin
-			if fctx.is_abstract then display_error ctx.com "Abstract methods may not have an expression" p
+			if fctx.is_abstract then unexpected_expression ctx.com fctx "Abstract methods may not have an expression" p
 			else if not (fctx.is_inline || fctx.is_macro) then warning ctx WExternWithExpr "Extern non-inline function may not have an expression" p;
 		end;
 	end;
@@ -1418,13 +1448,13 @@ let create_property (ctx,cctx,fctx) c f (get,set,t,eo) p =
 	let name = fst f.cff_name in
 	(* TODO is_lib: lazify load_complex_type *)
 	let ret = (match t, eo with
-		| None, None -> typing_error (name ^ ": Property requires type-hint or initialization") p;
+		| None, None -> typing_error "Property requires type-hint or initialization" p;
 		| None, _ -> mk_mono()
 		| Some t, _ -> lazy_display_type ctx (fun () -> load_type_hint ctx p (Some t))
 	) in
 	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 typing_error (name ^ ": Abstract properties cannot be real variables") f.cff_pos;
+			if Meta.has Meta.IsVar f.cff_meta then typing_error "Abstract properties cannot be real variables" f.cff_pos;
 			let ta = apply_params a.a_params (extract_param_types a.a_params) a.a_this in
 			tfun [ta] ret, tfun [ta;ret] ret
 		| _ -> tfun [] ret, TFun(["value",false,ret],ret)
@@ -1571,7 +1601,7 @@ let reject_final_static_method ctx cctx fctx f =
 					try snd (List.find (fun (a,p) -> a = AStatic) f.cff_access)
 					with Not_found -> f.cff_pos
 		in
-		ctx.com.error "Static method cannot be final" p
+		invalid_modifier_combination fctx ctx.com fctx "final" "static" p
 
 let init_field (ctx,cctx,fctx) f =
 	let c = cctx.tclass in
@@ -1594,7 +1624,7 @@ let init_field (ctx,cctx,fctx) f =
 					try List.assoc AOverride f.cff_access
 					with Not_found -> p
 				in
-				typing_error ("Invalid override on field '" ^ name ^ "': class has no super class") p
+				invalid_modifier ctx.com fctx "override" "field of class that has no parent" p
 			| _ -> ()
 			);
 		| None -> ()
@@ -1763,7 +1793,7 @@ let init_class ctx c p context_init herits fields =
 					else
 						display_error ctx.com ("If using overloaded constructors, all constructors must be declared with 'overload'") (if has_class_field_flag cf CfOverload then ctor.cf_pos else cf.cf_pos)
 				| Some ctor ->
-							display_error ctx.com "Duplicate constructor" p
+						display_error ctx.com "Duplicate constructor" p
 				end
 			| FKInit ->
 				()

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

@@ -1 +1 @@
-Main.hx:5: characters 16-24 : Only extern functions may be overloaded on this target
+Main.hx:5: characters 16-24 : Invalid modifier: overload is only supported on extern functions

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

@@ -1 +1 @@
-Main.hx:6: characters 2-10 : Constructors cannot be abstract
+Main.hx:6: characters 2-10 : Invalid modifier: abstract on constructor

+ 7 - 0
tests/misc/projects/Issue10881/Main.hx

@@ -0,0 +1,7 @@
+abstract SerArray<S>(Array<S>) {
+	public dynamic function onChange():Void {};
+}
+
+class Main {
+	static function main() {}
+}

+ 2 - 0
tests/misc/projects/Issue10881/compile-fail.hxml

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

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

@@ -0,0 +1 @@
+Main.hx:2: characters 2-44 : Invalid modifier: dynamic on method of abstract

+ 1 - 1
tests/misc/projects/Issue6584/compile1-fail.hxml.stderr

@@ -1 +1 @@
-Main1.hx:2: characters 2-17 : v: Static final variable must be initialized
+Main1.hx:2: characters 2-17 : Static final variable must be initialized

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

@@ -1 +1 @@
-Main.hx:6: lines 6-8 : opAssign: Assignment overloading is not supported
+Main.hx:6: lines 6-8 : Assignment overloading is not supported

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

@@ -1,2 +1,2 @@
-Main.hx:2: characters 2-7 : Static method cannot be final
+Main.hx:2: characters 2-7 : Invalid modifier combination: final + static
 Main.hx:9: lines 9-11 : Cannot override final constructor

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

@@ -1 +1 @@
-Main.hx:6: characters 2-7 : Macro abstract constructors are not supported
+Main.hx:6: characters 2-7 : Invalid modifier: macro on abstract constructor

+ 1 - 1
tests/misc/projects/Issue8828/compile1-fail.hxml.stderr

@@ -1 +1 @@
-Main1.hx:2: characters 2-8 : extern modifier is not allowed on enum abstract fields
+Main1.hx:2: characters 2-8 : Invalid modifier: extern on field of enum abstract

+ 2 - 2
tests/misc/projects/Issue9014/compile-fail.hxml.stderr

@@ -1,2 +1,2 @@
-Main.hx:3: characters 2-40 : foo: 'override' is not allowed on 'static' functions
-Main.hx:4: characters 2-39 : bar: 'inline' is not allowed on 'dynamic' functions
+Main.hx:3: characters 2-40 : Invalid modifier combination: override + static
+Main.hx:4: characters 2-39 : Invalid modifier combination: dynamic + inline

+ 1 - 1
tests/misc/projects/Issue9619/abstract-dynamic/compile-fail.hxml.stderr

@@ -1 +1 @@
-Main.hx:2: characters 2-52 : Abstract methods may not be dynamic
+Main.hx:2: characters 2-52 : Invalid modifier combination: abstract + dynamic

+ 1 - 1
tests/misc/projects/Issue9619/abstract-final/compile-fail.hxml.stderr

@@ -1 +1 @@
-Main.hx:2: characters 26-42 : Abstract methods may not be final
+Main.hx:2: characters 26-42 : Invalid modifier combination: abstract + final

+ 1 - 1
tests/misc/projects/Issue9619/abstract-inline/compile-fail.hxml.stderr

@@ -1 +1 @@
-Main.hx:2: characters 34-50 : Abstract methods may not be inline
+Main.hx:2: characters 34-50 : Invalid modifier combination: abstract + inline

+ 1 - 1
tests/misc/projects/Issue9619/abstract-static/compile-fail.hxml.stderr

@@ -1 +1 @@
-Main.hx:2: characters 27-43 : Static methods may not be abstract
+Main.hx:2: characters 27-43 : Invalid modifier combination: abstract + static

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

@@ -1 +1 @@
-Main.hx:2: characters 2-19 : x: Cannot declare member variable in abstract
+Main.hx:2: characters 2-19 : Cannot declare member variable in abstract

+ 1 - 1
tests/misc/projects/extern-overloads/not-not-extern/compile-fail.hxml.stderr

@@ -1 +1 @@
-Main.hx:2: characters 2-10 : Only extern functions may be overloaded on this target
+Main.hx:2: characters 2-10 : Invalid modifier: overload is only supported on extern functions

+ 1 - 1
tests/misc/projects/extern-overloads/not-on-constructor/compile-fail.hxml.stderr

@@ -1 +1 @@
-Main.hx:2: characters 2-10 : Constructors cannot be overloaded on this target
+Main.hx:2: characters 2-10 : Invalid modifier: overload on constructor

+ 3 - 3
tests/misc/src/Main.hx

@@ -147,9 +147,9 @@ class Main {
 				.join('\n');
 
 			if (content != expected) {
-				println('Actual $name output doesn\'t match the expected one');
-				println('Expected:\n"$expected"');
-				println('Actual:\n"$content"');
+				println('Expected:\n$expected');
+				println('Actual:\n$content');
+				println('');
 				return false;
 			}
 		}

+ 1 - 1
tests/unit/compile-each.hxml

@@ -7,6 +7,6 @@
 --resource serializedValues.txt
 --macro Macro.init()
 --dce full
--lib utest:git:https://github.com/haxe-utest/utest#559b24c9a36533281ba7a2eed8aab83ed6b872b4
+-lib utest
 -D analyzer-optimize
 -D analyzer-user-var-fusion