[nullsafe] Introduce NullsafeMode as a replacement for `is_strict_mode`

Summary:
Refactor all occurences of `is_strict_mode` to use `NullsafeMode`
instead. This will allow introducing _local_ typechecking modes for
nullsafe in the follow up patches.

Reviewed By: ezgicicek

Differential Revision: D19639883

fbshipit-source-id: bdf535b66
master
Artem Pianykh 5 years ago committed by Facebook Github Bot
parent 355ff5c202
commit c735b6f0a5

@ -120,10 +120,14 @@ let type_get_direct_supertypes tenv (typ : Typ.t) =
let type_get_class_name {Typ.desc} = match desc with Typ.Tptr (typ, _) -> Typ.name typ | _ -> None let type_get_class_name {Typ.desc} = match desc with Typ.Tptr (typ, _) -> Typ.name typ | _ -> None
let type_name_get_annotation tenv (name : Typ.name) : Annot.Item.t option =
match Tenv.lookup tenv name with Some {annots} -> Some annots | None -> None
let type_get_annotation tenv (typ : Typ.t) : Annot.Item.t option = let type_get_annotation tenv (typ : Typ.t) : Annot.Item.t option =
match typ.desc with match typ.desc with
| Tptr ({desc= Tstruct name}, _) | Tstruct name -> ( | Tptr ({desc= Tstruct name}, _) | Tstruct name ->
match Tenv.lookup tenv name with Some {annots} -> Some annots | None -> None ) type_name_get_annotation tenv name
| _ -> | _ ->
None None

@ -122,6 +122,8 @@ val override_iter : (Procname.t -> unit) -> Tenv.t -> Procname.t -> unit
val lookup_attributes : Tenv.t -> Procname.t -> ProcAttributes.t option val lookup_attributes : Tenv.t -> Procname.t -> ProcAttributes.t option
val type_name_get_annotation : Tenv.t -> Typ.name -> Annot.Item.t option
val type_get_annotation : Tenv.t -> Typ.t -> Annot.Item.t option val type_get_annotation : Tenv.t -> Typ.t -> Annot.Item.t option
val type_get_class_name : Typ.t -> Typ.Name.t option val type_get_class_name : Typ.t -> Typ.Name.t option

@ -12,14 +12,6 @@ open! IStd
*) *)
type t = {annotation_deprecated: Annot.Item.t; annotated_type: AnnotatedType.t} type t = {annotation_deprecated: Annot.Item.t; annotated_type: AnnotatedType.t}
let is_class_in_strict_mode tenv typ =
match PatternMatch.type_get_annotation tenv typ with
| Some ia ->
Annotations.ia_is_nullsafe_strict ia
| None ->
false
let rec get_type_name {Typ.desc} = let rec get_type_name {Typ.desc} =
match desc with Typ.Tstruct name -> Some name | Typ.Tptr (t, _) -> get_type_name t | _ -> None match desc with Typ.Tstruct name -> Some name | Typ.Tptr (t, _) -> get_type_name t | _ -> None
@ -47,12 +39,15 @@ let is_enum_value tenv ~class_typ (field_info : Struct.field_info) =
let get tenv field_name class_typ = let get tenv field_name class_typ =
let lookup = Tenv.lookup tenv in let lookup = Tenv.lookup tenv in
(* We currently don't support field-level strict mode annotation, so fetch it from class *) (* We currently don't support field-level strict mode annotation, so fetch it from class *)
let is_strict_mode = is_class_in_strict_mode tenv class_typ in let nullsafe_mode =
Typ.name class_typ
|> Option.value_map ~f:(NullsafeMode.of_class tenv) ~default:NullsafeMode.Default
in
Struct.get_field_info ~lookup field_name class_typ Struct.get_field_info ~lookup field_name class_typ
|> Option.map ~f:(fun (Struct.{typ= field_typ; annotations} as field_info) -> |> Option.map ~f:(fun (Struct.{typ= field_typ; annotations} as field_info) ->
let is_enum_value = is_enum_value tenv ~class_typ field_info in let is_enum_value = is_enum_value tenv ~class_typ field_info in
let nullability = let nullability =
AnnotatedNullability.of_type_and_annotation field_typ annotations ~is_strict_mode AnnotatedNullability.of_type_and_annotation field_typ annotations ~nullsafe_mode
in in
let corrected_nullability = let corrected_nullability =
match nullability with match nullability with

@ -91,7 +91,7 @@ let pp fmt t =
F.fprintf fmt "StrictNonnull[%s]" (string_of_nonnull_origin origin) F.fprintf fmt "StrictNonnull[%s]" (string_of_nonnull_origin origin)
let of_type_and_annotation ~is_strict_mode typ annotations = let of_type_and_annotation ~(nullsafe_mode : NullsafeMode.t) typ annotations =
if not (PatternMatch.type_is_class typ) then StrictNonnull PrimitiveType if not (PatternMatch.type_is_class typ) then StrictNonnull PrimitiveType
else if Annotations.ia_is_nullable annotations then else if Annotations.ia_is_nullable annotations then
let nullable_origin = let nullable_origin =
@ -99,7 +99,11 @@ let of_type_and_annotation ~is_strict_mode typ annotations =
else AnnotatedNullable else AnnotatedNullable
in in
Nullable nullable_origin Nullable nullable_origin
else if is_strict_mode then StrictNonnull StrictMode else
else if Annotations.ia_is_nonnull annotations then UncheckedNonnull AnnotatedNonnull match nullsafe_mode with
| NullsafeMode.Strict ->
StrictNonnull StrictMode
| NullsafeMode.Default ->
if Annotations.ia_is_nonnull annotations then UncheckedNonnull AnnotatedNonnull
(* Currently, we treat not annotated types as nonnull *) (* Currently, we treat not annotated types as nonnull *)
else UncheckedNonnull ImplicitlyNonnull else UncheckedNonnull ImplicitlyNonnull

@ -51,7 +51,7 @@ and strict_nonnull_origin =
val get_nullability : t -> Nullability.t val get_nullability : t -> Nullability.t
val of_type_and_annotation : is_strict_mode:bool -> Typ.t -> Annot.Item.t -> t val of_type_and_annotation : nullsafe_mode:NullsafeMode.t -> Typ.t -> Annot.Item.t -> t
(** Given the type and its annotations, returns its nullability. NOTE: it does not take into account (** Given the type and its annotations, returns its 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 models etc., so this is intended to be used as a helper function for more high-level annotation
processing. *) processing. *)

@ -16,7 +16,7 @@ module L = Logging
*) *)
type t = type t =
{ is_strict_mode: bool { nullsafe_mode: NullsafeMode.t
; model_source: model_source option ; model_source: model_source option
; ret: ret_signature ; ret: ret_signature
; params: param_signature list } ; params: param_signature list }
@ -35,10 +35,10 @@ and model_source = InternalModel | ThirdPartyRepo of {filename: string; line_num
[@@deriving compare] [@@deriving compare]
(* get nullability of method's return type given its annotations and information about its params *) (* get nullability of method's return type given its annotations and information about its params *)
let nullability_for_return ret_type ret_annotations ~is_strict_mode let nullability_for_return ret_type ret_annotations ~nullsafe_mode ~has_propagates_nullable_in_param
~has_propagates_nullable_in_param = =
let nullability = let nullability =
AnnotatedNullability.of_type_and_annotation ~is_strict_mode ret_type ret_annotations AnnotatedNullability.of_type_and_annotation ~nullsafe_mode ret_type ret_annotations
in in
(* if any param is annotated with propagates nullable, then the result is nullable *) (* if any param is annotated with propagates nullable, then the result is nullable *)
match nullability with match nullability with
@ -53,10 +53,10 @@ let nullability_for_return ret_type ret_annotations ~is_strict_mode
(* Given annotations for method signature, extract nullability information (* Given annotations for method signature, extract nullability information
for return type and params *) for return type and params *)
let extract_nullability ~is_strict_mode ret_type ret_annotations param_annotated_types = let extract_nullability ~nullsafe_mode ret_type ret_annotations param_annotated_types =
let params_nullability = let params_nullability =
List.map param_annotated_types ~f:(fun (typ, annotations) -> List.map param_annotated_types ~f:(fun (typ, annotations) ->
AnnotatedNullability.of_type_and_annotation typ annotations ~is_strict_mode ) AnnotatedNullability.of_type_and_annotation typ annotations ~nullsafe_mode )
in in
let has_propagates_nullable_in_param = let has_propagates_nullable_in_param =
List.exists params_nullability ~f:(function List.exists params_nullability ~f:(function
@ -66,13 +66,12 @@ let extract_nullability ~is_strict_mode ret_type ret_annotations param_annotated
false ) false )
in in
let return_nullability = let return_nullability =
nullability_for_return ret_type ret_annotations ~is_strict_mode nullability_for_return ret_type ret_annotations ~nullsafe_mode ~has_propagates_nullable_in_param
~has_propagates_nullable_in_param
in in
(return_nullability, params_nullability) (return_nullability, params_nullability)
let get ~is_strict_mode proc_attributes : t = let get ~nullsafe_mode proc_attributes : t =
let Annot.Method.{return= ret_annotation; params= original_params_annotation} = let Annot.Method.{return= ret_annotation; params= original_params_annotation} =
proc_attributes.ProcAttributes.method_annotation proc_attributes.ProcAttributes.method_annotation
in in
@ -101,7 +100,7 @@ let get ~is_strict_mode proc_attributes : t =
List.map params_with_annotations ~f:(fun ((_, typ), annotations) -> (typ, annotations)) List.map params_with_annotations ~f:(fun ((_, typ), annotations) -> (typ, annotations))
in in
let return_nullability, params_nullability = let return_nullability, params_nullability =
extract_nullability ~is_strict_mode ret_type ret_annotation param_annotated_types extract_nullability ~nullsafe_mode ret_type ret_annotation param_annotated_types
in in
let ret = let ret =
{ ret_annotation_deprecated= ret_annotation { ret_annotation_deprecated= ret_annotation
@ -114,7 +113,7 @@ let get ~is_strict_mode proc_attributes : t =
; mangled ; mangled
; param_annotated_type= AnnotatedType.{nullability; typ} } ) ; param_annotated_type= AnnotatedType.{nullability; typ} } )
in in
{is_strict_mode; model_source= None; ret; params} {nullsafe_mode; model_source= None; ret; params}
let param_has_annot predicate pvar ann_sig = let param_has_annot predicate pvar ann_sig =
@ -131,9 +130,8 @@ let pp proc_name fmt annotated_signature =
Mangled.pp mangled Mangled.pp mangled
in in
let {ret_annotation_deprecated; ret_annotated_type} = annotated_signature.ret in let {ret_annotation_deprecated; ret_annotated_type} = annotated_signature.ret in
let mode_as_string = if annotated_signature.is_strict_mode then "Strict" else "Def" in F.fprintf fmt "[%a] %a%a %a (%a )" NullsafeMode.pp annotated_signature.nullsafe_mode pp_ia
F.fprintf fmt "[%s] %a%a %a (%a )" mode_as_string pp_ia ret_annotation_deprecated AnnotatedType.pp ret_annotation_deprecated AnnotatedType.pp ret_annotated_type
ret_annotated_type
(Procname.pp_simplified_string ~withclass:false) (Procname.pp_simplified_string ~withclass:false)
proc_name (Pp.comma_seq pp_annotated_param) annotated_signature.params proc_name (Pp.comma_seq pp_annotated_param) annotated_signature.params

