[nullsafe] Rename nullability variants

Summary:
Rename DeclaredNonnull -> UncheckedNonnull, Nonnull -> StrictNonnull.
This is a preparatory step to introduce one more nullability option,
specifically CheckedNonnull to support local nullsafe mode.

Reviewed By: ngorogiannis, mityal

Differential Revision: D19619289

fbshipit-source-id: 12a3ff814
master
Artem Pianykh 5 years ago committed by Facebook Github Bot
parent c0a990c47c
commit ea3cbae757

@ -56,12 +56,12 @@ let get tenv field_name class_typ =
in
let corrected_nullability =
match nullability with
| AnnotatedNullability.DeclaredNonnull _ when is_enum_value ->
| AnnotatedNullability.UncheckedNonnull _ when is_enum_value ->
(* Enum values are the special case - they can not be null. So we can strengten nullability.
Note that if it is nullable, we do NOT change nullability: in this case this is probably
not an enum value, but just a static field annotated as nullable.
*)
AnnotatedNullability.Nonnull EnumValue
AnnotatedNullability.StrictNonnull EnumValue
| _ ->
nullability
in

@ -16,8 +16,8 @@ module F = Format
type t =
| Nullable of nullable_origin
| DeclaredNonnull of declared_nonnull_origin (** See {!Nullability.t} for explanation *)
| Nonnull of nonnull_origin
| UncheckedNonnull of unchecked_nonnull_origin (** See {!Nullability.t} for explanation *)
| StrictNonnull of strict_nonnull_origin
[@@deriving compare]
and nullable_origin =
@ -31,7 +31,7 @@ and nullable_origin =
| ModelledNullable (** nullsafe knows it is nullable via its internal models *)
[@@deriving compare]
and declared_nonnull_origin =
and unchecked_nonnull_origin =
| AnnotatedNonnull
(** The type is explicitly annotated as non nullable via one of nonnull annotations Nullsafe
recognizes *)
@ -39,7 +39,7 @@ and declared_nonnull_origin =
(** Infer was run in mode where all not annotated (non local) types are treated as non
nullable *)
and nonnull_origin =
and strict_nonnull_origin =
| ModelledNonnull (** nullsafe knows it is non-nullable via its internal models *)
| StrictMode (** under strict mode we consider non-null declarations to be trusted *)
| PrimitiveType (** Primitive types are non-nullable by language design *)
@ -50,10 +50,10 @@ and nonnull_origin =
let get_nullability = function
| Nullable _ ->
Nullability.Nullable
| DeclaredNonnull _ ->
Nullability.DeclaredNonnull
| Nonnull _ ->
Nullability.Nonnull
| UncheckedNonnull _ ->
Nullability.UncheckedNonnull
| StrictNonnull _ ->
Nullability.StrictNonnull
let pp fmt t =
@ -85,21 +85,21 @@ let pp fmt t =
match t with
| Nullable origin ->
F.fprintf fmt "Nullable[%s]" (string_of_nullable_origin origin)
| DeclaredNonnull origin ->
F.fprintf fmt "DeclaredNonnull[%s]" (string_of_declared_nonnull_origin origin)
| Nonnull origin ->
F.fprintf fmt "Nonnull[%s]" (string_of_nonnull_origin origin)
| UncheckedNonnull origin ->
F.fprintf fmt "UncheckedNonnull[%s]" (string_of_declared_nonnull_origin origin)
| StrictNonnull origin ->
F.fprintf fmt "StrictNonnull[%s]" (string_of_nonnull_origin origin)
let of_type_and_annotation ~is_strict_mode typ annotations =
if not (PatternMatch.type_is_class typ) then Nonnull PrimitiveType
if not (PatternMatch.type_is_class typ) then StrictNonnull PrimitiveType
else if Annotations.ia_is_nullable annotations then
let nullable_origin =
if Annotations.ia_is_propagates_nullable annotations then AnnotatedPropagatesNullable
else AnnotatedNullable
in
Nullable nullable_origin
else if is_strict_mode then Nonnull StrictMode
else if Annotations.ia_is_nonnull annotations then DeclaredNonnull AnnotatedNonnull
else if is_strict_mode then StrictNonnull StrictMode
else if Annotations.ia_is_nonnull annotations then UncheckedNonnull AnnotatedNonnull
(* Currently, we treat not annotated types as nonnull *)
else DeclaredNonnull ImplicitlyNonnull
else UncheckedNonnull ImplicitlyNonnull

