[nullsafe][annotation graph] Introduce ProvisionallyNullable nullability

Summary:
In the previous diffs, we introduced
AnnotatedNullability.ProvisionallyNullable. This is a symmetric change
introducing the same for Nullability.t

Note how ProvisionallyNullable is made `is_nonnullish`. This means that
if we run nullsafe in --nullsafe-annotation-graph mode, the following
should start happening:

1/ A lot of new issues will be recorded - every time a local method or
non-null param is dereferenced etc.
2/ But all of those new issues will be filtered by corresponding Rules
(e.g. AssignmentRule). So those issues will not manifest to user-visible
errors. However, now we are capable to see and analyse those hidden
issues in ClassLevelAnalysis. This is exactly what we will be doing in
follow up diffs.

Note that the place of ProvisionallyNullable in the hierarchy is
somewhat arbitraily. It is important to make it less pri then Nullable -
but when it comes to comparing with other "nonnullish" modes - we can
tweak the behavior later on.

Reviewed By: artempyanykh

Differential Revision: D24621411

fbshipit-source-id: 3b99e5e55
master
Mitya Lyubarskiy 4 years ago committed by Facebook GitHub Bot
parent a673a13b44
commit 234aae3e60

@ -47,7 +47,7 @@ let get_nullability = function
| Nullable _ -> | Nullable _ ->
Nullability.Nullable Nullability.Nullable
| ProvisionallyNullable _ -> | ProvisionallyNullable _ ->
Nullability.Nullable Nullability.ProvisionallyNullable
| ThirdPartyNonnull -> | ThirdPartyNonnull ->
Nullability.ThirdPartyNonnull Nullability.ThirdPartyNonnull
| UncheckedNonnull _ -> | UncheckedNonnull _ ->

@ -138,6 +138,8 @@ module ReportableViolation = struct
in in
make_issue_factory ~description ~issue_type make_issue_factory ~description ~issue_type
|> NullsafeIssue.with_third_party_dependent_methods [(procname, annotated_signature)] |> NullsafeIssue.with_third_party_dependent_methods [(procname, annotated_signature)]
(* Equivalent to non-null from user point of view *)
| Nullability.ProvisionallyNullable
| Nullability.LocallyCheckedNonnull | Nullability.LocallyCheckedNonnull
| Nullability.LocallyTrustedNonnull | Nullability.LocallyTrustedNonnull
| Nullability.UncheckedNonnull | Nullability.UncheckedNonnull

@ -29,6 +29,8 @@ module UserFriendlyNullable = struct
| Nullability.LocallyTrustedNonnull -> | Nullability.LocallyTrustedNonnull ->
(* The value is trusted in the current mode by definition, hence is not treated as nullable. *) (* The value is trusted in the current mode by definition, hence is not treated as nullable. *)
None None
| Nullability.ProvisionallyNullable ->
(* from the user-facing point of view, this is a non-null *) None
| Nullability.StrictNonnull -> | Nullability.StrictNonnull ->
None None
end end

@ -15,6 +15,7 @@ type t =
| UncheckedNonnull | UncheckedNonnull
| LocallyTrustedNonnull | LocallyTrustedNonnull
| LocallyCheckedNonnull | LocallyCheckedNonnull
| ProvisionallyNullable
| StrictNonnull | StrictNonnull
[@@deriving compare, equal] [@@deriving compare, equal]
@ -32,6 +33,8 @@ let join x y =
Nullable Nullable
| ThirdPartyNonnull, _ | _, ThirdPartyNonnull -> | ThirdPartyNonnull, _ | _, ThirdPartyNonnull ->
ThirdPartyNonnull ThirdPartyNonnull
| ProvisionallyNullable, _ | _, ProvisionallyNullable ->
ProvisionallyNullable
| UncheckedNonnull, _ | _, UncheckedNonnull -> | UncheckedNonnull, _ | _, UncheckedNonnull ->
UncheckedNonnull UncheckedNonnull
| LocallyTrustedNonnull, _ | _, LocallyTrustedNonnull -> | LocallyTrustedNonnull, _ | _, LocallyTrustedNonnull ->
@ -45,6 +48,11 @@ let join x y =
let is_subtype ~subtype ~supertype = equal (join subtype supertype) supertype let is_subtype ~subtype ~supertype = equal (join subtype supertype) supertype
let is_considered_nonnull ~nullsafe_mode nullability = let is_considered_nonnull ~nullsafe_mode nullability =
if equal ProvisionallyNullable nullability then
(* Deliberately ignoring modes for this type
(ProvisionallyNullable is currently not indented to work well with all features for non-default modes) *)
true
else
let least_required = let least_required =
match nullsafe_mode with match nullsafe_mode with
| NullsafeMode.Strict -> | NullsafeMode.Strict ->
@ -73,6 +81,8 @@ let to_string = function
"Null" "Null"
| Nullable -> | Nullable ->
"Nullable" "Nullable"
| ProvisionallyNullable ->
"ProvisionallyNullable"
| ThirdPartyNonnull -> | ThirdPartyNonnull ->
"ThirdPartyNonnull" "ThirdPartyNonnull"
| UncheckedNonnull -> | UncheckedNonnull ->

@ -37,6 +37,10 @@ type t =
type-checks files against its dependencies but does not require the dependencies to be type-checks files against its dependencies but does not require the dependencies to be
transitively checked. Therefore this type of non-nullable value is differentiated from transitively checked. Therefore this type of non-nullable value is differentiated from
StrictNonnull. *) StrictNonnull. *)
| ProvisionallyNullable
(** Only for "annotation graph" mode. Indicates the value coming from a not annotated object
in the class under analysis. Since the object is not annotated, it should be treated as
non-null for all cases related to user-facing issue generation. *)
| StrictNonnull | StrictNonnull
(** Non-nullable value with the highest degree of certainty, because it is either: (** Non-nullable value with the highest degree of certainty, because it is either:

@ -65,7 +65,7 @@ let get_nullability = function
(* Annotated as Nullable explicitly or implicitly *) (* Annotated as Nullable explicitly or implicitly *)
Nullability.Nullable Nullability.Nullable
| AnnotatedNullability.ProvisionallyNullable _ -> | AnnotatedNullability.ProvisionallyNullable _ ->
Nullability.Nullable Nullability.ProvisionallyNullable
| AnnotatedNullability.UncheckedNonnull _ | AnnotatedNullability.UncheckedNonnull _
| AnnotatedNullability.ThirdPartyNonnull | AnnotatedNullability.ThirdPartyNonnull
| AnnotatedNullability.LocallyTrustedNonnull | AnnotatedNullability.LocallyTrustedNonnull

Loading…
Cancel
Save