Browse Source

[typer] redesign AKNo some more

closes #10845
Simon Krajewski 2 years ago
parent
commit
b9f2a6c6b6

+ 3 - 3
src/typing/calls.ml

@@ -190,7 +190,7 @@ let rec acc_get ctx g p =
 	in
 	let dispatcher () = new call_dispatcher ctx MGet WithType.value p in
 	match g with
-	| AKNo(name,p) -> typing_error (name ^ " cannot be accessed for reading") p
+	| AKNo(_,p) -> typing_error ("This expression cannot be accessed for reading") p
 	| AKExpr e -> e
 	| AKSafeNav sn ->
 		(* generate null-check branching for the safe navigation chain *)
@@ -302,8 +302,8 @@ let rec build_call_access ctx acc el mode with_type p =
 		AKExpr e
 	| AKResolve(sea,name) ->
 		AKExpr (dispatch#expr_call (dispatch#resolve_call sea name) [] el)
-	| AKNo(s,p) ->
-		typing_error (s ^ " cannot be called") p
+	| AKNo(_,p) ->
+		typing_error "This expression cannot be called" p
 	| AKAccess _ ->
 		typing_error "This expression cannot be called" p
 	| AKAccessor fa ->

+ 7 - 4
src/typing/fields.ml

@@ -187,6 +187,9 @@ let field_access ctx mode f fh e pfield =
 		let normal inline =
 			AKField (make_access inline)
 		in
+		let normal_failure ()=
+			AKNo((normal false),pfield)
+		in
 		match (match mode with MGet | MCall _ -> v.v_read | MSet _ -> v.v_write) with
 		| AccNo when not (Meta.has Meta.PrivateAccess ctx.meta) ->
 			(match follow e.etype with
@@ -195,9 +198,9 @@ let field_access ctx mode f fh e pfield =
 			| TAnon a ->
 				(match !(a.a_status) with
 				| Statics c2 when ctx.curclass == c2 || can_access ctx c2 { f with cf_flags = unset_flag f.cf_flags (int_of_class_field_flag CfPublic) } true -> normal false
-				| _ -> if ctx.untyped then normal false else AKNo(f.cf_name, pfield))
+				| _ -> if ctx.untyped then normal false else normal_failure())
 			| _ ->
-				if ctx.untyped then normal false else AKNo(f.cf_name,pfield))
+				if ctx.untyped then normal false else normal_failure())
 		| AccNormal | AccNo ->
 			normal false
 		| AccCall when (not ctx.allow_transform) || (ctx.in_display && DisplayPosition.display_position#enclosed_in pfull) ->
@@ -233,7 +236,7 @@ let field_access ctx mode f fh e pfield =
 				AKAccessor (make_access false)
 			end
 		| AccNever ->
-			if ctx.untyped then normal false else AKNo(f.cf_name,pfield)
+			if ctx.untyped then normal false else normal_failure()
 		| AccInline ->
 			normal true
 		| AccCtor ->
@@ -242,7 +245,7 @@ let field_access ctx mode f fh e pfield =
 			in
 			(match ctx.curfun, fh with
 				| FunConstructor, FHInstance(c,_) when c == ctx.curclass || is_child_of_abstract c -> normal false
-				| _ -> AKNo(f.cf_name,pfield)
+				| _ -> normal_failure()
 			)
 		| AccRequire (r,msg) ->
 			match msg with

+ 19 - 8
src/typing/operators.ml

@@ -76,6 +76,10 @@ module BinopResult = struct
 	let get_type br = match br with
 		| BinopNormal bn -> bn.binop_type
 		| BinopSpecial(e,_) -> e.etype
+
+	let needs_assign = function
+		| BinopNormal _ -> true
+		| BinopSpecial(_,needs_assign) -> needs_assign
 end
 
 let check_assign ctx e =
@@ -556,7 +560,8 @@ let type_assign ctx e1 e2 with_type p =
 		mk (TBinop (OpAssign,e1,e2)) e1.etype p
 	in
 	match e1 with
-	| AKNo(s,p) -> typing_error ("Cannot access " ^ s ^ " for writing") p
+	| AKNo(_,p) ->
+		typing_error "This expression cannot be accessed for writing" p
 	| AKUsingField _ | AKSafeNav _ ->
 		typing_error "Invalid operation" p
 	| AKExpr { eexpr = TLocal { v_kind = VUser TVOLocalFunction; v_name = name } } ->
@@ -627,7 +632,7 @@ let type_assign_op ctx op e1 e2 with_type p =
 		field_rhs_by_name op cf.cf_name ev (WithType.with_type cf.cf_type)
 	in
 	let assign vr e r_rhs =
-		check_assign ctx e;
+		if BinopResult.needs_assign r_rhs then check_assign ctx e;
 		let assign e_rhs =
 			let e_rhs = AbstractCast.cast_or_unify ctx e.etype e_rhs p in
 			match e_rhs.eexpr with
@@ -649,11 +654,13 @@ let type_assign_op ctx op e1 e2 with_type p =
 		vr#to_texpr e
 	in
 	(match !type_access_ref ctx (fst e1) (snd e1) (MSet (Some e2)) with_type with
-	| AKNo(s,p) ->
+	| AKNo(_,p) ->
 		(* try abstract operator overloading *)
-		(try type_non_assign_op ctx op e1 e2 true true with_type p
-		with Not_found -> typing_error ("Cannot access " ^ s ^ " for writing") p
-		)
+		begin try
+			type_non_assign_op ctx op e1 e2 true true with_type p
+		with Not_found ->
+			typing_error "This expression cannot be accessed for writing" p
+		end
 	| AKUsingField _ | AKSafeNav _ ->
 		typing_error "Invalid operation" p
 	| AKExpr e ->
@@ -839,8 +846,12 @@ let type_unop ctx op flag e with_type p =
 		in
 		let access_set = !type_access_ref ctx (fst e) (snd e) (MSet None) WithType.value (* WITHTYPETODO *) in
 		match access_set with
-		| AKNo(s,p) ->
-			typing_error ("Cannot access " ^ s ^ " for writing") p
+		| AKNo(acc,p) ->
+			begin try
+				try_abstract_unop_overloads (acc_get ctx acc p)
+			with Not_found ->
+				typing_error "This expression cannot be accessed for writing" p
+			end
 		| AKExpr e ->
 			find_overload_or_make e
 		| AKField fa ->

+ 36 - 18
src/typing/typer.ml

@@ -269,24 +269,40 @@ let rec type_ident_raise ctx i p mode with_type =
 	let is_set = match mode with MSet _ -> true | _ -> false in
 	match i with
 	| "true" ->
+		let acc = AKExpr (mk (TConst (TBool true)) ctx.t.tbool p) in
 		if mode = MGet then
-			AKExpr (mk (TConst (TBool true)) ctx.t.tbool p)
+			acc
 		else
-			AKNo(i,p)
+			AKNo(acc,p)
 	| "false" ->
+		let acc = AKExpr (mk (TConst (TBool false)) ctx.t.tbool p) in
 		if mode = MGet then
-			AKExpr (mk (TConst (TBool false)) ctx.t.tbool p)
+			acc
 		else
-			AKNo(i,p)
+			AKNo(acc,p)
 	| "this" ->
-		if is_set then add_class_field_flag ctx.curfield CfModifiesThis;
-		(match mode, ctx.curclass.cl_kind with
-		| MSet _, KAbstractImpl _ ->
-			if not (assign_to_this_is_allowed ctx) then
-				typing_error "Abstract 'this' value can only be modified inside an inline function" p;
-			AKExpr (get_this ctx p)
-		| (MCall _, KAbstractImpl _) | (MGet, _)-> AKExpr(get_this ctx p)
-		| _ -> AKNo(i,p))
+		let acc = AKExpr(get_this ctx p) in
+		begin match mode with
+		| MSet _ ->
+			add_class_field_flag ctx.curfield CfModifiesThis;
+			begin match ctx.curclass.cl_kind with
+			| KAbstractImpl _ ->
+				if not (assign_to_this_is_allowed ctx) then
+					typing_error "Abstract 'this' value can only be modified inside an inline function" p;
+				acc
+			| _ ->
+				AKNo(acc,p)
+			end
+		| MCall _ ->
+			begin match ctx.curclass.cl_kind with
+			| KAbstractImpl _ ->
+				acc
+			| _ ->
+				AKNo(acc,p)
+			end
+		| MGet ->
+			acc
+		end;
 	| "abstract" ->
 		begin match mode, ctx.curclass.cl_kind with
 			| MSet _, KAbstractImpl ab -> typing_error "Property 'abstract' is read-only" p;
@@ -311,7 +327,7 @@ let rec type_ident_raise ctx i p mode with_type =
 		| FunMemberClassLocal | FunMemberAbstractLocal -> typing_error "Cannot access super inside a local function" p);
 		AKExpr (mk (TConst TSuper) t p)
 	| "null" ->
-		if mode = MGet then begin
+		let acc =
 			(* Hack for #10787 *)
 			if ctx.com.platform = Cs then
 				AKExpr (null (spawn_monomorph ctx p) p)
@@ -334,8 +350,8 @@ let rec type_ident_raise ctx i p mode with_type =
 				in
 				AKExpr (null t p)
 			end
-		end else
-			AKNo(i,p)
+		in
+		if mode = MGet then acc else AKNo(acc,p)
 	| _ ->
 	try
 		let v = PMap.find i ctx.locals in
@@ -394,10 +410,12 @@ let rec type_ident_raise ctx i p mode with_type =
 			field_access ctx mode f (FHStatic c) e p
 		)
 	with Not_found -> try
-		let wrap e = if is_set then
-				AKNo(i,p)
+		let wrap e =
+			let acc = AKExpr e in
+			if is_set then
+				AKNo(acc,p)
 			else
-				AKExpr e
+				acc
 		in
 		(* lookup imported enums *)
 		let rec loop l =

+ 2 - 2
src/typing/typerBase.ml

@@ -6,7 +6,7 @@ open Error
 
 type access_kind =
 	(* Access is not possible or allowed. *)
-	| AKNo of placed_name
+	| AKNo of access_kind * pos
 	(* Access on arbitrary expression. *)
 	| AKExpr of texpr
 	(* Safe navigation access chain *)
@@ -209,7 +209,7 @@ let rec s_access_kind acc =
 	let st = s_type (print_context()) in
 	let se = s_expr_pretty true "" false st in
 	match acc with
-	| AKNo(s,_) -> "AKNo " ^ s
+	| AKNo(acc,_) -> "AKNo " ^ (s_access_kind acc)
 	| AKExpr e -> "AKExpr " ^ (se e)
 	| AKSafeNav sn -> Printf.sprintf  "AKSafeNav(%s)" (s_safe_nav_access sn)
 	| AKField fa -> Printf.sprintf "AKField(%s)" (s_field_access "" fa)

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

@@ -1 +1 @@
-Main.hx:20: characters 10-18 : Cannot access position for writing
+Main.hx:20: characters 10-18 : This expression cannot be accessed for writing

+ 3 - 3
tests/misc/projects/Issue10845/compile-fail.hxml.stderr

@@ -1,10 +1,10 @@
-Main.hx:21: characters 3-8 : Cannot access field for writing
+Main.hx:21: characters 3-10 : Cannot modify abstract value of final field
 Main.hx:22: characters 3-10 : Cannot modify abstract value of final local
 Main.hx:24: characters 3-8 : Cannot modify abstract value of final field
 Main.hx:25: characters 3-13 : Cannot modify abstract value of final local
-Main.hx:29: characters 3-8 : Cannot access field for writing
+Main.hx:29: characters 3-8 : This expression cannot be accessed for writing
 Main.hx:30: characters 3-8 : Cannot assign to final
-Main.hx:32: characters 3-8 : Cannot access field for writing
+Main.hx:32: characters 3-8 : This expression cannot be accessed for writing
 Main.hx:33: characters 3-8 : Cannot assign to final
 Main.hx:37: characters 3-17 : Cannot modify abstract value of final field
 Main.hx:38: characters 3-17 : Cannot modify abstract value of final local

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

@@ -1,2 +1,2 @@
-Main.hx:3: characters 9-13 : null cannot be called
+Main.hx:3: characters 9-13 : This expression cannot be called
 Main.hx:3: characters 9-13 : ... For function argument 'v'

+ 1 - 1
tests/misc/projects/Issue6584/compile2-fail.hxml.stderr

@@ -1 +1 @@
-Main2.hx:5: characters 3-4 : Cannot access v for writing
+Main2.hx:5: characters 3-4 : This expression cannot be accessed for writing

+ 1 - 1
tests/misc/projects/Issue6584/compile3-fail.hxml.stderr

@@ -1 +1 @@
-Main3.hx:9: characters 3-4 : Cannot access v for writing
+Main3.hx:9: characters 3-4 : This expression cannot be accessed for writing

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

@@ -1 +1 @@
-Main.hx:10: characters 11-12 : Cannot access x for writing
+Main.hx:10: characters 11-12 : This expression cannot be accessed for writing

+ 47 - 0
tests/unit/src/unit/issues/Issue10845.hx

@@ -0,0 +1,47 @@
+package unit.issues;
+
+import utest.Assert;
+
+private var count = 0;
+
+private abstract MyInt(Int) from Int to Int {
+	@:op(A += B)
+	public inline function addEq(x:Int):MyInt {
+		count++;
+		return this;
+	}
+
+	@:op(A++)
+	public inline function increment():MyInt {
+		count++;
+		return this;
+	}
+}
+
+class Issue10845 extends Test {
+	final field:MyInt = 1;
+
+	function test():Void {
+		final local:MyInt = 1;
+
+		field++;
+		eq(1, count);
+		local++;
+		eq(2, count);
+
+		field += 1;
+		eq(3, count);
+		local += 1;
+		eq(4, count);
+
+		field.addEq(1);
+		eq(5, count);
+		local.addEq(1);
+		eq(6, count);
+
+		field.increment();
+		eq(7, count);
+		local.increment();
+		eq(8, count);
+	}
+}