Skip to content

Commit 07978dc

Browse files
sinancepelfacebook-github-bot
authored andcommitted
purge protocols per handle
Summary: We had a bug where we were never removing elements from the master list of protocols. This meant that if you registered a class as a protocol and then removed the protocol superclass, Pyre would still think of it as a protocol. To prevent the issue, keep track of protocols as a set and remove protocols per handle in the `purge` function. Moved the DependencyHandler since we're relying on it to register protocols now. Caught by the consistency checker. Reviewed By: dkgi Differential Revision: D14736415 fbshipit-source-id: 7beb9cf6869515b43c9f5c435bb854cd85da84f5
1 parent 50cd2c6 commit 07978dc

File tree

9 files changed

+166
-74
lines changed

9 files changed

+166
-74
lines changed

analysis/dependencies.ml

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type index = {
1515
alias_keys: (Type.t Hash_set.t) File.Handle.Table.t;
1616
global_keys: (Reference.t Hash_set.t) File.Handle.Table.t;
1717
dependent_keys: (Reference.t Hash_set.t) File.Handle.Table.t;
18+
protocol_keys: (Type.t Hash_set.t) File.Handle.Table.t;
1819
}
1920

2021

@@ -30,6 +31,7 @@ module type Handler = sig
3031
val add_alias_key: handle: File.Handle.t -> Type.t -> unit
3132
val add_global_key: handle: File.Handle.t -> Reference.t -> unit
3233
val add_dependent_key: handle: File.Handle.t -> Reference.t -> unit
34+
val add_protocol_key: handle: File.Handle.t -> Type.t -> unit
3335

3436
val add_dependent: handle: File.Handle.t -> Reference.t -> unit
3537
val dependents: Reference.t -> File.Handle.Set.Tree.t option
@@ -39,6 +41,7 @@ module type Handler = sig
3941
val get_alias_keys: handle: File.Handle.t -> Type.t list
4042
val get_global_keys: handle: File.Handle.t -> Reference.t list
4143
val get_dependent_keys: handle: File.Handle.t -> Reference.t list
44+
val get_protocol_keys: handle: File.Handle.t -> Type.t list
4245

4346
val clear_keys_batch: File.Handle.t list -> unit
4447

@@ -47,7 +50,7 @@ end
4750

4851

