Skip to content

Commit

Permalink
[flow] Specialized implementation for identifier type synthesis in cl…
Browse files Browse the repository at this point in the history
…ass extends

Summary:
The extends clause in class, although being an expression, is more annotation-like. We made this decision during LTI development so that we can tolerate more cyclic class definitions in the most common cases.

In the LTI 2.0 system, all the annotations will be resolved lazily all at once at the end of component resolution. Early forcing is not allowed, otherwise it will result in internal error. Currently, class extends' identifier are evaluated eagarly due to repositioning. We can achieve the same using AnnotT, and avoid the eagar repositioning. Using AnnotT to achieve repositioning effect is already used extensively in type_annotation and type_sig_merge when we are refering to a type identifier.

Changelog: [internal]

Reviewed By: panagosg7

Differential Revision: D55296799

fbshipit-source-id: d9d035750e81d58eca4befdf1f947719779187f0
  • Loading branch information
SamChou19815 authored and facebook-github-bot committed Mar 26, 2024
1 parent 4e16d4f commit 3e01314
Show file tree
Hide file tree
Showing 8 changed files with 34 additions and 12 deletions.
4 changes: 2 additions & 2 deletions src/typing/statement.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6490,8 +6490,8 @@ module Make
let open Ast.Expression in
let rec super_expr (loc, expr) =
match expr with
| Identifier (id_loc, id) ->
let t = identifier cx id id_loc in
| Identifier (id_loc, ({ Ast.Identifier.name; comments = _ } as id)) ->
let t = Type_env.sig_var_ref cx (OrdinaryName name) id_loc in
(t, (fun () -> ((loc, t), Identifier ((id_loc, t), id))))
| Member
{
Expand Down
9 changes: 9 additions & 0 deletions src/typing/type_env.ml
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,15 @@ let var_ref ?(lookup_mode = ForValue) cx ?desc name loc =
let t = query_var ~lookup_mode cx name ?desc loc in
Flow_js.reposition cx loc t

let sig_var_ref ?(lookup_mode = ForValue) cx ?desc name loc =
let desc =
match desc with
| Some desc -> desc
| None -> RIdentifier name
in
let reason = mk_reason desc loc in
AnnotT (reason, query_var cx ~lookup_mode name loc, true)

let read_class_self_type cx loc =
match checked_find_loc_env_write_opt cx Env_api.ClassSelfLoc loc with
| Some t -> t
Expand Down
8 changes: 8 additions & 0 deletions src/typing/type_env.mli
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ val var_ref :
ALoc.t ->
Type.t

val sig_var_ref :
?lookup_mode:LookupMode.t ->
Context.t ->
?desc:Reason.reason_desc ->
Reason.name ->
ALoc.t ->
Type.t

val intrinsic_ref :
Context.t -> ?desc:Reason.reason_desc -> Reason.name -> ALoc.t -> (Type.t * ALoc.t) option

Expand Down
4 changes: 4 additions & 0 deletions tests/autocomplete/autocomplete.exp
Original file line number Diff line number Diff line change
Expand Up @@ -2679,6 +2679,10 @@ class_declaration_name.js:5:8
Flags: --pretty
{"result":[]}

class_extends.js:5:20
Flags: --pretty
{"result":[{"name":"Foo","type":"class Foo"},{"name":"function","type":""}]}

pattern_object_key_middle.js:6:12
Flags: --pretty
{"result":[{"name":"foobar","type":"string"}]}
Expand Down
6 changes: 6 additions & 0 deletions tests/autocomplete/class_extends.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// @flow

class Foo {}

class Bar extends F
// ^
1 change: 1 addition & 0 deletions tests/autocomplete/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ queries_in_file autocomplete "enums.js" --lsp
queries_in_file autocomplete "enum-key.js" --lsp
queries_in_file autocomplete "enum-id.js" --pretty
queries_in_file autocomplete "class_declaration_name.js" --pretty
queries_in_file autocomplete "class_extends.js" --pretty
queries_in_file autocomplete "pattern_object_key_middle.js" --pretty
queries_in_file autocomplete "iterator.js" --lsp
queries_in_file autocomplete "indexed-access-1.js" --lsp
Expand Down
7 changes: 2 additions & 5 deletions tests/extends/extends.exp
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,16 @@ References:

Error ---------------------------------------------------------------------------------------------------- test.js:30:17

Cannot extend `D` [1] with `obj` because object type [2] is not inheritable. [incompatible-use]
Cannot extend `D` [1] with `obj` because `obj` [2] is not inheritable. [incompatible-use]

test.js:30:17
30| class D extends obj {}
^^^
^^^ [2]

References:
test.js:30:7
30| class D extends obj {}
^ [1]
test.js:29:18
29| declare var obj: {};
^^ [2]



Expand Down
7 changes: 2 additions & 5 deletions tests/rec/rec.exp
Original file line number Diff line number Diff line change
Expand Up @@ -339,20 +339,17 @@ References:

Error ----------------------------------------------------------------------------------------------- this_subst.js:1:53

Cannot extend `InstrumentedContainer` [1] with `container` because uninitialized variable [2] is not inheritable.
Cannot extend `InstrumentedContainer` [1] with `container` because `container` [2] is not inheritable.
[incompatible-use]

this_subst.js:1:53
1| var container = class InstrumentedContainer extends container {
^^^^^^^^^
^^^^^^^^^ [2]

References:
this_subst.js:1:23
1| var container = class InstrumentedContainer extends container {
^^^^^^^^^^^^^^^^^^^^^ [1]
this_subst.js:1:5
1| var container = class InstrumentedContainer extends container {
^^^^^^^^^ [2]



Expand Down

0 comments on commit 3e01314

Please sign in to comment.