[infer] Distinguish dummy struct types from normal ones when merging tenv

Summary:
Some field types of structs are missing in Java. The reason is:

* When capture, empty struct types are added without their fields.
* The empty struct types are overwritten to the global tenv when merging all tenvs.

As a fix, this diff add a boolean field, `dummy`, in `Typ.Struct.t`, then avoids that non-dummy types are replaced by dummy types.

Reviewed By: ngorogiannis

Differential Revision: D18657323

fbshipit-source-id: 4a263f8e7
master
Sungkeun Cho 5 years ago committed by Facebook Github Bot
parent ff819da3c6
commit 6885fb4256

@ -29,10 +29,11 @@ let pp fmt (tenv : t) =
let create () = TypenameHash.create 1000 let create () = TypenameHash.create 1000
(** Construct a struct type in a type environment *) (** Construct a struct type in a type environment *)
let mk_struct tenv ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots name = let mk_struct tenv ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots ?dummy
name =
let struct_typ = let struct_typ =
Typ.Struct.internal_mk_struct ?default ?fields ?statics ?methods ?exported_objc_methods ?supers Typ.Struct.internal_mk_struct ?default ?fields ?statics ?methods ?exported_objc_methods ?supers
?annots () ?annots ?dummy ()
in in
TypenameHash.replace tenv name struct_typ ; TypenameHash.replace tenv name struct_typ ;
struct_typ struct_typ
@ -99,7 +100,13 @@ module SQLite : SqliteUtils.Data with type t = per_file = struct
FileLocal (Serializer.deserialize blob) FileLocal (Serializer.deserialize blob)
end end
let merge ~src ~dst = TypenameHash.iter (fun pname cfg -> TypenameHash.replace dst pname cfg) src let merge ~src ~dst =
TypenameHash.iter
(fun pname cfg ->
if (not (Typ.Struct.is_dummy cfg)) || not (TypenameHash.mem dst pname) then
TypenameHash.replace dst pname cfg )
src
let merge_per_file ~src ~dst = let merge_per_file ~src ~dst =
match (src, dst) with match (src, dst) with

@ -41,6 +41,7 @@ val mk_struct :
-> ?exported_objc_methods:Typ.Procname.t list -> ?exported_objc_methods:Typ.Procname.t list
-> ?supers:Typ.Name.t list -> ?supers:Typ.Name.t list
-> ?annots:Annot.Item.t -> ?annots:Annot.Item.t
-> ?dummy:bool
-> Typ.Name.t -> Typ.Name.t
-> Typ.Struct.t -> Typ.Struct.t
(** Construct a struct_typ, normalizing field types *) (** Construct a struct_typ, normalizing field types *)

@ -1518,7 +1518,8 @@ module Struct = struct
; supers: Name.t list (** superclasses *) ; supers: Name.t list (** superclasses *)
; methods: Procname.t list (** methods defined *) ; methods: Procname.t list (** methods defined *)
; exported_objc_methods: Procname.t list (** methods in ObjC interface, subset of [methods] *) ; exported_objc_methods: Procname.t list (** methods in ObjC interface, subset of [methods] *)
; annots: Annot.Item.t (** annotations *) } ; annots: Annot.Item.t (** annotations *)
; dummy: bool (** dummy struct for class including static method *) }
type lookup = Name.t -> t option type lookup = Name.t -> t option
@ -1554,21 +1555,22 @@ module Struct = struct
let internal_mk_struct ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots let internal_mk_struct ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots
() = ?dummy () =
let default_ = let default_ =
{ fields= [] { fields= []
; statics= [] ; statics= []
; methods= [] ; methods= []
; exported_objc_methods= [] ; exported_objc_methods= []
; supers= [] ; supers= []
; annots= Annot.Item.empty } ; annots= Annot.Item.empty
; dummy= false }
in in
let mk_struct_ ?(default = default_) ?(fields = default.fields) ?(statics = default.statics) let mk_struct_ ?(default = default_) ?(fields = default.fields) ?(statics = default.statics)
?(methods = default.methods) ?(exported_objc_methods = default.exported_objc_methods) ?(methods = default.methods) ?(exported_objc_methods = default.exported_objc_methods)
?(supers = default.supers) ?(annots = default.annots) () = ?(supers = default.supers) ?(annots = default.annots) ?(dummy = default.dummy) () =
{fields; statics; methods; exported_objc_methods; supers; annots} {fields; statics; methods; exported_objc_methods; supers; annots; dummy}
in in
mk_struct_ ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots () mk_struct_ ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots ?dummy ()
(** the element typ of the final extensible array in the given typ, if any *) (** the element typ of the final extensible array in the given typ, if any *)
@ -1617,4 +1619,7 @@ module Struct = struct
None ) None )
| _ -> | _ ->
None None
let is_dummy {dummy} = dummy
end end

@ -697,7 +697,8 @@ module Struct : sig
; supers: Name.t list (** supers *) ; supers: Name.t list (** supers *)
; methods: Procname.t list (** methods defined *) ; methods: Procname.t list (** methods defined *)
; exported_objc_methods: Procname.t list (** methods in ObjC interface, subset of [methods] *) ; exported_objc_methods: Procname.t list (** methods in ObjC interface, subset of [methods] *)
; annots: Annot.Item.t (** annotations *) } ; annots: Annot.Item.t (** annotations *)
; dummy: bool (** dummy struct for class including static method *) }
type lookup = Name.t -> t option type lookup = Name.t -> t option
@ -714,6 +715,7 @@ module Struct : sig
-> ?exported_objc_methods:Procname.t list -> ?exported_objc_methods:Procname.t list
-> ?supers:Name.t list -> ?supers:Name.t list
-> ?annots:Annot.Item.t -> ?annots:Annot.Item.t
-> ?dummy:bool
-> unit -> unit
-> t -> t
(** Construct a struct_typ, normalizing field types *) (** Construct a struct_typ, normalizing field types *)
@ -728,4 +730,6 @@ module Struct : sig
val get_field_type_and_annotation : val get_field_type_and_annotation :
lookup:lookup -> Fieldname.t -> typ -> (typ * Annot.Item.t) option lookup:lookup -> Fieldname.t -> typ -> (typ * Annot.Item.t) option
(** Return the type of the field [fn] and its annotation, None if [typ] has no field named [fn] *) (** Return the type of the field [fn] and its annotation, None if [typ] has no field named [fn] *)
val is_dummy : t -> bool
end end

@ -339,12 +339,12 @@ and get_class_struct_typ =
| Some struct_typ -> | Some struct_typ ->
struct_typ struct_typ
| None when JBasics.ClassSet.mem cn !seen -> | None when JBasics.ClassSet.mem cn !seen ->
Tenv.mk_struct tenv name Tenv.mk_struct ~dummy:true tenv name
| None -> ( | None -> (
seen := JBasics.ClassSet.add cn !seen ; seen := JBasics.ClassSet.add cn !seen ;
match JClasspath.lookup_node cn program with match JClasspath.lookup_node cn program with
| None -> | None ->
Tenv.mk_struct tenv name Tenv.mk_struct ~dummy:true tenv name
| Some node -> | Some node ->
let create_super_list interface_names = let create_super_list interface_names =
List.iter ~f:(fun cn -> ignore (get_class_struct_typ program tenv cn)) interface_names ; List.iter ~f:(fun cn -> ignore (get_class_struct_typ program tenv cn)) interface_names ;

Loading…
Cancel
Save