@ -18,8 +18,8 @@ open! IStd
type t =
| Nullable of nullable_origin
| DeclaredNonnull of declared_nonnull_origin (** See {!Nullability.t} for explanation *)
| Nonnull of nonnull_origin
| UncheckedNonnull of unchecked_nonnull_origin (** See {!Nullability.t} for explanation *)
| StrictNonnull of strict_nonnull_origin
[@@deriving compare]
and nullable_origin =
@ -33,7 +33,7 @@ and nullable_origin =
| ModelledNullable (** nullsafe knows it is nullable via its internal models *)
[@@deriving compare]
and declared_nonnull_origin =
and unchecked_nonnull_origin =
| AnnotatedNonnull
(** The type is explicitly annotated as non nullable via one of nonnull annotations Nullsafe
recognizes *)
@ -41,7 +41,7 @@ and declared_nonnull_origin =
(** Infer was run in mode where all not annotated (non local) types are treated as non
nullable *)
and nonnull_origin =
and strict_nonnull_origin =
| ModelledNonnull (** nullsafe knows it is non-nullable via its internal models *)
| StrictMode (** under strict mode we consider non-null declarations to be trusted *)
| PrimitiveType (** Primitive types are non-nullable by language design *)

@ -151,7 +151,7 @@ let mark_ia_nullability ia x = if x then mk_ia_nullable ia else ia
let set_modelled_nullability_for_annotated_type annotated_type should_set_nullable =
let nullability =
if should_set_nullable then AnnotatedNullability.Nullable ModelledNullable
else AnnotatedNullability.Nonnull ModelledNonnull
else AnnotatedNullability.StrictNonnull ModelledNonnull
in
AnnotatedType.{annotated_type with nullability}

