浏览代码

[matcher] show exhaustiveness errors even on empty switches

Also type empty switch as Void.
Simon Krajewski 6 年之前
父节点
当前提交
0927f0f6b7

+ 20 - 7
src/typing/matcher.ml

@@ -1167,11 +1167,17 @@ module Compile = struct
 				let ev = mk (TLocal v) e.etype e.epos in
 				(ev :: subjects,(v,e.epos,e) :: vars)
 		) ([],[]) subjects in
-		let dt = compile mctx subjects cases in
-		Useless.check mctx.ctx.com cases;
-		match vars with
-			| [] -> dt
-			| _ -> bind mctx vars dt
+		begin match cases,subjects with
+		| [],(subject :: _) ->
+			let dt_fail = fail mctx subject.epos in
+			switch mctx subject [] dt_fail
+		| _ ->
+			let dt = compile mctx subjects cases in
+			Useless.check mctx.ctx.com cases;
+			match vars with
+				| [] -> dt
+				| _ -> bind mctx vars dt
+		end
 end
 
 module TexprConverter = struct
@@ -1519,8 +1525,15 @@ module Match = struct
 			match with_type with
 				| WithType.NoValue -> ctx.t.tvoid
 				| WithType.Value(_) ->
-					let el = List.map (fun (case,_,_) -> match case.Case.case_expr with Some e -> e | None -> mk (TBlock []) ctx.t.tvoid p) cases in
-					unify_min ctx el
+					begin match cases with
+					| [] ->
+						(* If there are no cases we assume Void. This then causes a "Cannot use Void as value" error.
+						   Note that we cannot rely on an exhaustiveness error because the switch could be over an empty enum. *)
+						ctx.t.tvoid
+					| _ ->
+						let el = List.map (fun (case,_,_) -> match case.Case.case_expr with Some e -> e | None -> mk (TBlock []) ctx.t.tvoid p) cases in
+						unify_min ctx el
+					end
 				| WithType.WithType(t,_) -> t
 		in
 		if match_debug then begin

+ 8 - 0
tests/misc/projects/Issue3181/Main.hx

@@ -0,0 +1,8 @@
+private enum abstract A(Int) { }
+
+class Main {
+	static public function main() {
+		var a:Null<A> = cast 1;
+		var b = switch(a) { }
+	}
+}

+ 3 - 0
tests/misc/projects/Issue3181/compile-fail.hxml

@@ -0,0 +1,3 @@
+--main Main
+-neko neko.n
+--no-output

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

@@ -0,0 +1 @@
+Main.hx:6: characters 3-24 : Cannot use Void as value

+ 11 - 6
tests/unit/src/unit/issues/Issue3181.hx

@@ -3,10 +3,15 @@ package unit.issues;
 private enum abstract A(Int) { }
 
 class Issue3181 extends Test {
-	function test() {
-		var a:Null<A> = cast 1;
-		t(unit.HelperMacros.typeError(
-			switch(a) { }
-		));
-	}
+
+	/* Note: This no longer fails at block-level because it shouldn't. It does fail at
+	   in value places because we type the switch as Void in that case. However, we cannot
+	   test that here because this check is made at a later stage. */
+
+	// function test() {
+	// 	var a:Null<A> = cast 1;
+	// 	t(unit.HelperMacros.typeError(
+	// 		var b = switch(a) { }
+	// 	));
+	// }
 }