Skip to content

Commit 811b6e7

Browse files
stroxlerfacebook-github-bot
authored andcommitted
Infer: improve the type specificity in TypeInferenceData
Summary: It came up in review of a separate diff that our types did not clearly express that attributes and globals always have nonmissing annotations. This diff fixes that by separating optional type annotations from required ones. It's a little ugly to need a type synonym for `Type.t`, but as far as I can tell from skimming the docs there's no way to get a derived `to_yojson` otherwise, and if the choice is between a type synonym or a bunch of hand-rolled json serialization I think the former is better. Reviewed By: dkgi Differential Revision: D28939568 fbshipit-source-id: ffd76acd4a123cd9b6c9fbe297d7046c8c95ec6f
1 parent 5c0e371 commit 811b6e7

File tree

2 files changed

+60
-47
lines changed

2 files changed

+60
-47
lines changed

source/interprocedural_analyses/type_inference/test/typeInferenceLocalTest.ml

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -141,19 +141,23 @@ let check_inference_results ~context ~checks source =
141141
Memory.reset_shared_memory ()
142142

143143

144+
let get_inferred = function
145+
| TypeAnnotation.Inferred inferred -> Some inferred
146+
| TypeAnnotation.Given _
147+
| TypeAnnotation.Missing ->
148+
None
149+
150+
144151
let test_inferred_returns context =
145152
let check_return_annotation ~define_name ~expected source =
146-
let check
147-
( { LocalResult.define = { DefineAnnotation.return = { TypeAnnotation.inferred; _ }; _ }; _ }
148-
as result )
149-
=
153+
let check ({ LocalResult.define = { DefineAnnotation.return; _ }; _ } as result) =
150154
Asserts.assert_inference_result
151155
~context
152156
~result
153157
~details:"Checking inferred return annotation"
154158
~source
155159
~expected:(Some expected)
156-
~actual:inferred
160+
~actual:(get_inferred return)
157161
in
158162
check_inference_results ~context ~checks:[Setup.make_function define_name, check] source
159163
in
@@ -170,7 +174,7 @@ let test_inferred_parameters context =
170174
let open DefineAnnotation.Parameters in
171175
let check_parameter_annotation ~define_name ~parameter_name ~expected source =
172176
let check ({ LocalResult.define = { DefineAnnotation.parameters; _ }; _ } as result) =
173-
let { Value.annotation = { TypeAnnotation.inferred; _ }; _ } =
177+
let { Value.annotation; _ } =
174178
Asserts.find_by_name ("$parameter$" ^ parameter_name) parameters
175179
in
176180
Asserts.assert_inference_result
@@ -179,7 +183,7 @@ let test_inferred_parameters context =
179183
~details:("Checking inferred annotation for parameter " ^ parameter_name)
180184
~source
181185
~expected:(Some expected)
182-
~actual:inferred
186+
~actual:(get_inferred annotation)
183187
in
184188
check_inference_results ~context ~checks:[Setup.make_function define_name, check] source
185189
in
@@ -197,16 +201,14 @@ let test_inferred_globals context =
197201
let check_global_annotation ~define_name ~global_name ~expected source =
198202
let open GlobalAnnotation in
199203
let check ({ LocalResult.globals; _ } as result) =
200-
let { Value.annotation = { TypeAnnotation.inferred; _ }; _ } =
201-
Asserts.find_by_name global_name globals
202-
in
204+
let { Value.annotation; _ } = Asserts.find_by_name global_name globals in
203205
Asserts.assert_inference_result
204206
~context
205207
~result
206208
~details:("Checking inferred annotation for global " ^ global_name)
207209
~source
208210
~expected:(Some expected)
209-
~actual:inferred
211+
~actual:(Some annotation)
210212
in
211213
check_inference_results ~context ~checks:[Setup.make_function define_name, check] source
212214
in
@@ -223,16 +225,14 @@ let test_inferred_attributes context =
223225
let check_attribute_annotation ~define_name ~attribute_name ~expected source =
224226
let open AttributeAnnotation in
225227
let check ({ LocalResult.attributes; _ } as result) =
226-
let { Value.annotation = { TypeAnnotation.inferred; _ }; _ } =
227-
Asserts.find_by_name attribute_name attributes
228-
in
228+
let { Value.annotation; _ } = Asserts.find_by_name attribute_name attributes in
229229
Asserts.assert_inference_result
230230
~context
231231
~result
232232
~details:("Checking inferred annotation for attribute " ^ attribute_name)
233233
~source
234234
~expected:(Some expected)
235-
~actual:inferred
235+
~actual:(Some annotation)
236236
in
237237
check_inference_results ~context ~checks:[Setup.make_function define_name, check] source
238238
in

source/interprocedural_analyses/type_inference/typeInferenceData.ml

Lines changed: 45 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -64,43 +64,56 @@ module AnnotationLocation = struct
6464
create ~lookup ~qualifier ~line
6565
end
6666

