Parcourir la source

[typer] eagerly check Void-ness of locals if we know the type

also clarify documentation on Context.typeExpr
closes #10626
Simon Krajewski il y a 3 ans
Parent
commit
4c5d3f9c45

+ 6 - 0
src/context/typecore.ml

@@ -403,6 +403,12 @@ let delay_late ctx p f =
 	in
 	ctx.g.delayed <- loop ctx.g.delayed
 
+let delay_if_mono ctx p t f = match follow t with
+	| TMono _ ->
+		delay ctx p f
+	| _ ->
+		f()
+
 let rec flush_pass ctx p (where:string) =
 	match ctx.g.delayed with
 	| (p2,l) :: rest when p2 <= p ->

+ 6 - 8
src/typing/typer.ml

@@ -637,14 +637,12 @@ and type_vars ctx vl p =
 				check_error ctx e p;
 				add_local ctx VGenerated n t_dynamic pv, None (* TODO: What to do with this... *)
 	) vl in
-	delay ctx PTypeField (fun() ->
-		List.iter
-			(fun (v,_) ->
-				if ExtType.is_void (follow v.v_type) then
-					typing_error "Variables of type Void are not allowed" v.v_pos
-			)
-			vl
-	);
+	List.iter (fun (v,_) ->
+		delay_if_mono ctx PTypeField v.v_type (fun() ->
+			if ExtType.is_void (follow v.v_type) then
+				typing_error "Variables of type Void are not allowed" v.v_pos
+		)
+	) vl;
 	match vl with
 	| [v,eo] ->
 		mk (TVar (v,eo)) ctx.t.tvoid p

+ 4 - 1
std/haxe/macro/Context.hx

@@ -416,7 +416,10 @@ class Context {
 		Types expression `e` and returns the corresponding `TypedExpr`.
 
 		Typing the expression may result in a compiler error which can be
-		caught using `try ... catch`.
+		caught using `try ... catch`. Note that not all compiler errors can
+		be caught this way because the compiler might delay various checks
+		to a later stage, at which point the exception handler is no longer
+		active.
 	**/
 	public static function typeExpr(e:Expr):TypedExpr {
 		return load("type_expr", 1)(e);

+ 17 - 0
tests/unit/src/unit/issues/Issue10626.hx

@@ -0,0 +1,17 @@
+package unit.issues;
+
+macro function foo() {
+	var s = try {
+		haxe.macro.Context.typeExpr(macro var x:Void);
+		"no exception";
+	} catch (e) {
+		"an exception";
+	}
+	return macro $v{s};
+}
+
+class Issue10626 extends unit.Test {
+	function test() {
+		eq("an exception", foo());
+	}
+}