Browse Source

[typer] support @:from(ignoredByInference)

see #10739
Simon Krajewski 2 years ago
parent
commit
2f60b84be6

+ 46 - 0
src/typing/typerBase.ml

@@ -42,6 +42,50 @@ type object_decl_kind =
 	| ODKPlain
 	| ODKPlain
 	| ODKFailed
 	| ODKFailed
 
 
+module MetaConfig = struct
+
+	let as_bool e = match fst e with
+		| EConst (Ident "true") -> true
+		| EConst (Ident "false") -> false
+		| _ -> raise (Invalid_argument "bool")
+
+	let read_arg_config meta f l =
+		List.iter (fun (meta',el,_) ->
+			if meta' = meta then
+				List.iter (fun e -> match fst e with
+					| EConst (Ident s) ->
+						f (s,((EConst (Ident "true"),null_pos)))
+					| EBinop(OpAssign,(EConst (Ident s),_),e2) ->
+						f (s, e2)
+					| _ ->
+						()
+				) el
+		) l
+end
+
+module AbstractFromConfig = struct
+	type t = {
+		mutable ignored_by_inference : bool;
+	}
+
+	let make () = {
+		ignored_by_inference = false;
+	}
+
+	let update_config_from_meta config ml =
+		MetaConfig.read_arg_config Meta.From (fun (s,e) -> match s with
+			| "ignoredByInference" ->
+				begin try
+					config.ignored_by_inference <- MetaConfig.as_bool e
+				with Invalid_argument _ ->
+					()
+				end
+			| _ ->
+				()
+		) ml;
+		config
+end
+
 let type_call_target_ref : (typer -> expr -> expr list -> WithType.t -> pos option -> access_kind) ref = ref (fun _ _ _ _ -> die "" __LOC__)
 let type_call_target_ref : (typer -> expr -> expr list -> WithType.t -> pos option -> access_kind) ref = ref (fun _ _ _ _ -> die "" __LOC__)
 let type_access_ref : (typer -> expr_def -> pos -> access_mode -> WithType.t -> access_kind) ref = ref (fun _ _ _ _ _ -> assert false)
 let type_access_ref : (typer -> expr_def -> pos -> access_mode -> WithType.t -> access_kind) ref = ref (fun _ _ _ _ _ -> assert false)
 
 
@@ -284,6 +328,8 @@ let get_abstract_froms ctx a pl =
 		(* We never want to use the @:from we're currently in because that's recursive (see #10604) *)
 		(* We never want to use the @:from we're currently in because that's recursive (see #10604) *)
 		if f == ctx.curfield then
 		if f == ctx.curfield then
 			acc
 			acc
+		else if (AbstractFromConfig.update_config_from_meta (AbstractFromConfig.make ()) f.cf_meta).ignored_by_inference then
+			acc
 		else match follow (Type.field_type f) with
 		else match follow (Type.field_type f) with
 		| TFun ([_,_,v],t) ->
 		| TFun ([_,_,v],t) ->
 			(try
 			(try

+ 50 - 0
tests/misc/projects/Issue10739/Main.hx

@@ -0,0 +1,50 @@
+class Main {
+	static function main() {
+		getAnswer().next(v -> switch v {
+			case 42: 'Perfect!';
+			case 40, 41, 43, 44: 'Close enough!';
+			default: new NotError();
+		}).handle(o -> trace(Std.string(o)));
+	}
+
+	static function getAnswer():Promise<Int>
+		return 3 + 39;
+}
+
+class NotError {
+	public function new() {}
+}
+
+abstract Promise<T>((handler:(result:Outcome<T, NotError>) -> Void) -> Void) {
+	inline function new(f)
+		this = f;
+
+	public function next<X>(transform:Next<T, X>):Promise<X>
+		return new Promise(handler -> this(o -> switch o {
+			case Success(v): transform(v).handle(handler);
+			case Failure(e): handler(Failure(e));
+		}));
+
+	@:from static function ofOutcome<T>(o:Outcome<T, NotError>):Promise<T>
+		return new Promise<T>(h -> h(o));
+
+	@:from static function ofValue<T>(v:T):Promise<T>
+		return ofOutcome(Success(v));
+
+	@:from static function ofError<T>(e:NotError):Promise<T>
+		return ofOutcome(Failure(e));
+
+	public function handle(cb)
+		this(cb);
+}
+
+@:callable
+abstract Next<In, Out>(In->Promise<Out>) from In->Promise<Out> {
+	@:from(ignoredByInference) static function ofSync<In, Out>(f:In->Out):Next<In, Out>
+		return v -> (f(v) : Promise<Out>);
+}
+
+enum Outcome<T, E> {
+	Success(data:T);
+	Failure(error:E);
+}

+ 3 - 0
tests/misc/projects/Issue10739/compile.hxml

@@ -0,0 +1,3 @@
+-cp src
+-main Main
+--interp

+ 1 - 0
tests/misc/projects/Issue10739/compile.hxml.stdout

@@ -0,0 +1 @@
+Main.hx:7: Success(Perfect!)