|
|
|
(*
|
|
|
|
* 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 top : t
|
|
|
|
(** The most generic type. *)
|
|
|
|
|
|
|
|
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 is_strict_subtype : subtype:t -> supertype:t -> bool
|
|
|
|
(** The same as subtype, but non-reflexive version. *)
|
|
|
|
|
|
|
|
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
|