[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
(** 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 =
Typ.Struct.internal_mk_struct ?default ?fields ?statics ?methods ?exported_objc_methods ?supers
?annots ()
?annots ?dummy ()
in
TypenameHash.replace tenv name struct_typ ;
struct_typ
@ -99,7 +100,13 @@ module SQLite : SqliteUtils.Data with type t = per_file = struct
FileLocal (Serializer.deserialize blob)
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 =
match (src, dst) with

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

@ -1518,7 +1518,8 @@ module Struct = struct
; supers: Name.t list (** superclasses *)
; methods: Procname.t list (** methods defined *)
; 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
@ -1554,21 +1555,22 @@ module Struct = struct
let internal_mk_struct ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots
() =
?dummy () =
let default_ =
{ fields= []
; statics= []
; methods= []
; exported_objc_methods= []
; supers= []
; annots= Annot.Item.empty }
; annots= Annot.Item.empty
; dummy= false }
in
let mk_struct_ ?(default = default_) ?(fields = default.fields) ?(statics = default.statics)
?(methods = default.methods) ?(exported_objc_methods = default.exported_objc_methods)
?(supers = default.supers) ?(annots = default.annots) () =
{fields; statics; methods; exported_objc_methods; supers; annots}
?(supers = default.supers) ?(annots = default.annots) ?(dummy = default.dummy) () =
{fields; statics; methods; exported_objc_methods; supers; annots; dummy}
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 *)
@ -1617,4 +1619,7 @@ module Struct = struct
None )
| _ ->
None
let is_dummy {dummy} = dummy
end

@ -697,7 +697,8 @@ module Struct : sig
; supers: Name.t list (** supers *)
; methods: Procname.t list (** methods defined *)
; 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
@ -714,6 +715,7 @@ module Struct : sig
-> ?exported_objc_methods:Procname.t list
-> ?supers:Name.t list
-> ?annots:Annot.Item.t
-> ?dummy:bool
-> unit
-> t
(** Construct a struct_typ, normalizing field types *)
@ -728,4 +730,6 @@ module Struct : sig
val get_field_type_and_annotation :
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] *)
val is_dummy : t -> bool
end

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

Loading…
Cancel
Save