Summary: This is a central abstraction for coming future unknown nullability support. # Context Annot.ml is a low-level module: - it contains lists of raw (string) annotations - no algebraic datatypes for annotations - it mixes annotations that Nullsafe should be aware of with all sorts of other annotations - some annotations make sense for return values, some make sense for params, and some make sense for methods. But, most importantly, it does not contain information about source of an annotation, making it hard to distinct things like "Nonnull as default" vs "Nonnull as explicitly annotated" vs "Nonnull as modelled". Ditto for nullable. Because of this, it is tricky to introduce unknown nullability in an elegant way. Let's get rid of using Annot.Item.t in nullsafe code in the following way: - Move nullability information associated with the Java type to a dedicated algebraic DT. - Split other annotations that are important for nullsafe into param flags, ret value flags, and method flags, and introduce corresponding datatypes. # This diff This diff introduces NullsafeType and adds this to AnnotatedSignature. It is not used yet, hence the diff is a no-op. In future diffs, we are going to (see also TODOs in the code): - actually use this information instead of accessing Annot.item - add more information to AnnotatedSignature - remove Annot.item from AnnnotatedSignature - when this is done, introduce notion of unknown nullability. Reviewed By: ngorogiannis Differential Revision: D17420595 fbshipit-source-id: b30706d9bmaster
parent
4ff2700bde
commit
633186c41e
@ -0,0 +1,81 @@
|
||||
(*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*)
|
||||
|
||||
open! IStd
|
||||
module F = Format
|
||||
|
||||
(** Representation of a (non local) type in Java program, with added information about its nullability,
|
||||
according to the source code.
|
||||
Nullability information might come either from explicit annotations, or from other sources,
|
||||
including conventions about defaults.
|
||||
Note that nullsafe omits Nullability information in types used for local variable declarations:
|
||||
this information is inferred according to flow-sensitive inferrence rule.
|
||||
*)
|
||||
|
||||
(* TODO(T52947663) add notion of unknown nullability *)
|
||||
type nullability = Nullable of nullable_origin | Nonnull of nonnull_origin [@@deriving compare]
|
||||
|
||||
and nullable_origin =
|
||||
| AnnotatedNullable (** The type is expicitly annotated with @Nullable in the code *)
|
||||
| AnnotatedPropagatesNullable
|
||||
(** If a function param is annotated as @PropagatesNullable, this param is automatically nullable *)
|
||||
| HasPropagatesNullableInParam
|
||||
(** If a method has at least one param marked as @PropagatesNullable, return value is automatically nullable *)
|
||||
| ModelledNullable (** nullsafe knows it is nullable via its internal models *)
|
||||
[@@deriving compare]
|
||||
|
||||
and nonnull_origin =
|
||||
| AnnotatedNonnull
|
||||
(** The type is explicitly annotated as non nullable via one of nonnull annotations Nullsafe recognizes *)
|
||||
| NotAnnotatedHenceNullableMode
|
||||
(** Infer was run in mode where all not annotated (non local) types are treated as non nullable *)
|
||||
| ModelledNonnull (** nullsafe knows it is non-nullable via its internal models *)
|
||||
[@@deriving compare]
|
||||
|
||||
type t = {nullability: nullability; typ: Typ.t} [@@deriving compare]
|
||||
|
||||
let pp fmt {nullability; typ} =
|
||||
let string_of_nullable_origin nullable_origin =
|
||||
match nullable_origin with
|
||||
| AnnotatedNullable ->
|
||||
"@"
|
||||
| AnnotatedPropagatesNullable ->
|
||||
"propagates"
|
||||
| HasPropagatesNullableInParam ->
|
||||
"<-propagates"
|
||||
| ModelledNullable ->
|
||||
"model"
|
||||
in
|
||||
let string_of_nonnull_origin nonnull_origin =
|
||||
match nonnull_origin with
|
||||
| AnnotatedNonnull ->
|
||||
"@"
|
||||
| NotAnnotatedHenceNullableMode ->
|
||||
"default"
|
||||
| ModelledNonnull ->
|
||||
"model"
|
||||
in
|
||||
let pp_nullability fmt nullability =
|
||||
match nullability with
|
||||
| Nullable nullable_origin ->
|
||||
F.fprintf fmt "Nullable[%s]" (string_of_nullable_origin nullable_origin)
|
||||
| Nonnull nonnull_origin ->
|
||||
F.fprintf fmt "Nonnull[%s]" (string_of_nonnull_origin nonnull_origin)
|
||||
in
|
||||
F.fprintf fmt "%a %a" pp_nullability nullability (Typ.pp_full Pp.text) typ
|
||||
|
||||
|
||||
let nullability_of_annot_item ia =
|
||||
if Annotations.ia_is_nullable ia then
|
||||
let nullable_origin =
|
||||
if Annotations.ia_is_propagates_nullable ia then AnnotatedPropagatesNullable
|
||||
else AnnotatedNullable
|
||||
in
|
||||
Nullable nullable_origin
|
||||
else if Annotations.ia_is_nonnull ia then Nonnull AnnotatedNonnull
|
||||
(* Currently, we treat not annotated types as nonnull *)
|
||||
else Nonnull NotAnnotatedHenceNullableMode
|
@ -0,0 +1,42 @@
|
||||
(*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*)
|
||||
|
||||
open! IStd
|
||||
|
||||
(** Representation of a type in Java program, but with added information about its nullability.
|
||||
Nullability information might come either from explicit annotations, or from other sources,
|
||||
including conventions about defaults.
|
||||
*)
|
||||
|
||||
type nullability = Nullable of nullable_origin | Nonnull of nonnull_origin [@@deriving compare]
|
||||
|
||||
and nullable_origin =
|
||||
| AnnotatedNullable (** The type is expicitly annotated with @Nullable in the code *)
|
||||
| AnnotatedPropagatesNullable
|
||||
(** If a function param is annotated as @PropagatesNullable, this param is automatically nullable *)
|
||||
| HasPropagatesNullableInParam
|
||||
(** If a method has at least one param marked as @PropagatesNullable, return value is automatically nullable *)
|
||||
| ModelledNullable (** nullsafe knows it is nullable via its internal models *)
|
||||
[@@deriving compare]
|
||||
|
||||
and nonnull_origin =
|
||||
| AnnotatedNonnull
|
||||
(** The type is explicitly annotated as non nullable via one of nonnull annotations Nullsafe recognizes *)
|
||||
| NotAnnotatedHenceNullableMode
|
||||
(** Infer was run in mode where all not annotated (non local) types are treated as non nullable *)
|
||||
| ModelledNonnull (** nullsafe knows it is non-nullable via its internal models *)
|
||||
[@@deriving compare]
|
||||
|
||||
type t = {nullability: nullability; typ: Typ.t} [@@deriving compare]
|
||||
|
||||
val pp : Format.formatter -> t -> unit
|
||||
|
||||
val nullability_of_annot_item : Annot.Item.t -> nullability
|
||||
(** Converts the information from the annotation to nullability.
|
||||
NOTE: it does not take into account models etc., so this is intended to be used
|
||||
as a helper function for more high-level annotation processing.
|
||||
*)
|
Loading…
Reference in new issue