@ -23,8 +23,8 @@ and function_info =
let is_whitelisted_assignment ~is_strict_mode ~lhs ~rhs =
match (is_strict_mode, lhs, rhs) with
| false, Nullability.Nonnull, Nullability.DeclaredNonnull ->
(* We allow DeclaredNonnull -> Nonnull conversion outside of strict mode for better adoption.
| false, Nullability.StrictNonnull, Nullability.UncheckedNonnull ->
(* We allow UncheckedNonnull -> StrictNonnull conversion outside of strict mode for better adoption.
Otherwise using strictified classes in non-strict context becomes a pain because
of extra warnings.
*)
@ -78,7 +78,7 @@ let bad_param_description
"`null`"
| Nullability.Nullable ->
"nullable"
| Nullability.Nonnull | Nullability.DeclaredNonnull ->
| Nullability.StrictNonnull | Nullability.UncheckedNonnull ->
Logging.die InternalError "Invariant violation: unexpected nullability"
in
Format.asprintf "%a is %s" MF.pp_monospaced actual_param_expression nullability_descr
@ -131,7 +131,11 @@ let bad_param_description
let is_declared_nonnull_to_nonnull ~lhs ~rhs =
match (lhs, rhs) with Nullability.Nonnull, Nullability.DeclaredNonnull -> true | _ -> false
match (lhs, rhs) with
| Nullability.StrictNonnull, Nullability.UncheckedNonnull ->
true
| _ ->
false
let get_issue_type = function
@ -171,7 +175,7 @@ let violation_description {is_strict_mode; lhs; rhs} ~assignment_location assign
"`null`"
| Nullable ->
"a nullable"
| Nonnull | DeclaredNonnull ->
| StrictNonnull | UncheckedNonnull ->
Logging.die InternalError "Invariant violation: unexpected nullability"
in
Format.asprintf "%a is declared non-nullable but is assigned %s%s." MF.pp_monospaced
@ -185,7 +189,7 @@ let violation_description {is_strict_mode; lhs; rhs} ~assignment_location assign
"`null`"
| Nullable ->
"a nullable value"
| Nonnull | DeclaredNonnull ->
| StrictNonnull | UncheckedNonnull ->
Logging.die InternalError "Invariant violation: unexpected nullability"
in
Format.asprintf "%a: return type is declared non-nullable but the method returns %s%s."

@ -19,9 +19,9 @@ let check ~is_strict_mode nullability =
match nullability with
| Nullability.Nullable | Nullability.Null ->
Error {is_strict_mode; nullability}
| Nullability.DeclaredNonnull ->
| Nullability.UncheckedNonnull ->
if is_strict_mode then Error {is_strict_mode; nullability} else Ok ()
| Nullability.Nonnull ->
| Nullability.StrictNonnull ->
Ok ()
@ -40,7 +40,7 @@ let violation_description {nullability} ~dereference_location dereference_type
~nullable_object_descr ~nullable_object_origin =
let module MF = MarkupFormatter in
match nullability with
| Nullability.DeclaredNonnull ->
| Nullability.UncheckedNonnull ->
(* This can happen only in strict mode.
This type of violation is more subtle than the normal case because, so it should be rendered in a special way *)
ErrorRenderingUtils.get_strict_mode_violation_issue ~bad_usage_location:dereference_location
@ -91,7 +91,7 @@ let violation_description {nullability} ~dereference_location dereference_type
| Nullability.Nullable ->
Format.sprintf "%s is nullable and is not locally checked for null when %s%s"
what_is_dereferred_str action_descr suffix
| Nullability.DeclaredNonnull | Nullability.Nonnull ->
| Nullability.UncheckedNonnull | Nullability.StrictNonnull ->
Logging.die InternalError "Invariant violation: unexpected nullability"
in
(description, IssueType.eradicate_nullable_dereference, dereference_location)

@ -15,7 +15,7 @@ val is_object_nullability_self_explanatory : object_expression:string -> TypeOri
val get_strict_mode_violation_issue :
bad_usage_location:Location.t -> TypeOrigin.t -> string * IssueType.t * Location.t
(** Situation when we tried to use DeclaredNonnull as Nonnull. This is disallowed only in strict
mode. Returns a tuple (error message, issue type, error location). NOTE: Location of the error
will be NOT in the place when the value is used (that is [bad_usage_location]), but where the
value is first obtained from. *)
(** Situation when we tried to use UncheckedNonnull as StrictNonnull. This is disallowed only in
strict mode. Returns a tuple (error message, issue type, error location). NOTE: Location of the
error will be NOT in the place when the value is used (that is [bad_usage_location]), but where
the value is first obtained from. *)

@ -14,7 +14,7 @@ let create origin = {nullability= TypeOrigin.get_nullability origin; origin}
let get_nullability {nullability} = nullability
let is_nonnull_or_declared_nonnull {nullability} =
match nullability with Nonnull | DeclaredNonnull -> true | _ -> false
match nullability with StrictNonnull | UncheckedNonnull -> true | _ -> false
let to_string {nullability} = Printf.sprintf "[%s]" (Nullability.to_string nullability)

@ -13,7 +13,7 @@ type type_role = Param | Ret
let is_whitelisted_violation ~subtype ~supertype =
match (subtype, supertype) with
| Nullability.DeclaredNonnull, Nullability.Nonnull ->
| Nullability.UncheckedNonnull, Nullability.StrictNonnull ->
(* It is a violation that we are currently willing to ignore because
it is hard to obey in practice.
It might lead to unsoundness issues, so this might be reconsidered.

@ -10,14 +10,21 @@ open! IStd
type t =
| Null (** The only possible value for that type is null *)
| Nullable (** No guarantees on the nullability *)
| DeclaredNonnull
| UncheckedNonnull
(** The type comes from a signature that is annotated (explicitly or implicitly according to
conventions) as non-nullable. Hovewer, it might still contain null since the truthfullness
conventions) as non-nullable. However, it might still contain null since the truthfulness
of the declaration was not checked. *)
| Nonnull
(** We believe that this value can not be null. If it is not the case, this is an unsoundness
issue for Nullsafe, and we aim to minimize number of such issues occuring in real-world
programs. *)
| StrictNonnull
(** Non-nullable value with the highest degree of certainty, because it is either:
- a non-null literal,
- an expression that semantically cannot be null,
- comes from internal code checked under strict mode,
- comes from a third-party method with an appropriate built-in model or user-defined
nullability signature.
The latter two are potential sources of unsoundness issues for nullsafe, but we need to
strike the balance between the strictness of analysis, convenience, and real-world risk. *)
[@@deriving compare, equal]
let top = Nullable
@ -30,10 +37,10 @@ let join x y =
Nullable
| Nullable, _ | _, Nullable ->
Nullable
| DeclaredNonnull, _ | _, DeclaredNonnull ->
DeclaredNonnull
| Nonnull, Nonnull ->
Nonnull
| UncheckedNonnull, _ | _, UncheckedNonnull ->
UncheckedNonnull
| StrictNonnull, StrictNonnull ->
StrictNonnull
let is_subtype ~subtype ~supertype = equal (join subtype supertype) supertype
@ -43,7 +50,7 @@ let to_string = function
"Null"
| Nullable ->
"Nullable"
| DeclaredNonnull ->
"DeclaredNonnull"
| Nonnull ->
"Nonnull"
| UncheckedNonnull ->
"UncheckedNonnull"
| StrictNonnull ->
"StrictNonnull"

@ -18,13 +18,15 @@ open! IStd
type t =
| Null (** The only possible value for that type is null *)
| Nullable (** No guarantees on the nullability *)
| DeclaredNonnull
| UncheckedNonnull
(** The type comes from a signature that is annotated (explicitly or implicitly according to
conventions) as non-nullable. Hovewer, it might still contain null since the truthfullness
of the declaration was not checked. *)
| Nonnull
(** We believe that this value can not be null. If it is not the case, this is an unsoundness
issue for Nullsafe, and we aim to minimize number of such issues occuring in real-world
| StrictNonnull
(** We believe that this value can not be null because it is either a non-null literal, an
expression that semantically cannot be null, or a non-null value that should not be null
according to typechecking rules. If the latter is not the case, this is an unsoundness
issue for nullsafe, and we aim to minimize number of such issues occuring in real-world
programs. *)
[@@deriving compare, equal]

@ -11,9 +11,10 @@ type violation = {declared_nullability: Nullability.t; can_be_narrowed_to: Nulla
let check ~what ~by_rhs_upper_bound =
match (what, by_rhs_upper_bound) with
| Nullability.Nullable, Nullability.Nonnull | Nullability.Nullable, Nullability.DeclaredNonnull ->
| Nullability.Nullable, Nullability.StrictNonnull
| Nullability.Nullable, Nullability.UncheckedNonnull ->
Error {declared_nullability= what; can_be_narrowed_to= by_rhs_upper_bound}
| Nullability.Null, Nullability.Nonnull | Nullability.Null, Nullability.DeclaredNonnull ->
| Nullability.Null, Nullability.StrictNonnull | Nullability.Null, Nullability.UncheckedNonnull ->
(* Null, Nonnull pais is an edge case that we don't expect to arise in practice for two reasons:
1. The only way to declare something as Null is to declare it is java.lang.Void, but nullsafe
does not know about it just yet.

@ -183,9 +183,9 @@ let is_declared_nonnull AnnotatedField.{annotated_type} =
match annotated_type.nullability with
| AnnotatedNullability.Nullable _ ->
false
| AnnotatedNullability.DeclaredNonnull _ ->
| AnnotatedNullability.UncheckedNonnull _ ->
true
| AnnotatedNullability.Nonnull _ ->
| AnnotatedNullability.StrictNonnull _ ->
true
@ -234,7 +234,7 @@ let get_nullability_upper_bound_for_typestate proc_name field_name typestate =
*)
let get_nullability_upper_bound field_name typestate_list =
(* Join upper bounds for all typestates in the list *)
List.fold typestate_list ~init:Nullability.Nonnull ~f:(fun acc (proc_name, typestate) ->
List.fold typestate_list ~init:Nullability.StrictNonnull ~f:(fun acc (proc_name, typestate) ->
Nullability.join acc
(get_nullability_upper_bound_for_typestate proc_name field_name typestate) )

@ -63,7 +63,7 @@ let get_nullability = function
| ArrayAccess
| OptimisticFallback (* non-null is the most optimistic type *)
| Undef (* This is a very special case, assigning non-null is a technical trick *) ->
Nullability.Nonnull
Nullability.StrictNonnull
| Field {field_type= {nullability}} ->
AnnotatedNullability.get_nullability nullability
| MethodParameter {param_annotated_type= {nullability}} ->
@ -116,7 +116,7 @@ let get_method_ret_description pname call_loc
match nullability with
| AnnotatedNullability.Nullable _ ->
"nullable"
| AnnotatedNullability.DeclaredNonnull _ | AnnotatedNullability.Nonnull _ ->
| AnnotatedNullability.UncheckedNonnull _ | AnnotatedNullability.StrictNonnull _ ->
"non-nullable"
in
let model_info =

Loading…
Cancel
Save