@ -10,7 +10,7 @@
open! IStd open! IStd
type t = type t =
{ is_strict_mode: bool { nullsafe_mode: NullsafeMode.t
; model_source: model_source option (** None, if signature is not modelled *) ; model_source: model_source option (** None, if signature is not modelled *)
; ret: ret_signature ; ret: ret_signature
; params: param_signature list } ; params: param_signature list }
@ -35,7 +35,7 @@ val set_modelled_nullability : Procname.t -> t -> model_source -> bool * bool li
(** Override nullability for a function signature given its modelled nullability (for ret value and (** Override nullability for a function signature given its modelled nullability (for ret value and
params) *) params) *)
val get : is_strict_mode:bool -> ProcAttributes.t -> t val get : nullsafe_mode:NullsafeMode.t -> ProcAttributes.t -> t
(** Get a method signature with annotations from a proc_attributes. *) (** Get a method signature with annotations from a proc_attributes. *)
val pp : Procname.t -> Format.formatter -> t -> unit val pp : Procname.t -> Format.formatter -> t -> unit

@ -6,7 +6,8 @@
*) *)
open! IStd open! IStd
type violation = {is_strict_mode: bool; lhs: Nullability.t; rhs: Nullability.t} [@@deriving compare] type violation = {nullsafe_mode: NullsafeMode.t; lhs: Nullability.t; rhs: Nullability.t}
[@@deriving compare]
type assignment_type = type assignment_type =
| PassingParamToFunction of function_info | PassingParamToFunction of function_info
@ -21,24 +22,28 @@ and function_info =
; param_position: int ; param_position: int
; function_procname: Procname.t } ; function_procname: Procname.t }
let is_whitelisted_assignment ~is_strict_mode ~lhs ~rhs = let is_whitelisted_assignment ~nullsafe_mode ~lhs ~rhs =
match (is_strict_mode, lhs, rhs) with match nullsafe_mode with
| false, Nullability.StrictNonnull, Nullability.UncheckedNonnull -> | NullsafeMode.Default -> (
match (lhs, rhs) with
| Nullability.StrictNonnull, Nullability.UncheckedNonnull ->
(* We allow UncheckedNonnull -> StrictNonnull conversion outside of strict mode for better adoption. (* We allow UncheckedNonnull -> StrictNonnull conversion outside of strict mode for better adoption.
Otherwise using strictified classes in non-strict context becomes a pain because Otherwise using strictified classes in non-strict context becomes a pain because
of extra warnings. of extra warnings.
*) *)
true true
| _ -> | _ ->
false )
| NullsafeMode.Strict ->
false false
let check ~is_strict_mode ~lhs ~rhs = let check ~(nullsafe_mode : NullsafeMode.t) ~lhs ~rhs =
let is_allowed_assignment = let is_allowed_assignment =
Nullability.is_subtype ~subtype:rhs ~supertype:lhs Nullability.is_subtype ~subtype:rhs ~supertype:lhs
|| is_whitelisted_assignment ~is_strict_mode ~lhs ~rhs || is_whitelisted_assignment ~nullsafe_mode ~lhs ~rhs
in in
Result.ok_if_true is_allowed_assignment ~error:{is_strict_mode; lhs; rhs} Result.ok_if_true is_allowed_assignment ~error:{nullsafe_mode; lhs; rhs}
let get_origin_opt assignment_type origin = let get_origin_opt assignment_type origin =
@ -130,11 +135,15 @@ let bad_param_description
nullability_evidence_as_suffix nullability_evidence_as_suffix
let is_declared_nonnull_to_nonnull ~lhs ~rhs = let is_unchecked_nonnull_to_strict_nonnull ~lhs ~rhs =
match (lhs, rhs) with match (lhs, rhs) with
| Nullability.StrictNonnull, Nullability.UncheckedNonnull -> | Nullability.StrictNonnull, Nullability.UncheckedNonnull ->
true true
| _ -> (* Don't fold those cases into catch-all *)
| Nullability.StrictNonnull, _
| Nullability.UncheckedNonnull, _
| Nullability.Nullable, _
| Nullability.Null, _ ->
false false
@ -147,10 +156,10 @@ let get_issue_type = function
IssueType.eradicate_return_not_nullable IssueType.eradicate_return_not_nullable
let violation_description {is_strict_mode; lhs; rhs} ~assignment_location assignment_type let violation_description {nullsafe_mode; lhs; rhs} ~assignment_location assignment_type ~rhs_origin
~rhs_origin = =
if is_declared_nonnull_to_nonnull ~lhs ~rhs then ( if is_unchecked_nonnull_to_strict_nonnull ~lhs ~rhs then (
if not is_strict_mode then if not (NullsafeMode.equal nullsafe_mode NullsafeMode.Strict) then
Logging.die InternalError "Unexpected situation: should not be a violation not in strict mode" ; Logging.die InternalError "Unexpected situation: should not be a violation not in strict mode" ;
(* This type of violation is more subtle than the normal case because, so it should be rendered in a special way *) (* 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:assignment_location ErrorRenderingUtils.get_strict_mode_violation_issue ~bad_usage_location:assignment_location
@ -201,5 +210,4 @@ let violation_description {is_strict_mode; lhs; rhs} ~assignment_location assign
(error_message, issue_type, assignment_location) (error_message, issue_type, assignment_location)
let violation_severity {is_strict_mode} = let violation_severity {nullsafe_mode} = NullsafeMode.severity nullsafe_mode
if is_strict_mode then Exceptions.Error else Exceptions.Warning

@ -13,7 +13,7 @@ open! IStd
type violation [@@deriving compare] type violation [@@deriving compare]
val check : val check :
is_strict_mode:bool -> lhs:Nullability.t -> rhs:Nullability.t -> (unit, violation) result nullsafe_mode:NullsafeMode.t -> lhs:Nullability.t -> rhs:Nullability.t -> (unit, violation) result
type assignment_type = type assignment_type =
| PassingParamToFunction of function_info | PassingParamToFunction of function_info

@ -6,7 +6,7 @@
*) *)
open! IStd open! IStd
type violation = {is_strict_mode: bool; nullability: Nullability.t} [@@deriving compare] type violation = {nullsafe_mode: NullsafeMode.t; nullability: Nullability.t} [@@deriving compare]
type dereference_type = type dereference_type =
| MethodCall of Procname.t | MethodCall of Procname.t
@ -15,12 +15,16 @@ type dereference_type =
| ArrayLengthAccess | ArrayLengthAccess
[@@deriving compare] [@@deriving compare]
let check ~is_strict_mode nullability = let check ~nullsafe_mode nullability =
match nullability with match nullability with
| Nullability.Nullable | Nullability.Null -> | Nullability.Nullable | Nullability.Null ->
Error {is_strict_mode; nullability} Error {nullsafe_mode; nullability}
| Nullability.UncheckedNonnull -> | Nullability.UncheckedNonnull -> (
if is_strict_mode then Error {is_strict_mode; nullability} else Ok () match nullsafe_mode with
| NullsafeMode.Strict ->
Error {nullsafe_mode; nullability}
| NullsafeMode.Default ->
Ok () )
| Nullability.StrictNonnull -> | Nullability.StrictNonnull ->
Ok () Ok ()
@ -97,5 +101,4 @@ let violation_description {nullability} ~dereference_location dereference_type
(description, IssueType.eradicate_nullable_dereference, dereference_location) (description, IssueType.eradicate_nullable_dereference, dereference_location)
let violation_severity {is_strict_mode} = let violation_severity {nullsafe_mode} = NullsafeMode.severity nullsafe_mode
if is_strict_mode then Exceptions.Error else Exceptions.Warning

@ -11,7 +11,7 @@ open! IStd
type violation [@@deriving compare] type violation [@@deriving compare]
val check : is_strict_mode:bool -> Nullability.t -> (unit, violation) result val check : nullsafe_mode:NullsafeMode.t -> Nullability.t -> (unit, violation) result
type dereference_type = type dereference_type =
| MethodCall of Procname.t | MethodCall of Procname.t

@ -6,7 +6,7 @@
*) *)
open! IStd open! IStd
type violation = {is_strict_mode: bool; base: Nullability.t; overridden: Nullability.t} type violation = {nullsafe_mode: NullsafeMode.t; base: Nullability.t; overridden: Nullability.t}
[@@deriving compare] [@@deriving compare]
type type_role = Param | Ret type type_role = Param | Ret
@ -23,7 +23,7 @@ let is_whitelisted_violation ~subtype ~supertype =
false false
let check ~is_strict_mode type_role ~base ~overridden = let check ~nullsafe_mode type_role ~base ~overridden =
let subtype, supertype = let subtype, supertype =
match type_role with match type_role with
| Ret -> | Ret ->
@ -35,7 +35,7 @@ let check ~is_strict_mode type_role ~base ~overridden =
in in
Result.ok_if_true Result.ok_if_true
(Nullability.is_subtype ~subtype ~supertype || is_whitelisted_violation ~subtype ~supertype) (Nullability.is_subtype ~subtype ~supertype || is_whitelisted_violation ~subtype ~supertype)
~error:{is_strict_mode; base; overridden} ~error:{nullsafe_mode; base; overridden}
type violation_type = type violation_type =
@ -94,5 +94,4 @@ let violation_description _ violation_type ~base_proc_name ~overridden_proc_name
MF.pp_monospaced base_method_descr MF.pp_monospaced base_method_descr
let violation_severity {is_strict_mode} = let violation_severity {nullsafe_mode} = NullsafeMode.severity nullsafe_mode
if is_strict_mode then Exceptions.Error else Exceptions.Warning