67+
module SerializableType = struct
68+
type t = Type.t [@@deriving show, eq]
69+
70+
let to_yojson type_ = `String (type_to_string type_)
71+
end
72+
6773
module TypeAnnotation = struct
68-
type t = {
69-
inferred: Type.t option;
70-
given: Type.t option;
71-
}
74+
type t =
75+
| Inferred of SerializableType.t
76+
| Given of SerializableType.t
77+
| Missing
7278
[@@deriving show, eq]
7379

74-
let is_inferred annotation = Option.is_some annotation.inferred
80+
let is_inferred = function
81+
| Inferred _ -> true
82+
| Given _
83+
| Missing ->
84+
false
7585

76-
let combine_with ~f left right =
77-
{
78-
inferred =
79-
( match left.inferred, right.inferred with
80-
| Some left, Some right -> Some (f left right)
81-
| None, right -> right
82-
| left, None -> left );
83-
given = (if Option.is_some left.given then left.given else right.given);
84-
}
8586

87+
let from_given ~global_resolution expression =
88+
let parser = GlobalResolution.annotation_parser global_resolution in
89+
match expression >>| parser.parse_annotation with
90+
| Some type_ -> Given type_
91+
| None -> Missing
8692

87-
let join ~global_resolution = combine_with ~f:(GlobalResolution.join global_resolution)
8893

89-
let meet ~global_resolution = combine_with ~f:(GlobalResolution.meet global_resolution)
94+
let from_inferred type_ = Inferred type_
95+
96+
let merge ~f left right =
97+
match left, right with
98+
| Inferred left, Inferred right -> Inferred (f left right)
99+
| Inferred type_, _
100+
| _, Inferred type_ ->
101+
Inferred type_
102+
| Given type_, _
103+
| _, Given type_ ->
104+
Given type_
105+
| Missing, Missing -> Missing
90106

91-
let from_given ~global_resolution given =
92-
let parser = GlobalResolution.annotation_parser global_resolution in
93-
let given = given >>| parser.parse_annotation in
94-
{ inferred = None; given }
95107

108+
let join ~global_resolution = merge ~f:(GlobalResolution.join global_resolution)
96109

97-
let from_inferred inferred = { inferred = Some inferred; given = None }
110+
let meet ~global_resolution = merge ~f:(GlobalResolution.meet global_resolution)
98111

99-
let to_yojson { inferred; given } =
100-
match inferred, given with
101-
| Some inferred, _ -> `String (type_to_string inferred)
102-
| None, Some given -> `String (type_to_string given)
103-
| _ -> `Null
112+
let to_yojson = function
113+
| Inferred type_
114+
| Given type_ ->
115+
SerializableType.to_yojson type_
116+
| Missing -> `Null
104117
end
105118

106119
module AnnotationsByName = struct
@@ -182,7 +195,7 @@ module GlobalAnnotation = struct
182195
type t = {
183196
name: SerializableReference.t;
184197
location: AnnotationLocation.t;
185-
annotation: TypeAnnotation.t;
198+
annotation: SerializableType.t;
186199
}
187200
[@@deriving show, eq, to_yojson]
188201

@@ -199,7 +212,7 @@ module GlobalAnnotation = struct
199212
let combine ~global_resolution left right =
200213
{
201214
left with
202-
annotation = TypeAnnotation.join ~global_resolution left.annotation right.annotation;
215+
annotation = GlobalResolution.join global_resolution left.annotation right.annotation;
203216
}
204217
end
205218

@@ -213,7 +226,7 @@ module AttributeAnnotation = struct
213226
parent: SerializableReference.t;
214227
name: SerializableReference.t;
215228
location: AnnotationLocation.t;
216-
annotation: TypeAnnotation.t;
229+
annotation: SerializableType.t;
217230
}
218231
[@@deriving show, eq, to_yojson]
219232

@@ -230,7 +243,7 @@ module AttributeAnnotation = struct
230243
let combine ~global_resolution left right =
231244
{
232245
left with
233-
annotation = TypeAnnotation.join ~global_resolution left.annotation right.annotation;
246+
annotation = GlobalResolution.join global_resolution left.annotation right.annotation;
234247
}
235248
end
236249

@@ -412,7 +425,7 @@ module LocalResult = struct
412425
{
413426
parent = type_to_reference parent;
414427
name;
415-
annotation = TypeAnnotation.from_inferred type_;
428+
annotation = type_;
416429
location = error.location |> AnnotationLocation.from_location_with_module ~lookup;
417430
};
418431
}
@@ -425,7 +438,7 @@ module LocalResult = struct
425438
globals
426439
{
427440
name;
428-
annotation = TypeAnnotation.from_inferred type_;
441+
annotation = type_;
429442
location = error.location |> AnnotationLocation.from_location_with_module ~lookup;
430443
};
431444
}

0 commit comments

Comments
 (0)