Summary: In previous refactoring stages, we operated on AnnotatedNullability (nullability of a field or method signature together with its origin), and InferredNullability (nullability of a value in typestate together with its origin). Now it is time to extract common Nullability as a type system concept, together with `<:` and `join` functionality. This was sketched in `NullsafeRules`, so this diff consolidates this as well. In follow up diffs, we will reduce/get rid of direct usages of things like `InferredNullability.is_nullable`. This will simplify introducing intermediate Nullability types. Reviewed By: artempyanykh Differential Revision: D17789599 fbshipit-source-id: f1b9d2dd0master
parent
1228c8e31b
commit
62f6041906
@ -0,0 +1,24 @@
|
||||
(*
|
||||
* 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
|
||||
|
||||
type t =
|
||||
| Nullable (** No guarantees on the nullability *)
|
||||
| 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. *)
|
||||
[@@deriving compare, equal]
|
||||
|
||||
let join x y =
|
||||
match (x, y) with Nullable, _ | _, Nullable -> Nullable | Nonnull, Nonnull -> Nonnull
|
||||
|
||||
|
||||
let is_subtype ~subtype ~supertype = equal (join subtype supertype) supertype
|
||||
|
||||
let to_string = function Nullable -> "Nullable" | Nonnull -> "Nonnull"
|
@ -0,0 +1,35 @@
|
||||
(*
|
||||
* 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
|
||||
|
||||
(** Nullability is a central concept for Nullsafe type-checker.
|
||||
Informally, nullability is a "type" - set of values together with some additional context.
|
||||
All nullsafe is interested about if whether a value can be null, and if it can,
|
||||
what are potential causes of leaking the null inside it.
|
||||
Formally, nullability values form a lattice with partial order and upper bound operations.
|
||||
Practically, most of nullsafe core should remain agnostic over exact values of nullability
|
||||
(e.g. pattern-mathching over them should be a rare case. Core of typechecker should deal with subtyping and joins instead.)
|
||||
*)
|
||||
|
||||
type t =
|
||||
| Nullable (** No guarantees on the nullability *)
|
||||
| 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. *)
|
||||
[@@deriving compare, equal]
|
||||
|
||||
val is_subtype : subtype:t -> supertype:t -> bool
|
||||
(** A is a subtype of B, if all values of A can be represented in B.
|
||||
Subtype relation is reflexive: everything is a subtype of itself. *)
|
||||
|
||||
val join : t -> t -> t
|
||||
(** Unique upper bound over two types: the most precise type that is a supertype of both.
|
||||
Practically, joins occur e.g. when two branches of execution flow are getting merged. *)
|
||||
|
||||
val to_string : t -> string
|
Loading…
Reference in new issue