Ver Fonte

Type array access on Array<T> as Null<T> (#6825)

* type array access on Array<T> as Null<T>

* only add Null<> to array reading

* fix OOM for compilation without specifying a target

* fixed signature of haxe.io.BufferInput.readByte()

* minor refactoring

* handle @:notNullable meta

* minor
Alexander Kuzmenko há 7 anos atrás
pai
commit
9afd1a688e
3 ficheiros alterados com 24 adições e 3 exclusões
  1. 12 0
      src/core/type.ml
  2. 11 2
      src/typing/typer.ml
  3. 1 1
      std/haxe/io/BufferInput.hx

+ 12 - 0
src/core/type.ml

@@ -1641,6 +1641,18 @@ let has_meta m ml = List.exists (fun (m2,_,_) -> m = m2) ml
 let get_meta m ml = List.find (fun (m2,_,_) -> m = m2) ml
 let no_meta = []
 
+(**
+	Check if type `t` has meta `m`.
+	Does not follow typedefs, monomorphs etc.
+*)
+let type_has_meta t m =
+	match t with
+		| TMono _ | TFun _ | TAnon _ | TDynamic _ | TLazy _ -> false
+		| TEnum ({ e_meta = metadata }, _)
+		| TInst ({ cl_meta = metadata }, _)
+		| TType ({ t_meta = metadata }, _)
+		| TAbstract ({ a_meta = metadata }, _) -> has_meta m metadata
+
 (*
 	we can restrict access as soon as both are runtime-compatible
 *)

+ 11 - 2
src/typing/typer.ml

@@ -2586,6 +2586,15 @@ and type_access ctx e p mode =
 	| _ ->
 		AKExpr (type_expr ctx (e,p) Value)
 
+and should_be_nullable_array_access ctx array_type access_mode =
+	if access_mode = MSet then
+		false
+	else
+		match array_type with
+		| TInst ({ cl_path = [],"Array"},[t]) ->
+			not ((Common.defined ctx.com Define.Static) && (type_has_meta (Abstract.follow_with_abstracts t) Meta.NotNull))
+		| _ -> false
+
 and type_array_access ctx e1 e2 p mode =
 	let e1 = type_expr ctx e1 Value in
 	let e2 = type_expr ctx e2 Value in
@@ -2617,8 +2626,8 @@ and type_array_access ctx e1 e2 p mode =
 				t_dynamic
 			| TAbstract(a,tl) when Meta.has Meta.ArrayAccess a.a_meta ->
 				loop (apply_params a.a_params tl a.a_this)
-			| _ ->
-				let pt = mk_mono() in
+			| t ->
+				let pt = if should_be_nullable_array_access ctx t mode then ctx.t.tnull (mk_mono()) else mk_mono() in
 				let t = ctx.t.tarray pt in
 				(try unify_raise ctx et t p
 				with Error(Unify _,_) -> if not ctx.untyped then begin

+ 1 - 1
std/haxe/io/BufferInput.hx

@@ -43,7 +43,7 @@ class BufferInput extends haxe.io.Input {
 		available += i.readBytes(buf, available, buf.length - available);
 	}
 
-	override function readByte() {
+	override function readByte():Int {
 		if( available == 0 ) refill();
 		var c = buf.get(pos);
 		pos++;