Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework module resolution #11168

Merged
merged 57 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
7fa5696
start on m.module_resolution
Simn Apr 19, 2023
caef2fd
support static inits
Simn Apr 19, 2023
a01743c
finish module_globals removal
Simn Apr 19, 2023
742d2cd
remove wildcard_packages
Simn Apr 19, 2023
7c7853c
get cursed resolution tests to pass
Simn Apr 19, 2023
44f7230
add some debug and a test of the current behavior (see #9197)
Simn Apr 19, 2023
6d5bfa4
remove early import resolving and fix python test
Simn Apr 20, 2023
0b9637d
turn into class
Simn Apr 20, 2023
bd8e5dc
add RLazy
Simn Apr 20, 2023
daa6bc2
(finally) remove context_init
Simn Apr 20, 2023
7585e5b
don't expand for type lookups
Simn Apr 20, 2023
1d97c94
fix 2/3 of broken display test
Simn Apr 20, 2023
dbfd99c
rename some things
Simn Apr 20, 2023
662a226
make immutable
Simn Apr 20, 2023
e0fd468
add own_resolution
Simn Apr 20, 2023
b1f3dc1
avoid some duplicate lookuppery
Simn Apr 20, 2023
4055247
distinguish class and abstract statics
Simn Apr 20, 2023
3709de7
move enum expansion to resolution_list
Simn Apr 20, 2023
0a0da53
move to own module
Simn Apr 20, 2023
a675ed2
add test for alias conflict
Simn Apr 20, 2023
67bae47
add test
Simn Apr 20, 2023
d142d76
add actual resolve method and try some caching
Simn Apr 20, 2023
19d27a1
Merge branch 'development' into module_resolution
Simn Apr 20, 2023
2737e97
Merge branch 'development' into module_resolution
Simn Apr 20, 2023
382269a
change expected enum typing
Simn Apr 21, 2023
419d254
Merge branch 'development' into module_resolution
Simn Apr 21, 2023
bb9c70f
try something different
Simn Apr 22, 2023
fe2bdfe
merge aliases into resolution_kind
Simn Apr 22, 2023
f73bcb2
remove add_l
Simn Apr 22, 2023
408440e
Merge branch 'development' into module_resolution
Simn Apr 22, 2023
949ef84
add some timers and a type import cache
Simn Apr 22, 2023
0472886
deal with weirdness
Simn Apr 22, 2023
888ebce
Merge branch 'development' into module_resolution
Simn Apr 24, 2023
f718a81
Merge branch 'development' into module_resolution
Simn Apr 26, 2023
08e179a
Merge branch 'development' into module_resolution
Simn Apr 28, 2023
3f41919
remove weird import lookup
Simn Apr 28, 2023
ff2c6d6
meh
Simn Apr 28, 2023
1ee74fb
asdfg
Simn Apr 28, 2023
01df50e
Merge branch 'development' into module_resolution
Simn May 3, 2023
04d38cb
keep weird handling for now to have CI green
Simn May 4, 2023
de52786
investigate
Simn May 5, 2023
935946b
add timer for flush_pass
Simn May 5, 2023
2e58fc4
Merge branch 'development' into module_resolution
Simn May 6, 2023
1c49717
add absurd amount of timers
Simn May 6, 2023
48c9c96
Merge branch 'development' into module_resolution
Simn May 10, 2023
7a88ce4
Revert "add absurd amount of timers"
Simn May 10, 2023
b6a4112
Revert "add timer for flush_pass"
Simn May 10, 2023
8197349
Revert "investigate"
Simn May 10, 2023
c86a360
Merge branch 'development' into module_resolution
Simn May 30, 2023
f0b0447
Merge branch 'development' into module_resolution
Simn Jun 26, 2023
2bc367f
Merge branch 'development' into module_resolution
Simn Jul 8, 2023
864210b
Merge branch 'development' into module_resolution
Simn Jul 12, 2023
307c94c
fix test
Simn Jul 12, 2023
eb3ca18
Merge branch 'development' into module_resolution
Simn Sep 25, 2023
65d7a0a
Remove unused open
kLabz Sep 28, 2023
dad1f5f
Merge branch 'development' into module_resolution
Simn Oct 19, 2023
f096714
remove timers
Simn Oct 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions src/compiler/retyper.ml
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,13 @@ let pair_class_field rctx ctx cctx fctx cf cff p =
remove_class_field_flag cf CfPostProcessed;
)

