浏览代码

follow through abstract underlying types for null-checks when matching

see #11715
Simon Krajewski 1 年之前
父节点
当前提交
1c1d967bab
共有 3 个文件被更改,包括 18 次插入3 次删除
  1. 2 2
      src/typing/matcher/compile.ml
  2. 15 0
      src/typing/matcher/matcherGlobals.ml
  3. 1 1
      src/typing/matcher/texprConverter.ml

+ 2 - 2
src/typing/matcher/compile.ml

@@ -270,7 +270,7 @@ and compile_switch mctx subjects cases =
 	let (subject_null,subject_switch,subject_default),reset_subject =
 		let subjects = match null with
 			| [] ->
-				if is_explicit_null subject.etype then
+				if is_explicit_null_or_abstract_over_that subject.etype then
 					switch_subject,subject,subject
 				else begin match switch_cases with
 				| [] ->
@@ -291,7 +291,7 @@ and compile_switch mctx subjects cases =
 	in
 	let dt = match null with
 		| [] ->
-			if is_explicit_null subject.etype then null_guard switch_default else dt
+			if is_explicit_null_or_abstract_over_that subject.etype then null_guard switch_default else dt
 		| cases ->
 			let dt_null = compile mctx subjects (cases @ default) in
 			null_guard dt_null

+ 15 - 0
src/typing/matcher/matcherGlobals.ml

@@ -7,3 +7,18 @@ let s_expr_pretty e = s_expr_pretty false "" false s_type e
 
 let make_offset_list left right middle other =
 	(ExtList.List.make left other) @ [middle] @ (ExtList.List.make right other)
+
+(* Like is_explicit_null, but follows abstract underlying types. *)
+let rec is_explicit_null_or_abstract_over_that = function
+	| TMono r ->
+		(match r.tm_type with None -> false | Some t -> is_explicit_null_or_abstract_over_that t)
+	| TAbstract ({ a_path = ([],"Null") },[t]) ->
+		true
+	| TAbstract(a,tl) when not (Meta.has Meta.CoreType a.a_meta) ->
+		is_explicit_null_or_abstract_over_that (Abstract.get_underlying_type a tl)
+	| TLazy f ->
+		is_explicit_null_or_abstract_over_that (lazy_type f)
+	| TType (t,tl) ->
+		is_explicit_null_or_abstract_over_that (apply_typedef t tl)
+	| _ ->
+		false

+ 1 - 1
src/typing/matcher/texprConverter.ml

@@ -274,7 +274,7 @@ let to_texpr ctx t_switch with_type dt =
 							| Some e -> Some {case_patterns = List.map (constructor_to_texpr ctx) (List.sort Constructor.compare cons);case_expr = e}
 						end
 					) cases in
-					let is_nullable_subject = is_explicit_null e_subject.etype in
+					let is_nullable_subject = is_explicit_null_or_abstract_over_that e_subject.etype in
 					let e_subject = match kind with
 						| SKValue -> e_subject
 						| SKEnum -> mk_index_call e_subject