4952
let handler {
50-
index = { function_keys; class_keys; alias_keys; global_keys; dependent_keys };
53+
index = { function_keys; class_keys; alias_keys; global_keys; dependent_keys; protocol_keys };
5154
dependents;
5255
} =
5356
(module struct
@@ -105,6 +108,15 @@ let handler {
105108
| Some hash_set ->
106109
Hash_set.add hash_set dependent
107110

111+
let add_protocol_key ~handle protocol =
112+
match Hashtbl.find protocol_keys handle with
113+
| None ->
114+
Hashtbl.set
115+
protocol_keys
116+
~key:handle
117+
~data:(Type.Hash_set.of_list [protocol])
118+
| Some hash_set ->
119+
Hash_set.add hash_set protocol
108120

109121
let add_dependent ~handle dependent =
110122
add_dependent_key ~handle dependent;
@@ -154,12 +166,19 @@ let handler {
154166
|> Option.value ~default:[]
155167

156168

169+
let get_protocol_keys ~handle =
170+
Hashtbl.find protocol_keys handle
171+
>>| Hash_set.to_list
172+
|> Option.value ~default:[]
173+
174+
157175
let clear_keys_batch handles =
158176
List.iter ~f:(Hashtbl.remove function_keys) handles;
159177
List.iter ~f:(Hashtbl.remove class_keys) handles;
160178
List.iter ~f:(Hashtbl.remove alias_keys) handles;
161179
List.iter ~f:(Hashtbl.remove global_keys) handles;
162-
List.iter ~f:(Hashtbl.remove dependent_keys) handles
180+
List.iter ~f:(Hashtbl.remove dependent_keys) handles;
181+
List.iter ~f:(Hashtbl.remove protocol_keys) handles
163182

164183

165184
let normalize handles =
@@ -186,13 +205,14 @@ let create () =
186205
alias_keys = File.Handle.Table.create ();
187206
global_keys = File.Handle.Table.create ();
188207
dependent_keys = File.Handle.Table.create ();
208+
protocol_keys = File.Handle.Table.create ();
189209
}
190210
in
191211
{ index = index; dependents = Reference.Table.create () }
192212

193213

194214
let copy {
195-
index = { function_keys; class_keys; alias_keys; global_keys; dependent_keys };
215+
index = { function_keys; class_keys; alias_keys; global_keys; dependent_keys; protocol_keys };
196216
dependents } =
197217
{
198218
index = {
@@ -201,6 +221,7 @@ let copy {
201221
alias_keys = Hashtbl.copy alias_keys;
202222
global_keys = Hashtbl.copy global_keys;
203223
dependent_keys = Hashtbl.copy dependent_keys;
224+
protocol_keys = Hashtbl.copy protocol_keys;
204225
};
205226
dependents = Hashtbl.copy dependents;
206227
}

analysis/dependencies.mli

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type index = {
1414
alias_keys: (Type.t Hash_set.t) File.Handle.Table.t;
1515
global_keys: (Reference.t Hash_set.t) File.Handle.Table.t;
1616
dependent_keys: (Reference.t Hash_set.t) File.Handle.Table.t;
17+
protocol_keys: (Type.t Hash_set.t) File.Handle.Table.t;
1718
}
1819

1920
type t = {
@@ -27,6 +28,7 @@ module type Handler = sig
2728
val add_alias_key: handle: File.Handle.t -> Type.t -> unit
2829
val add_global_key: handle: File.Handle.t -> Reference.t -> unit
2930
val add_dependent_key: handle: File.Handle.t -> Reference.t -> unit
31+
val add_protocol_key: handle: File.Handle.t -> Type.t -> unit
3032

3133
val add_dependent: handle: File.Handle.t -> Reference.t -> unit
3234

@@ -37,6 +39,7 @@ module type Handler = sig
3739
val get_alias_keys: handle: File.Handle.t -> Type.t list
3840
val get_global_keys: handle: File.Handle.t -> Reference.t list
3941
val get_dependent_keys: handle: File.Handle.t -> Reference.t list
42+
val get_protocol_keys: handle: File.Handle.t -> Type.t list
4043

4144
val clear_keys_batch: File.Handle.t list -> unit
4245

analysis/environment.ml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ module type Handler = sig
3535

3636
val class_definition: Type.t -> Resolution.class_representation option
3737

38-
val register_protocol: Type.t -> unit
38+
val register_protocol: handle: File.Handle.t -> Type.t -> unit
3939
val protocols: unit -> Type.t list
4040

4141
val register_module
@@ -269,6 +269,8 @@ let handler
269269
|> purge_table_given_keys globals;
270270
List.concat_map ~f:(fun handle -> DependencyHandler.get_dependent_keys ~handle) handles
271271
|> purge_dependents;
272+
List.concat_map ~f:(fun handle -> DependencyHandler.get_protocol_keys ~handle) handles
273+
|> List.iter ~f:(Hash_set.remove protocols);
272274
DependencyHandler.clear_keys_batch handles;
273275
List.map handles ~f:(fun handle -> Source.qualifier ~handle)
274276
|> List.iter ~f:(Hashtbl.remove modules);
@@ -281,7 +283,8 @@ let handler
281283
let class_definition =
282284
Hashtbl.find class_definitions
283285

284-
let register_protocol protocol =
286+
let register_protocol ~handle protocol =
287+
DependencyHandler.add_protocol_key ~handle protocol;
285288
Hash_set.add protocols protocol
286289

287290
let protocols () =
@@ -403,7 +406,9 @@ let register_class_definitions (module Handler: Handler) source =
403406
let annotated = Annotated.Class.create { Node.location; value = definition } in
404407

405408
if Annotated.Class.is_protocol annotated then
406-
Handler.register_protocol primitive;
409+
begin
410+
Handler.register_protocol ~handle primitive
411+
end;
407412

408413
Handler.set_class_definition
409414
~primitive

analysis/environment.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ module type Handler = sig
3636

3737
val class_definition: Type.t -> Resolution.class_representation option
3838

39-
val register_protocol: Type.t -> unit
39+
val register_protocol: handle: File.Handle.t -> Type.t -> unit
4040
val protocols: unit -> Type.t list
4141

4242
val register_module

analysis/test/environmentTest.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,6 +1490,7 @@ let test_purge _ =
14901490
let ((module Handler: Environment.Handler) as handler) = Environment.handler environment in
14911491
let source = {|
14921492
import a
1493+
class P(typing.Protocol): pass
14931494
class baz.baz(): pass
14941495
_T = typing.TypeVar("_T")
14951496
x = 5
@@ -1511,11 +1512,15 @@ let test_purge _ =
15111512
assert_equal
15121513
(dependencies "a.py")
15131514
(Some ["test.py"]);
1515+
assert_equal
1516+
(Handler.protocols ())
1517+
[Type.Primitive "P"];
15141518
15151519
Handler.purge [File.Handle.create "test.py"];
15161520
15171521
assert_is_none (Handler.class_definition (Type.Primitive "baz.baz"));
15181522
assert_is_none (Handler.aliases (Type.Primitive "_T"));
1523+
assert_equal (Handler.protocols ()) [];
15191524
assert_equal
15201525
(dependencies "a.py")
15211526
(Some [])

server/request.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,7 @@ let process_type_query_request ~state:({ State.environment; _ } as state) ~confi
626626
actual_key = Int.to_string key;
627627
actual_value =
628628
value
629+
>>| Type.Set.Tree.to_list
629630
>>| List.to_string ~f:Type.show;
630631
}
631632
| Ok (FunctionKeys.Decoded (key, value)) ->

0 commit comments

Comments
 (0)