Browse Source

[nullsafety] allow `@:nullSafety(Off) this` at any time in constructor (closes #8132)

Alexander Kuzmenko 6 years ago
parent
commit
4ee84e256d
2 changed files with 11 additions and 6 deletions
  1. 10 6
      src/typing/nullSafety.ml
  2. 1 0
      tests/nullsafety/src/cases/TestStrict.hx

+ 10 - 6
src/typing/nullSafety.ml

@@ -1417,7 +1417,7 @@ class class_checker cls immediate_execution report  =
 							| None -> Hashtbl.add fields_to_initialize f.cf_name f
 							| None -> Hashtbl.add fields_to_initialize f.cf_name f
 				)
 				)
 				cls.cl_ordered_fields;
 				cls.cl_ordered_fields;
-			let rec check_unsafe_usage init_list e =
+			let rec check_unsafe_usage init_list safety_enabled e =
 				if Hashtbl.length init_list > 0 then
 				if Hashtbl.length init_list > 0 then
 					match e.eexpr with
 					match e.eexpr with
 						| TField ({ eexpr = TConst TThis }, FInstance (_, _, field)) ->
 						| TField ({ eexpr = TConst TThis }, FInstance (_, _, field)) ->
@@ -1427,13 +1427,17 @@ class class_checker cls immediate_execution report  =
 							checker#error ("Cannot use method " ^ field.cf_name ^ " until all instance fields are initialized.") [e.epos];
 							checker#error ("Cannot use method " ^ field.cf_name ^ " until all instance fields are initialized.") [e.epos];
 						| TCall ({ eexpr = TField ({ eexpr = TConst TThis }, FInstance (_, _, field)) }, args) ->
 						| TCall ({ eexpr = TField ({ eexpr = TConst TThis }, FInstance (_, _, field)) }, args) ->
 							checker#error ("Cannot call method " ^ field.cf_name ^ " until all instance fields are initialized.") [e.epos];
 							checker#error ("Cannot call method " ^ field.cf_name ^ " until all instance fields are initialized.") [e.epos];
-							List.iter (check_unsafe_usage init_list) args
-						| TConst TThis ->
+							List.iter (check_unsafe_usage init_list safety_enabled) args
+						| TConst TThis when safety_enabled ->
 							checker#error "Cannot use \"this\" until all instance fields are initialized." [e.epos]
 							checker#error "Cannot use \"this\" until all instance fields are initialized." [e.epos]
 						| TLocal v when Hashtbl.mem this_vars v.v_id ->
 						| TLocal v when Hashtbl.mem this_vars v.v_id ->
 							checker#error "Cannot use \"this\" until all instance fields are initialized." [e.epos]
 							checker#error "Cannot use \"this\" until all instance fields are initialized." [e.epos]
+						| TMeta ((Meta.NullSafety, [(EConst (Ident "Off"), _)], _), e) ->
+							iter (check_unsafe_usage init_list false) e
+						| TMeta ((Meta.NullSafety, _, _), e) ->
+							iter (check_unsafe_usage init_list true) e
 						| _ ->
 						| _ ->
-							iter (check_unsafe_usage init_list) e
+							iter (check_unsafe_usage init_list safety_enabled) e
 			in
 			in
 			let rec traverse init_list e =
 			let rec traverse init_list e =
 				(match e.eexpr with
 				(match e.eexpr with
@@ -1441,7 +1445,7 @@ class class_checker cls immediate_execution report  =
 						Hashtbl.remove init_list f.cf_name;
 						Hashtbl.remove init_list f.cf_name;
 						ignore (traverse init_list right_expr)
 						ignore (traverse init_list right_expr)
 					| TWhile (condition, body, DoWhile) ->
 					| TWhile (condition, body, DoWhile) ->
-						check_unsafe_usage init_list condition;
+						check_unsafe_usage init_list true condition;
 						ignore (traverse init_list body)
 						ignore (traverse init_list body)
 					| TBlock exprs ->
 					| TBlock exprs ->
 						List.iter (fun e -> ignore (traverse init_list e)) exprs
 						List.iter (fun e -> ignore (traverse init_list e)) exprs
@@ -1455,7 +1459,7 @@ class class_checker cls immediate_execution report  =
 					| TVar (v, Some { eexpr = TConst TThis }) ->
 					| TVar (v, Some { eexpr = TConst TThis }) ->
 						Hashtbl.add this_vars v.v_id v
 						Hashtbl.add this_vars v.v_id v
 					| _ ->
 					| _ ->
-						check_unsafe_usage init_list e
+						check_unsafe_usage init_list true e
 				);
 				);
 				init_list
 				init_list
 			in
 			in

+ 1 - 0
tests/nullsafety/src/cases/TestStrict.hx

@@ -146,6 +146,7 @@ class TestStrict {
 			initializedInAllBranchesOfConstructor = 'hello';
 			initializedInAllBranchesOfConstructor = 'hello';
 		}
 		}
 		shouldFail(acceptThis(this));
 		shouldFail(acceptThis(this));
+		@:nullSafety(Off) acceptThis(this);
 		var self = this;
 		var self = this;
 		shouldFail(acceptThis(self));
 		shouldFail(acceptThis(self));
 		shouldFail(instanceMethod());
 		shouldFail(instanceMethod());