|
@@ -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
|
|
(* If true, cf_expr = None makes a difference in the logic. We insert a dummy expression in
|
|
display mode in order to address this. *)
|
|
display mode in order to address this. *)
|
|
mutable expr_presence_matters : bool;
|
|
mutable expr_presence_matters : bool;
|
|
|
|
+ mutable had_error : bool;
|
|
}
|
|
}
|
|
|
|
|
|
type method_kind =
|
|
type method_kind =
|
|
@@ -90,6 +91,31 @@ type method_kind =
|
|
| MKGetter
|
|
| MKGetter
|
|
| MKSetter
|
|
| 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 =
|
|
let dump_class_context cctx =
|
|
Printer.s_record_fields "" [
|
|
Printer.s_record_fields "" [
|
|
"tclass",Printer.s_tclass "\t" cctx.tclass;
|
|
"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;
|
|
"expr_presence_matters",string_of_bool fctx.expr_presence_matters;
|
|
]
|
|
]
|
|
|
|
|
|
-
|
|
|
|
let is_java_native_function ctx meta pos = try
|
|
let is_java_native_function ctx meta pos = try
|
|
match Meta.get Meta.Native meta with
|
|
match Meta.get Meta.Native meta with
|
|
| (Meta.Native,[],_) ->
|
|
| (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 ret p = (EReturn (Some (cast (EConst (Ident "this"),p))),p) in
|
|
let meta = (Meta.NoCompletion,[],null_pos) :: f.cff_meta in
|
|
let meta = (Meta.NoCompletion,[],null_pos) :: f.cff_meta in
|
|
if Meta.has Meta.MultiType a.a_meta then begin
|
|
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;
|
|
f.cff_access <- (AExtern,null_pos) :: f.cff_access;
|
|
end;
|
|
end;
|
|
(try
|
|
(try
|
|
let _, p = List.find (fun (acc, _) -> acc = AMacro) f.cff_access in
|
|
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 -> ());
|
|
with Not_found -> ());
|
|
(* We don't want the generated expression positions to shadow the real code. *)
|
|
(* We don't want the generated expression positions to shadow the real code. *)
|
|
let p = { p with pmax = p.pmin } in
|
|
let p = { p with pmax = p.pmin } in
|
|
@@ -397,7 +422,7 @@ let build_enum_abstract ctx c a fields p =
|
|
in
|
|
in
|
|
let rec loop visibility acc = match acc with
|
|
let rec loop visibility acc = match acc with
|
|
| (AExtern,p) :: acc ->
|
|
| (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
|
|
loop visibility acc
|
|
| (APrivate,p) as access :: acc ->
|
|
| (APrivate,p) as access :: acc ->
|
|
check_visibility_conflict visibility p;
|
|
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);
|
|
set_field field ct (EConst (Int (string_of_int !i, None)),null_pos);
|
|
incr i;
|
|
incr i;
|
|
| EAOther ->
|
|
| 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)
|
|
end else field.cff_kind <- FProp(("default",null_pos),("never",null_pos),ct,None)
|
|
| Some e ->
|
|
| Some e ->
|
|
begin match mode,e with
|
|
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_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;
|
|
do_add = true;
|
|
expr_presence_matters = false;
|
|
expr_presence_matters = false;
|
|
|
|
+ had_error = false;
|
|
} in
|
|
} in
|
|
if fctx.is_display_field then cctx.has_display_field <- true;
|
|
if fctx.is_display_field then cctx.has_display_field <- true;
|
|
fctx
|
|
fctx
|
|
@@ -638,11 +664,11 @@ let create_typer_context_for_field ctx cctx fctx cff =
|
|
let c = cctx.tclass in
|
|
let c = cctx.tclass in
|
|
if (fctx.is_abstract && not (has_meta Meta.LibType c.cl_meta)) then begin
|
|
if (fctx.is_abstract && not (has_meta Meta.LibType c.cl_meta)) then begin
|
|
if fctx.is_static then
|
|
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
|
|
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
|
|
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
|
|
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 "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);
|
|
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 c = cctx.tclass in
|
|
let t = cf.cf_type in
|
|
let t = cf.cf_type in
|
|
let p = cf.cf_pos 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);
|
|
cf.cf_meta <- ((Meta.Value,[e],null_pos) :: cf.cf_meta);
|
|
let check_cast e =
|
|
let check_cast e =
|
|
(* insert cast to keep explicit field type (issue #1901) *)
|
|
(* insert cast to keep explicit field type (issue #1901) *)
|
|
@@ -863,15 +889,15 @@ module TypeBinding = struct
|
|
let e = (match cf.cf_kind with
|
|
let e = (match cf.cf_kind with
|
|
| Var v when (has_class_flag c CExtern) || fctx.is_extern ->
|
|
| Var v when (has_class_flag c CExtern) || fctx.is_extern ->
|
|
if not fctx.is_static then begin
|
|
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
|
|
e
|
|
end else if not fctx.is_inline then begin
|
|
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
|
|
e
|
|
end else require_constant_expression e "Extern variable initialization must be a constant value"
|
|
end else require_constant_expression e "Extern variable initialization must be a constant value"
|
|
| Var v when not (is_physical_field cf) ->
|
|
| Var v when not (is_physical_field cf) ->
|
|
(* disallow initialization of non-physical fields (issue #1958) *)
|
|
(* 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 ->
|
|
| Var v when not fctx.is_static ->
|
|
let e = begin
|
|
let e = begin
|
|
let rec check_this e = match e.eexpr with
|
|
let rec check_this e = match e.eexpr with
|
|
@@ -973,9 +999,10 @@ module TypeBinding = struct
|
|
bind_type ctx cctx fctx cf r p
|
|
bind_type ctx cctx fctx cf r p
|
|
end
|
|
end
|
|
|
|
|
|
-let load_variable_type_hint ctx eo p = function
|
|
|
|
|
|
+let load_variable_type_hint ctx fctx eo p = function
|
|
| None when eo = None ->
|
|
| 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 ->
|
|
| None ->
|
|
mk_mono()
|
|
mk_mono()
|
|
| Some t ->
|
|
| 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 create_variable (ctx,cctx,fctx) c f t eo p =
|
|
let is_abstract_enum_field = Meta.has Meta.Enum f.cff_meta in
|
|
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 =
|
|
let missing_initialization =
|
|
fctx.is_final
|
|
fctx.is_final
|
|
&& not (fctx.is_extern || (has_class_flag c CExtern) || (has_class_flag c CInterface))
|
|
&& not (fctx.is_extern || (has_class_flag c CExtern) || (has_class_flag c CInterface))
|
|
&& eo = None
|
|
&& eo = None
|
|
in
|
|
in
|
|
if missing_initialization && fctx.is_static && fctx.is_final then
|
|
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
|
|
let kind = if fctx.is_inline then
|
|
{ v_read = AccInline ; v_write = AccNever }
|
|
{ v_read = AccInline ; v_write = AccNever }
|
|
else if fctx.is_final then
|
|
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
|
|
match t with
|
|
| TFun([_,_,t],_) -> t
|
|
| TFun([_,_,t],_) -> t
|
|
| TFun([(_,_,t1);(_,true,t2)],_) when is_pos_infos t2 -> t1
|
|
| 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
|
|
) "@:from" in
|
|
a.a_from_field <- (TLazy r,cf) :: a.a_from_field;
|
|
a.a_from_field <- (TLazy r,cf) :: a.a_from_field;
|
|
| (Meta.To,_,_) :: _ ->
|
|
| (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 =
|
|
let are_valid_args args =
|
|
match args with
|
|
match args with
|
|
| [_] -> true
|
|
| [_] -> true
|
|
@@ -1056,10 +1083,10 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
|
|
in
|
|
in
|
|
(match cf.cf_kind, cf.cf_type with
|
|
(match cf.cf_kind, cf.cf_type with
|
|
| Var _, _ ->
|
|
| 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) ->
|
|
| 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 *)
|
|
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) ->
|
|
| 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 *)
|
|
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
|
|
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
|
|
) "@:to" in
|
|
a.a_to_field <- (TLazy r, cf) :: a.a_to_field
|
|
a.a_to_field <- (TLazy r, cf) :: a.a_to_field
|
|
| ((Meta.ArrayAccess,_,_) | (Meta.Op,[(EArrayDecl _),_],_)) :: _ ->
|
|
| ((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;
|
|
a.a_array <- cf :: a.a_array;
|
|
allow_no_expr();
|
|
allow_no_expr();
|
|
| (Meta.Op,[EBinop(OpAssign,_,_),_],_) :: _ ->
|
|
| (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(OpAssignOp OpNullCoal,_,_),_],_) :: _
|
|
| (Meta.Op,[EBinop(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(_,_,_),_],_) :: _ ->
|
|
| (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,_,_),_],_) :: _ ->
|
|
| (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 targ = if fctx.is_abstract_member then tthis else ta in
|
|
let left_eq,right_eq =
|
|
let left_eq,right_eq =
|
|
match follow t with
|
|
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
|
|
type_iseq targ t1,type_iseq targ t2
|
|
| _ ->
|
|
| _ ->
|
|
if fctx.is_abstract_member then
|
|
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
|
|
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
|
|
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;
|
|
a.a_ops <- (op,cf) :: a.a_ops;
|
|
allow_no_expr();
|
|
allow_no_expr();
|
|
| (Meta.Op,[EUnop(op,flag,_),_],_) :: _ ->
|
|
| (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
|
|
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)));
|
|
(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;
|
|
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;
|
|
loop cf.cf_meta;
|
|
if cf.cf_name = "_new" && Meta.has Meta.MultiType a.a_meta then fctx.do_bind <- false;
|
|
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 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
|
|
if !allows_no_expr then begin
|
|
cf.cf_meta <- (Meta.NoExpr,[],null_pos) :: cf.cf_meta;
|
|
cf.cf_meta <- (Meta.NoExpr,[],null_pos) :: cf.cf_meta;
|
|
fctx.do_bind <- false;
|
|
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 name = fst f.cff_name in
|
|
let params = TypeloadFunction.type_function_params ctx fd name p in
|
|
let params = TypeloadFunction.type_function_params ctx fd name p in
|
|
if fctx.is_generic then begin
|
|
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;
|
|
end;
|
|
let fd = if fctx.is_macro && not ctx.com.is_macro_context && not fctx.is_static then
|
|
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 *)
|
|
(* 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 ->
|
|
| true,FKConstructor ->
|
|
typing_error "An interface cannot have a constructor" p;
|
|
typing_error "An interface cannot have a constructor" p;
|
|
| true,_ ->
|
|
| 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 ->
|
|
| 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
|
|
begin match fd.f_type with
|
|
| None -> ()
|
|
| None -> ()
|
|
| Some (CTPath ({ tpackage = []; tname = "Void" } as tp),p) ->
|
|
| Some (CTPath ({ tpackage = []; tname = "Void" } as tp),p) ->
|
|
if ctx.is_display_file && DisplayPosition.display_position#enclosed_in p then
|
|
if ctx.is_display_file && DisplayPosition.display_position#enclosed_in p then
|
|
ignore(load_instance ~allow_display:true ctx (tp,p) false);
|
|
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
|
|
end
|
|
| false,_ ->
|
|
| false,_ ->
|
|
()
|
|
()
|
|
end;
|
|
end;
|
|
let parent = (if not fctx.is_static then get_parent c name else None) in
|
|
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
|
|
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
|
|
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;
|
|
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 *)
|
|
(* 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
|
|
try List.assoc AAbstract f.cff_access
|
|
with Not_found -> p
|
|
with Not_found -> p
|
|
in
|
|
in
|
|
- display_error ctx.com "Constructors cannot be abstract" p
|
|
|
|
|
|
+ invalid_modifier ctx.com fctx "abstract" "constructor" p
|
|
end;
|
|
end;
|
|
add_class_field_flag cf CfAbstract;
|
|
add_class_field_flag cf CfAbstract;
|
|
end;
|
|
end;
|
|
@@ -1358,10 +1388,10 @@ let create_method (ctx,cctx,fctx) c f fd p =
|
|
| Some p ->
|
|
| Some p ->
|
|
begin match ctx.com.platform with
|
|
begin match ctx.com.platform with
|
|
| Java ->
|
|
| 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;
|
|
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;
|
|
end;
|
|
| None ->
|
|
| None ->
|
|
()
|
|
()
|
|
@@ -1371,11 +1401,11 @@ let create_method (ctx,cctx,fctx) c f fd p =
|
|
if ctx.com.config.pf_overload then
|
|
if ctx.com.config.pf_overload then
|
|
add_class_field_flag cf CfOverload
|
|
add_class_field_flag cf CfOverload
|
|
else if fctx.field_kind = FKConstructor then
|
|
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
|
|
else begin
|
|
add_class_field_flag cf CfOverload;
|
|
add_class_field_flag cf CfOverload;
|
|
if not (has_class_flag c CExtern || fctx.is_extern) then
|
|
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
|
|
end
|
|
| None ->
|
|
| None ->
|
|
()
|
|
()
|
|
@@ -1408,7 +1438,7 @@ let create_method (ctx,cctx,fctx) c f fd p =
|
|
end else
|
|
end else
|
|
delay ctx PTypeField (fun () -> args#verify_extern);
|
|
delay ctx PTypeField (fun () -> args#verify_extern);
|
|
if fd.f_expr <> None then begin
|
|
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;
|
|
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;
|
|
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
|
|
let name = fst f.cff_name in
|
|
(* TODO is_lib: lazify load_complex_type *)
|
|
(* TODO is_lib: lazify load_complex_type *)
|
|
let ret = (match t, eo with
|
|
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()
|
|
| None, _ -> mk_mono()
|
|
| Some t, _ -> lazy_display_type ctx (fun () -> load_type_hint ctx p (Some t))
|
|
| Some t, _ -> lazy_display_type ctx (fun () -> load_type_hint ctx p (Some t))
|
|
) in
|
|
) in
|
|
let t_get,t_set = match cctx.abstract with
|
|
let t_get,t_set = match cctx.abstract with
|
|
| Some a when fctx.is_abstract_member ->
|
|
| 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
|
|
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 [ta] ret, tfun [ta;ret] ret
|
|
| _ -> tfun [] ret, TFun(["value",false,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)
|
|
try snd (List.find (fun (a,p) -> a = AStatic) f.cff_access)
|
|
with Not_found -> f.cff_pos
|
|
with Not_found -> f.cff_pos
|
|
in
|
|
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 init_field (ctx,cctx,fctx) f =
|
|
let c = cctx.tclass in
|
|
let c = cctx.tclass in
|
|
@@ -1594,7 +1624,7 @@ let init_field (ctx,cctx,fctx) f =
|
|
try List.assoc AOverride f.cff_access
|
|
try List.assoc AOverride f.cff_access
|
|
with Not_found -> p
|
|
with Not_found -> p
|
|
in
|
|
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 -> ()
|
|
| None -> ()
|
|
@@ -1763,7 +1793,7 @@ let init_class ctx c p context_init herits fields =
|
|
else
|
|
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)
|
|
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 ->
|
|
| Some ctor ->
|
|
- display_error ctx.com "Duplicate constructor" p
|
|
|
|
|
|
+ display_error ctx.com "Duplicate constructor" p
|
|
end
|
|
end
|
|
| FKInit ->
|
|
| FKInit ->
|
|
()
|
|
()
|