@ -27,7 +27,7 @@ type violation_type =
type type_role = Param | Ret type type_role = Param | Ret
val check : val check :
is_strict_mode:bool nullsafe_mode:NullsafeMode.t
-> type_role -> type_role
-> base:Nullability.t -> base:Nullability.t
-> overridden:Nullability.t -> overridden:Nullability.t

@ -0,0 +1,25 @@
(*
* 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
type t = Default | Strict [@@deriving compare, equal]
let of_class tenv typ_name =
match PatternMatch.type_name_get_annotation tenv typ_name with
| Some annots ->
if Annotations.ia_is_nullsafe_strict annots then Strict else Default
| None ->
Default
let severity = function Strict -> Exceptions.Error | Default -> Exceptions.Warning
let to_string = function Default -> " Def" | Strict -> "Strict"
let pp fmt t = F.fprintf fmt "%s" (to_string t)

@ -0,0 +1,20 @@
(*
* 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
(** Represents a type-checking mode of nullsafe. *)
type t = Default | Strict [@@deriving compare, equal]
val of_class : Tenv.t -> Typ.name -> t
(** Extracts mode information from class annotations *)
val severity : t -> Exceptions.severity
(** Provides a default choice of issue severity for a particular mode *)
val pp : Format.formatter -> t -> unit

@ -164,7 +164,7 @@ module MkCallback (Extension : ExtensionT) : CallBackT = struct
in in
EradicateChecks.check_constructor_initialization tenv find_canonical_duplicate curr_pname EradicateChecks.check_constructor_initialization tenv find_canonical_duplicate curr_pname
curr_pdesc start_node curr_pdesc start_node
~is_strict_mode:annotated_signature.AnnotatedSignature.is_strict_mode ~nullsafe_mode:annotated_signature.AnnotatedSignature.nullsafe_mode
~typestates_for_curr_constructor_and_all_initializer_methods ~typestates_for_curr_constructor_and_all_initializer_methods
~typestates_for_all_constructors_incl_current proc_loc ; ~typestates_for_all_constructors_incl_current proc_loc ;
if Config.eradicate_verbose then L.result "Final Typestate@\n%a@." TypeState.pp typestate if Config.eradicate_verbose then L.result "Final Typestate@\n%a@." TypeState.pp typestate

@ -26,10 +26,10 @@ let is_virtual = function
false false
let check_object_dereference ~is_strict_mode tenv find_canonical_duplicate curr_pname node instr_ref let check_object_dereference ~nullsafe_mode tenv find_canonical_duplicate curr_pname node instr_ref
object_exp dereference_type inferred_nullability loc = object_exp dereference_type inferred_nullability loc =
Result.iter_error Result.iter_error
(DereferenceRule.check ~is_strict_mode (DereferenceRule.check ~nullsafe_mode
(InferredNullability.get_nullability inferred_nullability)) (InferredNullability.get_nullability inferred_nullability))
~f:(fun dereference_violation -> ~f:(fun dereference_violation ->
let nullable_object_origin = InferredNullability.get_origin inferred_nullability in let nullable_object_origin = InferredNullability.get_origin inferred_nullability in
@ -126,7 +126,7 @@ let check_nonzero tenv find_canonical_duplicate =
(** Check an assignment to a field. *) (** Check an assignment to a field. *)
let check_field_assignment ~is_strict_mode tenv find_canonical_duplicate curr_pdesc node instr_ref let check_field_assignment ~nullsafe_mode tenv find_canonical_duplicate curr_pdesc node instr_ref
typestate exp_lhs exp_rhs typ loc fname annotated_field_opt typecheck_expr : unit = typestate exp_lhs exp_rhs typ loc fname annotated_field_opt typecheck_expr : unit =
let curr_pname = Procdesc.get_proc_name curr_pdesc in let curr_pname = Procdesc.get_proc_name curr_pdesc in
let curr_pattrs = Procdesc.get_attributes curr_pdesc in let curr_pattrs = Procdesc.get_attributes curr_pdesc in
@ -156,7 +156,7 @@ let check_field_assignment ~is_strict_mode tenv find_canonical_duplicate curr_pd
Annotations.ia_is_cleanup ret_annotation_deprecated Annotations.ia_is_cleanup ret_annotation_deprecated
in in
let assignment_check_result = let assignment_check_result =
AssignmentRule.check ~is_strict_mode AssignmentRule.check ~nullsafe_mode
~lhs:(InferredNullability.get_nullability inferred_nullability_lhs) ~lhs:(InferredNullability.get_nullability inferred_nullability_lhs)
~rhs:(InferredNullability.get_nullability inferred_nullability_rhs) ~rhs:(InferredNullability.get_nullability inferred_nullability_rhs)
in in
@ -241,7 +241,7 @@ let get_nullability_upper_bound field_name typestate_list =
(** Check field initialization for a given constructor *) (** Check field initialization for a given constructor *)
let check_constructor_initialization tenv find_canonical_duplicate curr_constructor_pname let check_constructor_initialization tenv find_canonical_duplicate curr_constructor_pname
curr_constructor_pdesc start_node ~is_strict_mode curr_constructor_pdesc start_node ~nullsafe_mode
~typestates_for_curr_constructor_and_all_initializer_methods ~typestates_for_curr_constructor_and_all_initializer_methods
~typestates_for_all_constructors_incl_current loc : unit = ~typestates_for_all_constructors_incl_current loc : unit =
State.set_node start_node ; State.set_node start_node ;
@ -305,7 +305,7 @@ let check_constructor_initialization tenv find_canonical_duplicate curr_construc
then then
if if
Config.nullsafe_disable_field_not_initialized_in_nonstrict_classes Config.nullsafe_disable_field_not_initialized_in_nonstrict_classes
&& not is_strict_mode && NullsafeMode.equal nullsafe_mode NullsafeMode.Default
then then
(* Behavior needed for backward compatibility, where we are not ready to surface this type of errors by default. (* Behavior needed for backward compatibility, where we are not ready to surface this type of errors by default.
Hovewer, this error should be always turned on for @NullsafeStrict classes. Hovewer, this error should be always turned on for @NullsafeStrict classes.
@ -313,7 +313,7 @@ let check_constructor_initialization tenv find_canonical_duplicate curr_construc
() ()
else else
report_error tenv find_canonical_duplicate report_error tenv find_canonical_duplicate
(TypeErr.Field_not_initialized {is_strict_mode; field_name}) (TypeErr.Field_not_initialized {nullsafe_mode; field_name})
None loc curr_constructor_pdesc ; None loc curr_constructor_pdesc ;
(* Check if field is over-annotated. *) (* Check if field is over-annotated. *)
match annotated_field with match annotated_field with
@ -341,12 +341,12 @@ let check_constructor_initialization tenv find_canonical_duplicate curr_construc
() ()
let check_return_not_nullable ~is_strict_mode tenv find_canonical_duplicate loc curr_pname let check_return_not_nullable ~nullsafe_mode tenv find_canonical_duplicate loc curr_pname curr_pdesc
curr_pdesc (ret_signature : AnnotatedSignature.ret_signature) ret_inferred_nullability = (ret_signature : AnnotatedSignature.ret_signature) ret_inferred_nullability =
(* Returning from a function is essentially an assignment the actual return value to the formal `return` *) (* Returning from a function is essentially an assignment the actual return value to the formal `return` *)
let lhs = AnnotatedNullability.get_nullability ret_signature.ret_annotated_type.nullability in let lhs = AnnotatedNullability.get_nullability ret_signature.ret_annotated_type.nullability in
let rhs = InferredNullability.get_nullability ret_inferred_nullability in let rhs = InferredNullability.get_nullability ret_inferred_nullability in
Result.iter_error (AssignmentRule.check ~is_strict_mode ~lhs ~rhs) ~f:(fun assignment_violation -> Result.iter_error (AssignmentRule.check ~nullsafe_mode ~lhs ~rhs) ~f:(fun assignment_violation ->
let rhs_origin = InferredNullability.get_origin ret_inferred_nullability in let rhs_origin = InferredNullability.get_origin ret_inferred_nullability in
report_error tenv find_canonical_duplicate report_error tenv find_canonical_duplicate
(TypeErr.Bad_assignment (TypeErr.Bad_assignment
@ -391,7 +391,7 @@ let check_return_annotation tenv find_canonical_duplicate curr_pdesc ret_range
| Some (_, ret_inferred_nullability) -> | Some (_, ret_inferred_nullability) ->
(* TODO(T54308240) Model ret_implicitly_nullable in AnnotatedNullability *) (* TODO(T54308240) Model ret_implicitly_nullable in AnnotatedNullability *)
if not ret_implicitly_nullable then if not ret_implicitly_nullable then
check_return_not_nullable ~is_strict_mode:annotated_signature.is_strict_mode tenv check_return_not_nullable ~nullsafe_mode:annotated_signature.nullsafe_mode tenv
find_canonical_duplicate loc curr_pname curr_pdesc annotated_signature.ret find_canonical_duplicate loc curr_pname curr_pdesc annotated_signature.ret
ret_inferred_nullability ; ret_inferred_nullability ;
if Config.eradicate_return_over_annotated then if Config.eradicate_return_over_annotated then
@ -402,7 +402,7 @@ let check_return_annotation tenv find_canonical_duplicate curr_pdesc ret_range
(** Check the receiver of a virtual call. *) (** Check the receiver of a virtual call. *)
let check_call_receiver ~is_strict_mode tenv find_canonical_duplicate curr_pdesc node typestate let check_call_receiver ~nullsafe_mode tenv find_canonical_duplicate curr_pdesc node typestate
call_params callee_pname (instr_ref : TypeErr.InstrRef.t) loc typecheck_expr : unit = call_params callee_pname (instr_ref : TypeErr.InstrRef.t) loc typecheck_expr : unit =
match call_params with match call_params with
| ((original_this_e, this_e), typ) :: _ -> | ((original_this_e, this_e), typ) :: _ ->
@ -412,7 +412,7 @@ let check_call_receiver ~is_strict_mode tenv find_canonical_duplicate curr_pdesc
(typ, InferredNullability.create TypeOrigin.OptimisticFallback) (typ, InferredNullability.create TypeOrigin.OptimisticFallback)
loc loc
in in
check_object_dereference ~is_strict_mode tenv find_canonical_duplicate curr_pdesc node check_object_dereference ~nullsafe_mode tenv find_canonical_duplicate curr_pdesc node
instr_ref original_this_e (DereferenceRule.MethodCall callee_pname) instr_ref original_this_e (DereferenceRule.MethodCall callee_pname)
this_inferred_nullability loc this_inferred_nullability loc
| [] -> | [] ->
@ -452,7 +452,7 @@ let is_third_party_without_model proc_name model_source =
(** Check the parameters of a call. *) (** Check the parameters of a call. *)
let check_call_parameters ~is_strict_mode ~callee_annotated_signature tenv find_canonical_duplicate let check_call_parameters ~nullsafe_mode ~callee_annotated_signature tenv find_canonical_duplicate
curr_pdesc node callee_attributes resolved_params loc instr_ref : unit = curr_pdesc node callee_attributes resolved_params loc instr_ref : unit =
let callee_pname = callee_attributes.ProcAttributes.proc_name in let callee_pname = callee_attributes.ProcAttributes.proc_name in
let check {num= param_position; formal; actual= orig_e2, nullability_actual} = let check {num= param_position; formal; actual= orig_e2, nullability_actual} =
@ -484,12 +484,13 @@ let check_call_parameters ~is_strict_mode ~callee_annotated_signature tenv find_
to the formal param *) to the formal param *)
let lhs = AnnotatedNullability.get_nullability formal.param_annotated_type.nullability in let lhs = AnnotatedNullability.get_nullability formal.param_annotated_type.nullability in
let rhs = InferredNullability.get_nullability nullability_actual in let rhs = InferredNullability.get_nullability nullability_actual in
Result.iter_error (AssignmentRule.check ~is_strict_mode ~lhs ~rhs) ~f:report Result.iter_error (AssignmentRule.check ~nullsafe_mode ~lhs ~rhs) ~f:report
in in
let should_ignore_parameters_check = let should_ignore_parameters_check =
(* TODO(T52947663) model params in third-party non modelled method as a dedicated nullability type, (* TODO(T52947663) model params in third-party non modelled method as a dedicated nullability type,
so this logic can be moved to [AssignmentRule.check] *) so this logic can be moved to [AssignmentRule.check] *)
(not is_strict_mode) && Config.nullsafe_optimistic_third_party_params_in_non_strict NullsafeMode.equal nullsafe_mode NullsafeMode.Default
&& Config.nullsafe_optimistic_third_party_params_in_non_strict
&& is_third_party_without_model callee_pname && is_third_party_without_model callee_pname
callee_annotated_signature.AnnotatedSignature.model_source callee_annotated_signature.AnnotatedSignature.model_source
in in
@ -498,11 +499,11 @@ let check_call_parameters ~is_strict_mode ~callee_annotated_signature tenv find_
List.iter ~f:check resolved_params List.iter ~f:check resolved_params
let check_inheritance_rule_for_return find_canonical_duplicate tenv loc ~is_strict_mode let check_inheritance_rule_for_return find_canonical_duplicate tenv loc ~nullsafe_mode
~base_proc_name ~overridden_proc_name ~overridden_proc_desc ~base_nullability ~base_proc_name ~overridden_proc_name ~overridden_proc_desc ~base_nullability
~overridden_nullability = ~overridden_nullability =
Result.iter_error Result.iter_error
(InheritanceRule.check ~is_strict_mode InheritanceRule.Ret ~base:base_nullability (InheritanceRule.check ~nullsafe_mode InheritanceRule.Ret ~base:base_nullability
~overridden:overridden_nullability) ~f:(fun inheritance_violation -> ~overridden:overridden_nullability) ~f:(fun inheritance_violation ->
report_error tenv find_canonical_duplicate report_error tenv find_canonical_duplicate
(TypeErr.Inconsistent_subclass (TypeErr.Inconsistent_subclass
@ -513,11 +514,11 @@ let check_inheritance_rule_for_return find_canonical_duplicate tenv loc ~is_stri
None loc overridden_proc_desc ) None loc overridden_proc_desc )
let check_inheritance_rule_for_param find_canonical_duplicate tenv loc ~is_strict_mode let check_inheritance_rule_for_param find_canonical_duplicate tenv loc ~nullsafe_mode
~overridden_param_name ~base_proc_name ~overridden_proc_name ~overridden_proc_desc ~overridden_param_name ~base_proc_name ~overridden_proc_name ~overridden_proc_desc
~param_position ~base_nullability ~overridden_nullability = ~param_position ~base_nullability ~overridden_nullability =
Result.iter_error Result.iter_error
(InheritanceRule.check ~is_strict_mode InheritanceRule.Param ~base:base_nullability (InheritanceRule.check ~nullsafe_mode InheritanceRule.Param ~base:base_nullability
~overridden:overridden_nullability) ~f:(fun inheritance_violation -> ~overridden:overridden_nullability) ~f:(fun inheritance_violation ->
report_error tenv find_canonical_duplicate report_error tenv find_canonical_duplicate
(TypeErr.Inconsistent_subclass (TypeErr.Inconsistent_subclass
@ -530,7 +531,7 @@ let check_inheritance_rule_for_param find_canonical_duplicate tenv loc ~is_stric
None loc overridden_proc_desc ) None loc overridden_proc_desc )
let check_inheritance_rule_for_params find_canonical_duplicate tenv loc ~is_strict_mode let check_inheritance_rule_for_params find_canonical_duplicate tenv loc ~nullsafe_mode
~base_proc_name ~overridden_proc_name ~overridden_proc_desc ~base_signature ~base_proc_name ~overridden_proc_name ~overridden_proc_desc ~base_signature
~overridden_signature = ~overridden_signature =
let base_params = base_signature.AnnotatedSignature.params in let base_params = base_signature.AnnotatedSignature.params in
@ -547,7 +548,7 @@ let check_inheritance_rule_for_params find_canonical_duplicate tenv loc ~is_stri
{ mangled= overridden_param_name { mangled= overridden_param_name
; param_annotated_type= {nullability= annotated_nullability_overridden} } ) ; param_annotated_type= {nullability= annotated_nullability_overridden} } )
-> ->
check_inheritance_rule_for_param find_canonical_duplicate tenv loc ~is_strict_mode check_inheritance_rule_for_param find_canonical_duplicate tenv loc ~nullsafe_mode
~overridden_param_name ~base_proc_name ~overridden_proc_name ~overridden_proc_desc ~overridden_param_name ~base_proc_name ~overridden_proc_name ~overridden_proc_desc
~param_position:(if should_index_from_zero then index else index + 1) ~param_position:(if should_index_from_zero then index else index + 1)
~base_nullability:(AnnotatedNullability.get_nullability annotated_nullability_base) ~base_nullability:(AnnotatedNullability.get_nullability annotated_nullability_base)
@ -560,13 +561,12 @@ let check_inheritance_rule_for_params find_canonical_duplicate tenv loc ~is_stri
(* Check both params and return values for complying for co- and contravariance *) (* Check both params and return values for complying for co- and contravariance *)
let check_inheritance_rule_for_signature find_canonical_duplicate tenv loc ~is_strict_mode let check_inheritance_rule_for_signature find_canonical_duplicate tenv loc ~nullsafe_mode
~base_proc_name ~overridden_proc_name ~overridden_proc_desc ~base_signature ~base_proc_name ~overridden_proc_name ~overridden_proc_desc ~base_signature
~overridden_signature = ~overridden_signature =
(* Check params *) (* Check params *)
check_inheritance_rule_for_params find_canonical_duplicate tenv loc ~is_strict_mode check_inheritance_rule_for_params find_canonical_duplicate tenv loc ~nullsafe_mode ~base_proc_name
~base_proc_name ~overridden_proc_name ~overridden_proc_desc ~base_signature ~overridden_proc_name ~overridden_proc_desc ~base_signature ~overridden_signature ;
~overridden_signature ;
(* Check return value *) (* Check return value *)
match base_proc_name with match base_proc_name with
(* TODO model this as unknown nullability and get rid of that check *) (* TODO model this as unknown nullability and get rid of that check *)
@ -580,7 +580,7 @@ let check_inheritance_rule_for_signature find_canonical_duplicate tenv loc ~is_s
AnnotatedNullability.get_nullability AnnotatedNullability.get_nullability
overridden_signature.AnnotatedSignature.ret.ret_annotated_type.nullability overridden_signature.AnnotatedSignature.ret.ret_annotated_type.nullability
in in
check_inheritance_rule_for_return find_canonical_duplicate tenv loc ~is_strict_mode check_inheritance_rule_for_return find_canonical_duplicate tenv loc ~nullsafe_mode
~base_proc_name ~overridden_proc_name ~overridden_proc_desc ~base_nullability ~base_proc_name ~overridden_proc_name ~overridden_proc_desc ~base_nullability
~overridden_nullability ~overridden_nullability
| _ -> | _ ->
@ -599,7 +599,7 @@ let check_overridden_annotations find_canonical_duplicate tenv proc_name proc_de
| Some base_attributes -> | Some base_attributes ->
let base_signature = Models.get_modelled_annotated_signature tenv base_attributes in let base_signature = Models.get_modelled_annotated_signature tenv base_attributes in
check_inheritance_rule_for_signature check_inheritance_rule_for_signature
~is_strict_mode:annotated_signature.AnnotatedSignature.is_strict_mode ~nullsafe_mode:annotated_signature.AnnotatedSignature.nullsafe_mode
find_canonical_duplicate tenv loc ~base_proc_name ~overridden_proc_name:proc_name find_canonical_duplicate tenv loc ~base_proc_name ~overridden_proc_name:proc_name
~overridden_proc_desc:proc_desc ~base_signature ~overridden_signature:annotated_signature ~overridden_proc_desc:proc_desc ~base_signature ~overridden_signature:annotated_signature
| None -> | None ->

@ -33,7 +33,9 @@ let table_has_procedure table proc_name =
*) *)
let get_modelled_annotated_signature_for_biabduction proc_attributes = let get_modelled_annotated_signature_for_biabduction proc_attributes =
let proc_name = proc_attributes.ProcAttributes.proc_name in let proc_name = proc_attributes.ProcAttributes.proc_name in
let annotated_signature = AnnotatedSignature.get ~is_strict_mode:false proc_attributes in let annotated_signature =
AnnotatedSignature.get ~nullsafe_mode:NullsafeMode.Default proc_attributes
in
let proc_id = Procname.to_unique_id proc_name in let proc_id = Procname.to_unique_id proc_name in
let lookup_models_nullable ann_sig = let lookup_models_nullable ann_sig =
try try
@ -66,10 +68,11 @@ let to_modelled_nullability ThirdPartyMethod.{ret_nullability; param_nullability
take precedence over internal ones. *) take precedence over internal ones. *)
let get_modelled_annotated_signature tenv proc_attributes = let get_modelled_annotated_signature tenv proc_attributes =
let proc_name = proc_attributes.ProcAttributes.proc_name in let proc_name = proc_attributes.ProcAttributes.proc_name in
let is_strict_mode = let nullsafe_mode =
PatternMatch.check_current_class_attributes Annotations.ia_is_nullsafe_strict tenv proc_name Procname.get_class_type_name proc_name
|> Option.value_map ~default:NullsafeMode.Default ~f:(NullsafeMode.of_class tenv)
in in
let annotated_signature = AnnotatedSignature.get ~is_strict_mode proc_attributes in let annotated_signature = AnnotatedSignature.get ~nullsafe_mode proc_attributes in
let proc_id = Procname.to_unique_id proc_name in let proc_id = Procname.to_unique_id proc_name in
(* Look in the infer internal models *) (* Look in the infer internal models *)
let correct_by_internal_models ann_sig = let correct_by_internal_models ann_sig =

@ -108,7 +108,7 @@ type find_canonical_duplicate = Procdesc.Node.t -> Procdesc.Node.t
type checks = {eradicate: bool; check_ret_type: check_return_type list} type checks = {eradicate: bool; check_ret_type: check_return_type list}
(** Typecheck an expression. *) (** Typecheck an expression. *)
let rec typecheck_expr ~is_strict_mode find_canonical_duplicate visited checks tenv node instr_ref let rec typecheck_expr ~nullsafe_mode find_canonical_duplicate visited checks tenv node instr_ref
(curr_pdesc : Procdesc.t) typestate e tr_default loc : TypeState.range = (curr_pdesc : Procdesc.t) typestate e tr_default loc : TypeState.range =
match e with match e with
(* null literal or 0 *) (* null literal or 0 *)
@ -131,12 +131,12 @@ let rec typecheck_expr ~is_strict_mode find_canonical_duplicate visited checks t
| Exp.Var id -> | Exp.Var id ->
Option.value (TypeState.lookup_id id typestate) ~default:tr_default Option.value (TypeState.lookup_id id typestate) ~default:tr_default
| Exp.Exn e1 -> | Exp.Exn e1 ->
typecheck_expr ~is_strict_mode find_canonical_duplicate visited checks tenv node instr_ref typecheck_expr ~nullsafe_mode find_canonical_duplicate visited checks tenv node instr_ref
curr_pdesc typestate e1 tr_default loc curr_pdesc typestate e1 tr_default loc
| Exp.Lfield (exp, field_name, typ) -> | Exp.Lfield (exp, field_name, typ) ->
let _, _ = tr_default in let _, _ = tr_default in
let _, inferred_nullability = let _, inferred_nullability =
typecheck_expr ~is_strict_mode find_canonical_duplicate visited checks tenv node instr_ref typecheck_expr ~nullsafe_mode find_canonical_duplicate visited checks tenv node instr_ref
curr_pdesc typestate exp curr_pdesc typestate exp
(* TODO(T54687014) optimistic default might be an unsoundness issue - investigate *) (* TODO(T54687014) optimistic default might be an unsoundness issue - investigate *)
(typ, InferredNullability.create TypeOrigin.OptimisticFallback) (typ, InferredNullability.create TypeOrigin.OptimisticFallback)
@ -153,20 +153,20 @@ let rec typecheck_expr ~is_strict_mode find_canonical_duplicate visited checks t
tr_default tr_default
in in
if checks.eradicate then if checks.eradicate then
EradicateChecks.check_object_dereference ~is_strict_mode tenv find_canonical_duplicate EradicateChecks.check_object_dereference ~nullsafe_mode tenv find_canonical_duplicate
curr_pdesc node instr_ref exp (DereferenceRule.AccessToField field_name) curr_pdesc node instr_ref exp (DereferenceRule.AccessToField field_name)
inferred_nullability loc ; inferred_nullability loc ;
tr_new tr_new
| Exp.Lindex (array_exp, index_exp) -> | Exp.Lindex (array_exp, index_exp) ->
let _, inferred_nullability = let _, inferred_nullability =
typecheck_expr ~is_strict_mode find_canonical_duplicate visited checks tenv node instr_ref typecheck_expr ~nullsafe_mode find_canonical_duplicate visited checks tenv node instr_ref
curr_pdesc typestate array_exp tr_default loc curr_pdesc typestate array_exp tr_default loc
in in
let index_desc = let index_desc =
match EradicateChecks.explain_expr tenv node index_exp with Some s -> s | None -> "?" match EradicateChecks.explain_expr tenv node index_exp with Some s -> s | None -> "?"
in in
if checks.eradicate then if checks.eradicate then
EradicateChecks.check_object_dereference ~is_strict_mode tenv find_canonical_duplicate EradicateChecks.check_object_dereference ~nullsafe_mode tenv find_canonical_duplicate
curr_pdesc node instr_ref array_exp curr_pdesc node instr_ref array_exp
(DereferenceRule.AccessByIndex {index_desc}) (DereferenceRule.AccessByIndex {index_desc})
inferred_nullability loc ; inferred_nullability loc ;
@ -421,20 +421,20 @@ let pvar_apply instr_ref idenv tenv curr_pname curr_annotated_signature loc hand
(* typecheck_expr with fewer parameters, using a common template for typestate range *) (* typecheck_expr with fewer parameters, using a common template for typestate range *)
let typecheck_expr_simple ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this checks tenv let typecheck_expr_simple ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this checks tenv
node instr_ref typestate1 exp1 typ1 origin1 loc1 = node instr_ref typestate1 exp1 typ1 origin1 loc1 =
typecheck_expr ~is_strict_mode find_canonical_duplicate calls_this checks tenv node instr_ref typecheck_expr ~nullsafe_mode find_canonical_duplicate calls_this checks tenv node instr_ref
curr_pdesc typestate1 exp1 curr_pdesc typestate1 exp1
(typ1, InferredNullability.create origin1) (typ1, InferredNullability.create origin1)
loc1 loc1
(* check if there are errors in exp1 *) (* check if there are errors in exp1 *)
let typecheck_expr_for_errors ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this checks let typecheck_expr_for_errors ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this checks
tenv node instr_ref typestate1 exp1 loc1 : unit = tenv node instr_ref typestate1 exp1 loc1 : unit =
ignore ignore
(typecheck_expr_simple ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this checks (typecheck_expr_simple ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this checks tenv
tenv node instr_ref typestate1 exp1 Typ.void TypeOrigin.Undef loc1) node instr_ref typestate1 exp1 Typ.void TypeOrigin.Undef loc1)
(* Handle Preconditions.checkNotNull. *) (* Handle Preconditions.checkNotNull. *)
@ -559,7 +559,7 @@ let do_preconditions_check_state instr_ref idenv tenv curr_pname curr_annotated_
(* Handle m.put(k,v) as assignment pvar = v for the pvar associated to m.get(k) *) (* Handle m.put(k,v) as assignment pvar = v for the pvar associated to m.get(k) *)
let do_map_put call_params callee_pname tenv loc node curr_pname curr_pdesc calls_this checks let do_map_put call_params callee_pname tenv loc node curr_pname curr_pdesc calls_this checks
instr_ref ~is_strict_mode find_canonical_duplicate typestate' = instr_ref ~nullsafe_mode find_canonical_duplicate typestate' =
(* Get the proc name for map.get() from map.put() *) (* Get the proc name for map.get() from map.put() *)
let pname_get_from_pname_put pname_put = let pname_get_from_pname_put pname_put =
let object_t = Typ.Name.Java.Split.java_lang_object in let object_t = Typ.Name.Java.Split.java_lang_object in
@ -590,7 +590,7 @@ let do_map_put call_params callee_pname tenv loc node curr_pname curr_pdesc call
| Some map_get_str -> | Some map_get_str ->
let pvar_map_get = Pvar.mk (Mangled.from_string map_get_str) curr_pname in let pvar_map_get = Pvar.mk (Mangled.from_string map_get_str) curr_pname in
TypeState.add pvar_map_get TypeState.add pvar_map_get
(typecheck_expr_simple ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this (typecheck_expr_simple ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this
checks tenv node instr_ref typestate' exp_value typ_value TypeOrigin.Undef loc) checks tenv node instr_ref typestate' exp_value typ_value TypeOrigin.Undef loc)
typestate' typestate'
| None -> | None ->
@ -652,7 +652,7 @@ let normalize_cond_for_sil_prune idenv ~node cond =
let rec check_condition_for_sil_prune tenv idenv calls_this find_canonical_duplicate loc curr_pname let rec check_condition_for_sil_prune tenv idenv calls_this find_canonical_duplicate loc curr_pname
curr_pdesc curr_annotated_signature linereader typestate checks true_branch instr_ref curr_pdesc curr_annotated_signature linereader typestate checks true_branch instr_ref
~is_strict_mode ~original_node ~node c : TypeState.t = ~nullsafe_mode ~original_node ~node c : TypeState.t =
(* check if the expression is coming from a call, and return the argument *) (* check if the expression is coming from a call, and return the argument *)
let from_call filter_callee e : Exp.t option = let from_call filter_callee e : Exp.t option =
match e with match e with
@ -700,9 +700,8 @@ let rec check_condition_for_sil_prune tenv idenv calls_this find_canonical_dupli
let pvar = Pvar.mk (Mangled.from_string e_str) curr_pname in let pvar = Pvar.mk (Mangled.from_string e_str) curr_pname in
let e1 = Exp.Lvar pvar in let e1 = Exp.Lvar pvar in
let typ, ta = let typ, ta =
typecheck_expr_simple ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this typecheck_expr_simple ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this checks
checks tenv original_node instr_ref typestate e1 Typ.void TypeOrigin.OptimisticFallback tenv original_node instr_ref typestate e1 Typ.void TypeOrigin.OptimisticFallback loc
loc
in in
let range = (typ, ta) in let range = (typ, ta) in
let typestate1 = TypeState.add pvar range typestate in let typestate1 = TypeState.add pvar range typestate in
@ -734,8 +733,8 @@ let rec check_condition_for_sil_prune tenv idenv calls_this find_canonical_dupli
| Exp.BinOp (Binop.Eq, Exp.Const (Const.Cint i), e) | Exp.BinOp (Binop.Eq, Exp.Const (Const.Cint i), e)
| Exp.BinOp (Binop.Eq, e, Exp.Const (Const.Cint i)) | Exp.BinOp (Binop.Eq, e, Exp.Const (Const.Cint i))
when IntLit.iszero i -> ( when IntLit.iszero i -> (
typecheck_expr_for_errors ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this typecheck_expr_for_errors ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this checks
checks tenv original_node instr_ref typestate e loc ; tenv original_node instr_ref typestate e loc ;
let typestate1, e1, from_call = let typestate1, e1, from_call =
match from_is_true_on_null e with match from_is_true_on_null e with
| Some e1 -> | Some e1 ->
@ -748,7 +747,7 @@ let rec check_condition_for_sil_prune tenv idenv calls_this find_canonical_dupli
~original_node ~is_assignment:false e1 typestate1 loc ~original_node ~is_assignment:false e1 typestate1 loc
in in
let typ, inferred_nullability = let typ, inferred_nullability =
typecheck_expr_simple ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this checks typecheck_expr_simple ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this checks
tenv original_node instr_ref typestate2 e' Typ.void TypeOrigin.OptimisticFallback loc tenv original_node instr_ref typestate2 e' Typ.void TypeOrigin.OptimisticFallback loc
in in
if checks.eradicate then if checks.eradicate then
@ -764,8 +763,8 @@ let rec check_condition_for_sil_prune tenv idenv calls_this find_canonical_dupli
| Exp.BinOp (Binop.Ne, Exp.Const (Const.Cint i), e) | Exp.BinOp (Binop.Ne, Exp.Const (Const.Cint i), e)
| Exp.BinOp (Binop.Ne, e, Exp.Const (Const.Cint i)) | Exp.BinOp (Binop.Ne, e, Exp.Const (Const.Cint i))
when IntLit.iszero i -> ( when IntLit.iszero i -> (
typecheck_expr_for_errors ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this typecheck_expr_for_errors ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this checks
checks tenv original_node instr_ref typestate e loc ; tenv original_node instr_ref typestate e loc ;
let typestate1, e1, from_call = let typestate1, e1, from_call =
match from_instanceof e with match from_instanceof e with
| Some e1 -> | Some e1 ->
@ -784,7 +783,7 @@ let rec check_condition_for_sil_prune tenv idenv calls_this find_canonical_dupli
~original_node ~is_assignment:false e1 typestate1 loc ~original_node ~is_assignment:false e1 typestate1 loc
in in
let typ, inferred_nullability = let typ, inferred_nullability =
typecheck_expr_simple ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this checks typecheck_expr_simple ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this checks
tenv original_node instr_ref typestate2 e' Typ.void TypeOrigin.OptimisticFallback loc tenv original_node instr_ref typestate2 e' Typ.void TypeOrigin.OptimisticFallback loc
in in
if checks.eradicate then if checks.eradicate then
@ -801,12 +800,12 @@ let rec check_condition_for_sil_prune tenv idenv calls_this find_canonical_dupli
| Exp.UnOp (Unop.LNot, Exp.BinOp (Binop.Eq, e1, e2), _) -> | Exp.UnOp (Unop.LNot, Exp.BinOp (Binop.Eq, e1, e2), _) ->
check_condition_for_sil_prune tenv idenv calls_this find_canonical_duplicate loc curr_pname check_condition_for_sil_prune tenv idenv calls_this find_canonical_duplicate loc curr_pname
curr_pdesc curr_annotated_signature linereader typestate checks true_branch instr_ref curr_pdesc curr_annotated_signature linereader typestate checks true_branch instr_ref
~is_strict_mode ~original_node ~node ~nullsafe_mode ~original_node ~node
(Exp.BinOp (Binop.Ne, e1, e2)) (Exp.BinOp (Binop.Ne, e1, e2))
| Exp.UnOp (Unop.LNot, Exp.BinOp (Binop.Ne, e1, e2), _) -> | Exp.UnOp (Unop.LNot, Exp.BinOp (Binop.Ne, e1, e2), _) ->
check_condition_for_sil_prune tenv idenv calls_this find_canonical_duplicate loc curr_pname check_condition_for_sil_prune tenv idenv calls_this find_canonical_duplicate loc curr_pname
curr_pdesc curr_annotated_signature linereader typestate checks true_branch instr_ref curr_pdesc curr_annotated_signature linereader typestate checks true_branch instr_ref
~is_strict_mode ~original_node ~node ~nullsafe_mode ~original_node ~node
(Exp.BinOp (Binop.Eq, e1, e2)) (Exp.BinOp (Binop.Eq, e1, e2))
| _ -> | _ ->
(* TODO(T54687014): silenced warning may be an unsoundeness issue; investigate *) (* TODO(T54687014): silenced warning may be an unsoundeness issue; investigate *)
@ -841,11 +840,11 @@ let clarify_ret_by_propagates_nullable ret (resolved_params : EradicateChecks.re
let calc_typestate_after_call find_canonical_duplicate calls_this checks tenv idenv instr_ref let calc_typestate_after_call find_canonical_duplicate calls_this checks tenv idenv instr_ref
signature_params cflags call_params ~is_anonymous_inner_class_constructor signature_params cflags call_params ~is_anonymous_inner_class_constructor
~callee_annotated_signature ~callee_attributes ~callee_pname ~callee_pname_java ~curr_pname ~callee_annotated_signature ~callee_attributes ~callee_pname ~callee_pname_java ~curr_pname
~curr_pdesc ~curr_annotated_signature ~is_strict_mode ~typestate ~typestate1 loc node = ~curr_pdesc ~curr_annotated_signature ~nullsafe_mode ~typestate ~typestate1 loc node =
let resolve_param i (formal_param, actual_param) = let resolve_param i (formal_param, actual_param) =
let (orig_e2, e2), t2 = actual_param in let (orig_e2, e2), t2 = actual_param in
let _, inferred_nullability_actual = let _, inferred_nullability_actual =
typecheck_expr ~is_strict_mode find_canonical_duplicate calls_this checks tenv node instr_ref typecheck_expr ~nullsafe_mode find_canonical_duplicate calls_this checks tenv node instr_ref
curr_pdesc typestate e2 curr_pdesc typestate e2
(* TODO(T54687014) optimistic default might be an unsoundness issue - investigate *) (* TODO(T54687014) optimistic default might be an unsoundness issue - investigate *)
(t2, InferredNullability.create TypeOrigin.OptimisticFallback) (t2, InferredNullability.create TypeOrigin.OptimisticFallback)
@ -900,11 +899,11 @@ let calc_typestate_after_call find_canonical_duplicate calls_this checks tenv id
let typestate_after_call = let typestate_after_call =
if not is_anonymous_inner_class_constructor then ( if not is_anonymous_inner_class_constructor then (
if cflags.CallFlags.cf_virtual && checks.eradicate then if cflags.CallFlags.cf_virtual && checks.eradicate then
EradicateChecks.check_call_receiver ~is_strict_mode tenv find_canonical_duplicate curr_pdesc EradicateChecks.check_call_receiver ~nullsafe_mode tenv find_canonical_duplicate curr_pdesc
node typestate1 call_params callee_pname instr_ref loc node typestate1 call_params callee_pname instr_ref loc
(typecheck_expr ~is_strict_mode find_canonical_duplicate calls_this checks) ; (typecheck_expr ~nullsafe_mode find_canonical_duplicate calls_this checks) ;
if checks.eradicate then if checks.eradicate then
EradicateChecks.check_call_parameters ~is_strict_mode ~callee_annotated_signature tenv EradicateChecks.check_call_parameters ~nullsafe_mode ~callee_annotated_signature tenv
find_canonical_duplicate curr_pdesc node callee_attributes resolved_params loc instr_ref ; find_canonical_duplicate curr_pdesc node callee_attributes resolved_params loc instr_ref ;
if Models.is_check_not_null callee_pname then if Models.is_check_not_null callee_pname then
match Models.get_check_not_null_parameter callee_pname with match Models.get_check_not_null_parameter callee_pname with
@ -927,7 +926,7 @@ let calc_typestate_after_call find_canonical_duplicate calls_this checks tenv id
call_params loc node typestate1 call_params loc node typestate1
else if Models.is_mapPut callee_pname then else if Models.is_mapPut callee_pname then
do_map_put call_params callee_pname tenv loc node curr_pname curr_pdesc calls_this checks do_map_put call_params callee_pname tenv loc node curr_pname curr_pdesc calls_this checks
instr_ref ~is_strict_mode find_canonical_duplicate typestate1 instr_ref ~nullsafe_mode find_canonical_duplicate typestate1
else typestate1 ) else typestate1 )
else typestate1 else typestate1
in in
@ -936,7 +935,7 @@ let calc_typestate_after_call find_canonical_duplicate calls_this checks tenv id
(* SIL instruction in form of [ret = fun(args);] where fun is a non-builtin Java function *) (* SIL instruction in form of [ret = fun(args);] where fun is a non-builtin Java function *)
let typecheck_sil_call_function find_canonical_duplicate checks tenv instr_ref typestate idenv let typecheck_sil_call_function find_canonical_duplicate checks tenv instr_ref typestate idenv
~callee_pname ~curr_pname curr_pdesc curr_annotated_signature calls_this ~is_strict_mode ~callee_pname ~curr_pname curr_pdesc curr_annotated_signature calls_this ~nullsafe_mode
ret_id_typ etl_ loc callee_pname_java cflags node = ret_id_typ etl_ loc callee_pname_java cflags node =
let callee_attributes = let callee_attributes =
match PatternMatch.lookup_attributes tenv callee_pname with match PatternMatch.lookup_attributes tenv callee_pname with
@ -965,8 +964,8 @@ let typecheck_sil_call_function find_canonical_duplicate checks tenv instr_ref t
let etl = drop_unchecked_params calls_this curr_pname callee_attributes etl_ in let etl = drop_unchecked_params calls_this curr_pname callee_attributes etl_ in
let call_params, typestate1 = let call_params, typestate1 =
let handle_et (e1, t1) (etl1, typestate1) = let handle_et (e1, t1) (etl1, typestate1) =
typecheck_expr_for_errors ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this typecheck_expr_for_errors ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this checks
checks tenv node instr_ref typestate e1 loc ; tenv node instr_ref typestate e1 loc ;
let e2, typestate2 = let e2, typestate2 =
convert_complex_exp_to_pvar tenv idenv curr_pname curr_annotated_signature ~node convert_complex_exp_to_pvar tenv idenv curr_pname curr_annotated_signature ~node
~original_node:node ~is_assignment:false e1 typestate1 loc ~original_node:node ~is_assignment:false e1 typestate1 loc
@ -991,7 +990,7 @@ let typecheck_sil_call_function find_canonical_duplicate checks tenv instr_ref t
calc_typestate_after_call find_canonical_duplicate calls_this checks tenv idenv instr_ref calc_typestate_after_call find_canonical_duplicate calls_this checks tenv idenv instr_ref
signature_params cflags call_params ~is_anonymous_inner_class_constructor signature_params cflags call_params ~is_anonymous_inner_class_constructor
~callee_annotated_signature ~callee_attributes ~callee_pname ~callee_pname_java ~curr_pname ~callee_annotated_signature ~callee_attributes ~callee_pname ~callee_pname_java ~curr_pname
~curr_pdesc ~curr_annotated_signature ~is_strict_mode ~typestate ~typestate1 loc node ~curr_pdesc ~curr_annotated_signature ~nullsafe_mode ~typestate ~typestate1 loc node
in in
do_return finally_resolved_ret typestate_after_call do_return finally_resolved_ret typestate_after_call
@ -1004,7 +1003,7 @@ let typecheck_instr tenv calls_this checks (node : Procdesc.Node.t) idenv curr_p
let ret_pvar = Procdesc.get_ret_var curr_pdesc in let ret_pvar = Procdesc.get_ret_var curr_pdesc in
Pvar.equal pvar ret_pvar Pvar.equal pvar ret_pvar
in in
let is_strict_mode = curr_annotated_signature.is_strict_mode in let nullsafe_mode = curr_annotated_signature.nullsafe_mode in
match instr with match instr with
| Sil.Metadata (ExitScope (vars, _)) -> | Sil.Metadata (ExitScope (vars, _)) ->
List.fold_right vars ~init:typestate ~f:(fun var astate -> List.fold_right vars ~init:typestate ~f:(fun var astate ->
@ -1016,22 +1015,22 @@ let typecheck_instr tenv calls_this checks (node : Procdesc.Node.t) idenv curr_p
| Sil.Metadata (Abstract _ | Nullify _ | Skip | VariableLifetimeBegins _) -> | Sil.Metadata (Abstract _ | Nullify _ | Skip | VariableLifetimeBegins _) ->
typestate typestate
| Sil.Load {id; e; typ; loc} -> | Sil.Load {id; e; typ; loc} ->
typecheck_expr_for_errors ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this typecheck_expr_for_errors ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this checks
checks tenv node instr_ref typestate e loc ; tenv node instr_ref typestate e loc ;
let e', typestate' = let e', typestate' =
convert_complex_exp_to_pvar tenv idenv curr_pname curr_annotated_signature ~node convert_complex_exp_to_pvar tenv idenv curr_pname curr_annotated_signature ~node
~original_node:node ~is_assignment:false e typestate loc ~original_node:node ~is_assignment:false e typestate loc
in in
TypeState.add_id id TypeState.add_id id
(typecheck_expr_simple ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this checks (typecheck_expr_simple ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this checks
tenv node instr_ref typestate' e' typ TypeOrigin.Undef loc) tenv node instr_ref typestate' e' typ TypeOrigin.Undef loc)
typestate' typestate'
| Sil.Store {e1= Exp.Lvar pvar; e2= Exp.Exn _} when is_return pvar -> | Sil.Store {e1= Exp.Lvar pvar; e2= Exp.Exn _} when is_return pvar ->
(* skip assignment to return variable where it is an artifact of a throw instruction *) (* skip assignment to return variable where it is an artifact of a throw instruction *)
typestate typestate
| Sil.Store {e1; typ; e2; loc} -> | Sil.Store {e1; typ; e2; loc} ->
typecheck_expr_for_errors ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this typecheck_expr_for_errors ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this checks
checks tenv node instr_ref typestate e1 loc ; tenv node instr_ref typestate e1 loc ;
let e1', typestate1 = let e1', typestate1 =
convert_complex_exp_to_pvar tenv idenv curr_pname curr_annotated_signature ~node convert_complex_exp_to_pvar tenv idenv curr_pname curr_annotated_signature ~node
~original_node:node ~is_assignment:true e1 typestate loc ~original_node:node ~is_assignment:true e1 typestate loc
@ -1041,9 +1040,9 @@ let typecheck_instr tenv calls_this checks (node : Procdesc.Node.t) idenv curr_p
| Exp.Lfield (_, fn, f_typ) -> | Exp.Lfield (_, fn, f_typ) ->
let field_type_opt = AnnotatedField.get tenv fn f_typ in let field_type_opt = AnnotatedField.get tenv fn f_typ in
if checks.eradicate then if checks.eradicate then
EradicateChecks.check_field_assignment ~is_strict_mode tenv find_canonical_duplicate EradicateChecks.check_field_assignment ~nullsafe_mode tenv find_canonical_duplicate
curr_pdesc node instr_ref typestate1 e1' e2 typ loc fn field_type_opt curr_pdesc node instr_ref typestate1 e1' e2 typ loc fn field_type_opt
(typecheck_expr ~is_strict_mode find_canonical_duplicate calls_this checks tenv) (typecheck_expr ~nullsafe_mode find_canonical_duplicate calls_this checks tenv)
| _ -> | _ ->
() ()
in in
@ -1051,7 +1050,7 @@ let typecheck_instr tenv calls_this checks (node : Procdesc.Node.t) idenv curr_p
match e1' with match e1' with
| Exp.Lvar pvar -> | Exp.Lvar pvar ->
TypeState.add pvar TypeState.add pvar
(typecheck_expr_simple ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this (typecheck_expr_simple ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this
checks tenv node instr_ref typestate1 e2 typ TypeOrigin.Undef loc) checks tenv node instr_ref typestate1 e2 typ TypeOrigin.Undef loc)
typestate1 typestate1
| Exp.Lfield _ -> | Exp.Lfield _ ->
@ -1068,29 +1067,29 @@ let typecheck_instr tenv calls_this checks (node : Procdesc.Node.t) idenv curr_p
(* Type cast *) (* Type cast *)
| Sil.Call ((id, _), Exp.Const (Const.Cfun pn), (e, typ) :: _, loc, _) | Sil.Call ((id, _), Exp.Const (Const.Cfun pn), (e, typ) :: _, loc, _)
when Procname.equal pn BuiltinDecl.__cast -> when Procname.equal pn BuiltinDecl.__cast ->
typecheck_expr_for_errors ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this typecheck_expr_for_errors ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this checks
checks tenv node instr_ref typestate e loc ; tenv node instr_ref typestate e loc ;
let e', typestate' = let e', typestate' =
convert_complex_exp_to_pvar tenv idenv curr_pname curr_annotated_signature ~node convert_complex_exp_to_pvar tenv idenv curr_pname curr_annotated_signature ~node
~original_node:node ~is_assignment:false e typestate loc ~original_node:node ~is_assignment:false e typestate loc
in in
(* cast copies the type of the first argument *) (* cast copies the type of the first argument *)
TypeState.add_id id TypeState.add_id id
(typecheck_expr_simple ~is_strict_mode find_canonical_duplicate curr_pdesc calls_this checks (typecheck_expr_simple ~nullsafe_mode find_canonical_duplicate curr_pdesc calls_this checks
tenv node instr_ref typestate' e' typ TypeOrigin.OptimisticFallback loc) tenv node instr_ref typestate' e' typ TypeOrigin.OptimisticFallback loc)
typestate' typestate'
(* myarray.length *) (* myarray.length *)
| Sil.Call ((id, _), Exp.Const (Const.Cfun pn), [(array_exp, t)], loc, _) | Sil.Call ((id, _), Exp.Const (Const.Cfun pn), [(array_exp, t)], loc, _)
when Procname.equal pn BuiltinDecl.__get_array_length -> when Procname.equal pn BuiltinDecl.__get_array_length ->
let _, ta = let _, ta =
typecheck_expr ~is_strict_mode find_canonical_duplicate calls_this checks tenv node typecheck_expr ~nullsafe_mode find_canonical_duplicate calls_this checks tenv node instr_ref
instr_ref curr_pdesc typestate array_exp curr_pdesc typestate array_exp
(* TODO(T54687014) optimistic default might be an unsoundness issue - investigate *) (* TODO(T54687014) optimistic default might be an unsoundness issue - investigate *)
(t, InferredNullability.create TypeOrigin.OptimisticFallback) (t, InferredNullability.create TypeOrigin.OptimisticFallback)
loc loc
in in
if checks.eradicate then if checks.eradicate then
EradicateChecks.check_object_dereference ~is_strict_mode tenv find_canonical_duplicate EradicateChecks.check_object_dereference ~nullsafe_mode tenv find_canonical_duplicate
curr_pdesc node instr_ref array_exp DereferenceRule.ArrayLengthAccess ta loc ; curr_pdesc node instr_ref array_exp DereferenceRule.ArrayLengthAccess ta loc ;
TypeState.add_id id TypeState.add_id id
(Typ.mk (Tint Typ.IInt), InferredNullability.create TypeOrigin.ArrayLengthResult) (Typ.mk (Tint Typ.IInt), InferredNullability.create TypeOrigin.ArrayLengthResult)
@ -1106,7 +1105,7 @@ let typecheck_instr tenv calls_this checks (node : Procdesc.Node.t) idenv curr_p
, loc , loc
, cflags ) -> , cflags ) ->
typecheck_sil_call_function find_canonical_duplicate checks tenv instr_ref typestate idenv typecheck_sil_call_function find_canonical_duplicate checks tenv instr_ref typestate idenv
~callee_pname ~curr_pname curr_pdesc curr_annotated_signature calls_this ~is_strict_mode ~callee_pname ~curr_pname curr_pdesc curr_annotated_signature calls_this ~nullsafe_mode
ret_id_typ etl_ loc callee_pname_java cflags node ret_id_typ etl_ loc callee_pname_java cflags node
(* Calls instruction that is not a function call *) (* Calls instruction that is not a function call *)
| Sil.Call _ -> | Sil.Call _ ->
@ -1119,7 +1118,7 @@ let typecheck_instr tenv calls_this checks (node : Procdesc.Node.t) idenv curr_p
let node', normalized_cond = normalize_cond_for_sil_prune idenv ~node cond in let node', normalized_cond = normalize_cond_for_sil_prune idenv ~node cond in
check_condition_for_sil_prune tenv idenv calls_this find_canonical_duplicate loc curr_pname check_condition_for_sil_prune tenv idenv calls_this find_canonical_duplicate loc curr_pname
curr_pdesc curr_annotated_signature linereader typestate checks true_branch instr_ref curr_pdesc curr_annotated_signature linereader typestate checks true_branch instr_ref
~is_strict_mode ~node:node' ~original_node:node normalized_cond ~nullsafe_mode ~node:node' ~original_node:node normalized_cond
(** Typecheck the instructions in a cfg node. *) (** Typecheck the instructions in a cfg node. *)

@ -65,7 +65,7 @@ type err_instance =
; violation_type: InheritanceRule.violation_type ; violation_type: InheritanceRule.violation_type
; base_proc_name: Procname.t ; base_proc_name: Procname.t
; overridden_proc_name: Procname.t } ; overridden_proc_name: Procname.t }
| Field_not_initialized of {is_strict_mode: bool; field_name: Fieldname.t} | Field_not_initialized of {nullsafe_mode: NullsafeMode.t; field_name: Fieldname.t}
| Over_annotation of | Over_annotation of
{ over_annotated_violation: OverAnnotatedRule.violation { over_annotated_violation: OverAnnotatedRule.violation
; violation_type: OverAnnotatedRule.violation_type } ; violation_type: OverAnnotatedRule.violation_type }
@ -194,9 +194,8 @@ module Severity = struct
Some Exceptions.Advice Some Exceptions.Advice
| Over_annotation _ -> | Over_annotation _ ->
None None
| Field_not_initialized {is_strict_mode} -> | Field_not_initialized {nullsafe_mode} ->
(* TODO: show strict mode violations as errors *) Some (NullsafeMode.severity nullsafe_mode)
Some (if is_strict_mode then Exceptions.Error else Exceptions.Warning)
| Bad_assignment {assignment_violation} -> | Bad_assignment {assignment_violation} ->
Some (AssignmentRule.violation_severity assignment_violation) Some (AssignmentRule.violation_severity assignment_violation)
| Inconsistent_subclass {inheritance_violation} -> | Inconsistent_subclass {inheritance_violation} ->

@ -41,7 +41,7 @@ type err_instance =
; violation_type: InheritanceRule.violation_type ; violation_type: InheritanceRule.violation_type
; base_proc_name: Procname.t ; base_proc_name: Procname.t
; overridden_proc_name: Procname.t } ; overridden_proc_name: Procname.t }
| Field_not_initialized of {is_strict_mode: bool; field_name: Fieldname.t} | Field_not_initialized of {nullsafe_mode: NullsafeMode.t; field_name: Fieldname.t}
| Over_annotation of | Over_annotation of
{ over_annotated_violation: OverAnnotatedRule.violation { over_annotated_violation: OverAnnotatedRule.violation
; violation_type: OverAnnotatedRule.violation_type } ; violation_type: OverAnnotatedRule.violation_type }

Loading…
Cancel
Save