浏览代码

[typer] only allow `@:hack` when extending extern classes

And optimize eval calls accordingly.

closes #7473
see https://github.com/HaxeFoundation/crypto/issues/4
Simon Krajewski 7 年之前
父节点
当前提交
040bf60075
共有 2 个文件被更改,包括 10 次插入15 次删除
  1. 9 14
      src/macro/eval/evalJit.ml
  2. 1 1
      src/typing/typeloadCheck.ml

+ 9 - 14
src/macro/eval/evalJit.ml

@@ -302,23 +302,18 @@ and jit_expr jit return e =
 		| TField(ef,fa) ->
 		| TField(ef,fa) ->
 			let name = hash (field_name fa) in
 			let name = hash (field_name fa) in
 			let execs = List.map (jit_expr jit false) el in
 			let execs = List.map (jit_expr jit false) el in
-			(* let is_overridden c s_name =
-				try
-					Hashtbl.find ctx.overrides (c.cl_path,s_name)
-				with Not_found ->
-					false
-			in *)
+			let is_final c cf = c.cl_final || cf.cf_final in
 			let is_proper_method cf = match cf.cf_kind with
 			let is_proper_method cf = match cf.cf_kind with
 				| Method MethDynamic -> false
 				| Method MethDynamic -> false
 				| Method _ -> true
 				| Method _ -> true
 				| Var _ -> false
 				| Var _ -> false
 			in
 			in
-			(* let instance_call c =
+			let instance_call c =
 				let exec = jit_expr jit false ef in
 				let exec = jit_expr jit false ef in
 				let proto = get_instance_prototype ctx (path_hash c.cl_path) ef.epos in
 				let proto = get_instance_prototype ctx (path_hash c.cl_path) ef.epos in
 				let i = get_proto_field_index proto name in
 				let i = get_proto_field_index proto name in
 				emit_proto_field_call proto i (exec :: execs) e.epos
 				emit_proto_field_call proto i (exec :: execs) e.epos
-			in *)
+			in
 			let default () =
 			let default () =
 				let exec = jit_expr jit false ef in
 				let exec = jit_expr jit false ef in
 				emit_method_call exec name execs e.epos
 				emit_method_call exec name execs e.epos
@@ -338,18 +333,18 @@ and jit_expr jit return e =
 					let i = get_proto_field_index proto name in
 					let i = get_proto_field_index proto name in
 					emit_proto_field_call proto i execs e.epos
 					emit_proto_field_call proto i execs e.epos
 				| FInstance(c,_,cf) when is_proper_method cf ->
 				| FInstance(c,_,cf) when is_proper_method cf ->
-					default();
-					(* if is_overridden c cf.cf_name then
+					if not (is_final c cf) then
 						default()
 						default()
 					else if not c.cl_interface then
 					else if not c.cl_interface then
 						instance_call c
 						instance_call c
-					else if c.cl_implements = [] && c.cl_super = None then begin match c.cl_descendants with
+					(* still can't do this because of incomplete information *)
+					(* else if c.cl_implements = [] && c.cl_super = None then begin match c.cl_descendants with
 						| [c'] when not c'.cl_interface && not (is_overridden c' cf.cf_name) ->
 						| [c'] when not c'.cl_interface && not (is_overridden c' cf.cf_name) ->
 							instance_call c'
 							instance_call c'
 						| _ ->
 						| _ ->
-							default()
-					end else
-						default() *)
+							default() *)
+					else
+						default()
 				| _ ->
 				| _ ->
 					let exec = jit_expr jit false ef in
 					let exec = jit_expr jit false ef in
 					emit_field_call exec name execs e.epos
 					emit_field_call exec name execs e.epos

+ 1 - 1
src/typing/typeloadCheck.ml

@@ -368,7 +368,7 @@ module Inheritance = struct
 				| Meta.AutoBuild, el, p -> c.cl_meta <- (Meta.Build,el,{ c.cl_pos with pmax = c.cl_pos.pmin }(* prevent display metadata *)) :: m :: c.cl_meta
 				| Meta.AutoBuild, el, p -> c.cl_meta <- (Meta.Build,el,{ c.cl_pos with pmax = c.cl_pos.pmin }(* prevent display metadata *)) :: m :: c.cl_meta
 				| _ -> ()
 				| _ -> ()
 			) csup.cl_meta;
 			) csup.cl_meta;
-			if csup.cl_final && not (Meta.has Meta.Hack c.cl_meta || (match c.cl_kind with KTypeParameter _ -> true | _ -> false)) then
+			if csup.cl_final && not ((csup.cl_extern && Meta.has Meta.Hack c.cl_meta) || (match c.cl_kind with KTypeParameter _ -> true | _ -> false)) then
 				error ("Cannot extend a final " ^ if c.cl_interface then "interface" else "class") p;
 				error ("Cannot extend a final " ^ if c.cl_interface then "interface" else "class") p;
 		in
 		in
 		let check_cancel_build csup =
 		let check_cancel_build csup =