let pair_classes rctx context_init c d p =
let pair_classes rctx c d p =
let rctx = {rctx with
print_stack = (Printf.sprintf "[Class %s]" (s_type_path c.cl_path)) :: rctx.print_stack
} in
c.cl_restore();
(* TODO: What do we do with build macros? *)
let cctx = create_class_context c context_init p in
let cctx = create_class_context c p in
let ctx = create_typer_context_for_class rctx.typer cctx p in
let _ =
let rctx = {rctx with
Expand Down Expand Up @@ -180,14 +180,14 @@ let pair_typedefs ctx rctx td d =
ignore (disable_typeloading rctx ctx (fun () -> Typeload.load_complex_type ctx false d.d_data));
[]

let pair_abstracts ctx rctx context_init a d p =
let pair_abstracts ctx rctx a d p =
let rctx = {rctx with
print_stack = (Printf.sprintf "[Abstract %s]" (s_type_path a.a_path)) :: rctx.print_stack
} in
match a.a_impl with
| Some c ->
c.cl_restore();
let cctx = create_class_context c context_init p in
let cctx = create_class_context c p in
let ctx = create_typer_context_for_class rctx.typer cctx p in
let fl = List.map (fun cff ->
let cff = TypeloadFields.transform_abstract_field2 ctx a cff in
Expand Down Expand Up @@ -218,7 +218,6 @@ let attempt_retyping ctx m p =
print_stack = [Printf.sprintf "[Module %s]" (s_type_path m.m_path)];
} in
(* log rctx 0 (Printf.sprintf "Retyping module %s" (s_type_path m.m_path)); *)
let context_init = new TypeloadFields.context_init in
let find_type name = try
List.find (fun t -> snd (t_infos t).mt_path = name) ctx.m.curmod.m_types
with Not_found ->
Expand All @@ -230,11 +229,11 @@ let attempt_retyping ctx m p =
| (d,p) :: decls ->
begin match d with
| EImport (path,mode) ->
ImportHandling.init_import ctx context_init path mode p;
ImportHandling.init_import ctx path mode p;
ImportHandling.commit_import ctx path mode p;
loop acc decls
| EUsing path ->
ImportHandling.init_using ctx context_init path p;
ImportHandling.init_using ctx path p;
loop acc decls
| EClass c ->
let mt = find_type (fst c.d_name) in
Expand All @@ -257,18 +256,17 @@ let attempt_retyping ctx m p =
let pairs = loop [] decls in
let fl = List.map (fun (d,mt) -> match d,mt with
| EClass d,TClassDecl c ->
pair_classes rctx context_init c d p
pair_classes rctx c d p
| EEnum d,TEnumDecl en ->
pair_enums ctx rctx en d
| ETypedef d,TTypeDecl td ->
pair_typedefs ctx rctx td d
| EAbstract d,TAbstractDecl a ->
pair_abstracts ctx rctx context_init a d p
pair_abstracts ctx rctx a d p
| _ ->
fail rctx "?"
) pairs in
(* If we get here we know that the everything is ok. *)
delay ctx PConnectField (fun () -> context_init#run);
List.iter (fun fl ->
List.iter (fun f -> f()) fl
) fl;
Expand Down
11 changes: 11 additions & 0 deletions src/context/display/displayEmitter.ml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ let symbol_of_module_type = function
| TTypeDecl td -> SKTypedef td
| TAbstractDecl a -> SKAbstract a

let display_alias ctx name t p = match ctx.com.display.dms_kind with
| DMDefinition | DMTypeDefinition ->
raise_positions [p];
| DMUsage _ | DMImplementation ->
ReferencePosition.set (name,p,SKOther)
| DMHover ->
let ct = CompletionType.from_type (get_import_status ctx) t in
raise_hover (make_ci_literal name (t,ct)) None p
| _ ->
()

let display_module_type ctx mt p = match ctx.com.display.dms_kind with
| DMDefinition | DMTypeDefinition ->
begin match mt with
Expand Down
3 changes: 1 addition & 2 deletions src/context/display/displayTexpr.ml
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ let find_abstract_by_position decls p =
loop decls

let actually_check_display_field ctx c cff p =
let context_init = new TypeloadFields.context_init in
let cctx = TypeloadFields.create_class_context c context_init p in
let cctx = TypeloadFields.create_class_context c p in
let ctx = TypeloadFields.create_typer_context_for_class ctx cctx p in
let cff = TypeloadFields.transform_field (ctx,cctx) c cff (ref []) (pos cff.cff_name) in
let display_modifier = Typeload.check_field_access ctx cff in
Expand Down
8 changes: 4 additions & 4 deletions src/context/display/displayToplevel.ml
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ module CollectionContext = struct
Shadowed
with Not_found ->
let check_wildcard () =
List.exists (fun (sl,_) -> (sl,snd path) = path) ctx.ctx.m.wildcard_packages
List.exists (fun (sl,_) -> (sl,snd path) = path) ctx.ctx.m.import_resolution#extract_wildcard_packages
in
if is_import || (fst path = []) || check_wildcard () then Imported else Unimported

Expand Down Expand Up @@ -377,7 +377,7 @@ let collect ctx tk with_type sort =
()
in
List.iter enum_ctors ctx.m.curmod.m_types;
List.iter enum_ctors (List.map fst ctx.m.module_imports);
List.iter enum_ctors (List.map fst ctx.m.import_resolution#extract_type_imports);

(* enum constructors of expected type *)
begin match with_type with
Expand Down Expand Up @@ -414,7 +414,7 @@ let collect ctx tk with_type sort =
| _ -> raise Not_found
with Not_found ->
()
) ctx.m.module_globals;
) ctx.m.import_resolution#extract_field_imports;

(* literals *)
add (make_ci_literal "null" (tpair t_dynamic)) (Some "null");
Expand Down Expand Up @@ -459,7 +459,7 @@ let collect ctx tk with_type sort =
List.iter add_type ctx.m.curmod.m_types;

(* module imports *)
List.iter add_type (List.rev_map fst ctx.m.module_imports); (* reverse! *)
List.iter add_type (List.rev_map fst ctx.m.import_resolution#extract_type_imports); (* reverse! *)

(* types from files *)
let cs = ctx.com.cs in
Expand Down
110 changes: 58 additions & 52 deletions src/context/display/importHandling.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ open Common
open Type
open Error
open Typecore
open Resolution

type import_display_kind =
| IDKPackage of string list
Expand Down Expand Up @@ -61,7 +62,7 @@ let commit_import ctx path mode p =
ctx.m.import_statements <- (path,mode) :: ctx.m.import_statements;
if Filename.basename p.pfile <> "import.hx" then add_import_position ctx p path

let init_import ctx context_init path mode p =
let init_import ctx path mode p =
let rec loop acc = function
| x :: l when is_lower_ident (fst x) -> loop (x::acc) l
| rest -> List.rev acc, rest
Expand All @@ -71,7 +72,7 @@ let init_import ctx context_init path mode p =
| [] ->
(match mode with
| IAll ->
ctx.m.wildcard_packages <- (List.map fst pack,p) :: ctx.m.wildcard_packages
ctx.m.import_resolution#add (wildcard_package_resolution (List.map fst pack) p)
| _ ->
(match List.rev path with
(* p spans `import |` (to the display position), so we take the pmax here *)
Expand All @@ -82,7 +83,7 @@ let init_import ctx context_init path mode p =
let p_type = punion p1 p2 in
let md = ctx.g.do_load_module ctx (List.map fst pack,tname) p_type in
let types = md.m_types in
let no_private (t,_) = not (t_infos t).mt_private in
let not_private mt = not (t_infos mt).mt_private in
let error_private p = raise_typing_error "Importing private declarations from a module is not allowed" p in
let chk_private t p = if ctx.m.curmod != (t_infos t).mt_module && (t_infos t).mt_private then error_private p in
let has_name name t = snd (t_infos t).mt_path = name in
Expand All @@ -109,66 +110,70 @@ let init_import ctx context_init path mode p =
chk_private t p_type;
t
in
let rebind t name p =
let check_alias mt name pname =
if not (name.[0] >= 'A' && name.[0] <= 'Z') then
raise_typing_error "Type aliases must start with an uppercase letter" p;
let _, _, f = ctx.g.do_build_instance ctx t p_type in
(* create a temp private typedef, does not register it in module *)
let t_path = (fst md.m_path @ ["_" ^ snd md.m_path],name) in
let t_type = f (extract_param_types (t_infos t).mt_params) in
let mt = TTypeDecl {(mk_typedef ctx.m.curmod t_path p p t_type) with
t_private = true;
t_params = (t_infos t).mt_params
} in
if ctx.is_display_file && DisplayPosition.display_position#enclosed_in p then
DisplayEmitter.display_module_type ctx mt p;
mt
raise_typing_error "Type aliases must start with an uppercase letter" pname;
if ctx.is_display_file && DisplayPosition.display_position#enclosed_in pname then
DisplayEmitter.display_alias ctx name (type_of_module_type mt) pname;
in
let add_static_init t name s =
let name = (match name with None -> s | Some (n,_) -> n) in
match resolve_typedef t with
| TClassDecl c | TAbstractDecl {a_impl = Some c} ->
| TClassDecl c ->
ignore(c.cl_build());
ignore(PMap.find s c.cl_statics);
ctx.m.module_globals <- PMap.add name (TClassDecl c,s,p) ctx.m.module_globals
| TEnumDecl e ->
ignore(PMap.find s e.e_constrs);
ctx.m.module_globals <- PMap.add name (TEnumDecl e,s,p) ctx.m.module_globals
let cf = PMap.find s c.cl_statics in
static_field_resolution c cf name p
| TAbstractDecl ({a_impl = Some c} as a) ->
ignore(c.cl_build());
let cf = PMap.find s c.cl_statics in
static_abstract_field_resolution a c cf name p
| TEnumDecl en ->
let ef = PMap.find s en.e_constrs in
enum_constructor_resolution en ef name p
| _ ->
raise Not_found
in
let add_lazy_resolution f =
ctx.m.import_resolution#add (lazy_resolution f)
in
(match mode with
| INormal | IAsName _ ->
let name = (match mode with IAsName n -> Some n | _ -> None) in
(match rest with
| [] ->
(match name with
begin match name with
| None ->
ctx.m.module_imports <- List.filter no_private (List.map (fun t -> t,p) types) @ ctx.m.module_imports;
List.iter (fun mt ->
if not_private mt then
ctx.m.import_resolution#add (module_type_resolution mt None p)
) (List.rev types);
Option.may (fun c ->
context_init#add (fun () ->
ignore(c.cl_build());
List.iter (fun cf ->
if has_class_field_flag cf CfPublic then
ctx.m.module_globals <- PMap.add cf.cf_name (TClassDecl c,cf.cf_name,p) ctx.m.module_globals
) c.cl_ordered_statics
);
ctx.m.import_resolution#add (class_statics_resolution c p)
) md.m_statics
| Some(newname,pname) ->
ctx.m.module_imports <- (rebind (get_type tname) newname pname,p) :: ctx.m.module_imports);
let mt = get_type tname in
check_alias mt newname pname;
ctx.m.import_resolution#add (module_type_resolution mt (Some newname) p2)
end
| [tsub,p2] ->
let pu = punion p1 p2 in
(try
let tsub = List.find (has_name tsub) types in
chk_private tsub pu;
ctx.m.module_imports <- ((match name with None -> tsub | Some(n,pname) -> rebind tsub n pname),p) :: ctx.m.module_imports
let alias = match name with
| None ->
None
| Some(name,pname) ->
check_alias tsub name pname;
Some name
in
ctx.m.import_resolution#add (module_type_resolution tsub alias p2);
with Not_found ->
(* this might be a static property, wait later to check *)
let find_main_type_static () =
try
let tmain = find_type tname in
begin try
add_static_init tmain name tsub
Some (add_static_init tmain (Option.map fst name) tsub)
with Not_found ->
let parent,target_kind,candidates = match resolve_typedef tmain with
| TClassDecl c ->
Expand All @@ -189,13 +194,13 @@ let init_import ctx context_init path mode p =
(* TODO: cleaner way to get module fields? *)
PMap.foldi (fun n _ acc -> n :: acc) (try (Option.get md.m_statics).cl_statics with | _ -> PMap.empty) []
in

display_error ctx.com (StringError.string_error tsub candidates (parent ^ " has no " ^ target_kind ^ " " ^ tsub)) p
display_error ctx.com (StringError.string_error tsub candidates (parent ^ " has no " ^ target_kind ^ " " ^ tsub)) p;
None
end
with Not_found ->
fail_usefully tsub p
in
context_init#add (fun() ->
add_lazy_resolution (fun() ->
match md.m_statics with
| Some c ->
(try
Expand All @@ -208,8 +213,7 @@ let init_import ctx context_init path mode p =
if not (has_class_field_flag cf CfPublic) then
error_private p
else
let imported_name = match name with None -> tsub | Some (n,pname) -> n in
ctx.m.module_globals <- PMap.add imported_name (TClassDecl c,tsub,p) ctx.m.module_globals;
Some (static_field_resolution c cf (Option.map fst name) p)
else
loop rest
in
Expand All @@ -225,11 +229,12 @@ let init_import ctx context_init path mode p =
| [] -> ()
| (n,p) :: _ -> raise_typing_error ("Unexpected " ^ n) p);
let tsub = get_type tsub in
context_init#add (fun() ->
add_lazy_resolution (fun() ->
try
add_static_init tsub name fname
Some (add_static_init tsub (Option.map fst name) fname)
with Not_found ->
display_error ctx.com (s_type_path (t_infos tsub).mt_path ^ " has no field " ^ fname) (punion p p3)
display_error ctx.com (s_type_path (t_infos tsub).mt_path ^ " has no field " ^ fname) (punion p p3);
None
);
)
| IAll ->
Expand All @@ -238,14 +243,13 @@ let init_import ctx context_init path mode p =
| [tsub,_] -> get_type tsub
| _ :: (n,p) :: _ -> raise_typing_error ("Unexpected " ^ n) p
) in
context_init#add (fun() ->
add_lazy_resolution (fun() ->
match resolve_typedef t with
| TClassDecl c
| TAbstractDecl {a_impl = Some c} ->
ignore(c.cl_build());
PMap.iter (fun _ cf -> if not (has_meta Meta.NoImportGlobal cf.cf_meta) then ctx.m.module_globals <- PMap.add cf.cf_name (TClassDecl c,cf.cf_name,p) ctx.m.module_globals) c.cl_statics
| TEnumDecl e ->
PMap.iter (fun _ c -> if not (has_meta Meta.NoImportGlobal c.ef_meta) then ctx.m.module_globals <- PMap.add c.ef_name (TEnumDecl e,c.ef_name,p) ctx.m.module_globals) e.e_constrs
Some (class_statics_resolution c p)
| TEnumDecl en ->
Some (enum_statics_resolution en p)
| _ ->
raise_typing_error "No statics to import from this type" p
)
Expand All @@ -270,7 +274,6 @@ let handle_using ctx path p =
let t = ctx.g.do_load_type_def ctx p t in
[t]
) in
(* delay the using since we need to resolve typedefs *)
let filter_classes types =
let rec loop acc types = match types with
| td :: l ->
Expand All @@ -286,8 +289,11 @@ let handle_using ctx path p =
in
types,filter_classes

let init_using ctx context_init path p =
let init_using ctx path p =
let types,filter_classes = handle_using ctx path p in
(* do the import first *)
ctx.m.module_imports <- (List.map (fun t -> t,p) types) @ ctx.m.module_imports;
context_init#add (fun() -> ctx.m.module_using <- filter_classes types @ ctx.m.module_using)
List.iter (fun mt ->
ctx.m.import_resolution#add (module_type_resolution mt None p)
) (List.rev types);
(* delay the using since we need to resolve typedefs *)
delay_late ctx PConnectField (fun () -> ctx.m.module_using <- filter_classes types @ ctx.m.module_using)
Loading