Skip to content

Commit 5d92829

Browse files
committed
Refactor type substitution inside extractRecordType.
This reveals one record case that is not handled.
1 parent bbf68d0 commit 5d92829

File tree

1 file changed

+60
-56
lines changed

1 file changed

+60
-56
lines changed

analysis/src/CompletionBackEnd.ml

Lines changed: 60 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -980,13 +980,70 @@ let findLocalCompletionsWithOpens ~pos ~(env : QueryEnv.t) ~prefix ~exact ~opens
980980
(* There's no local completion for fields *)
981981
[]
982982

983+
let instantiateType ~typeParams ~typeArgs (t : Types.type_expr) =
984+
if typeParams = [] || typeArgs = [] then t
985+
else
986+
let rec applySub tp ta t =
987+
match (tp, ta) with
988+
| t1 :: tRest1, t2 :: tRest2 ->
989+
if t1 = t then t2 else applySub tRest1 tRest2 t
990+
| [], _ | _, [] -> assert false
991+
in
992+
let rec loop (t : Types.type_expr) =
993+
match t.desc with
994+
| Tlink t -> loop t
995+
| Tvar _ -> applySub typeParams typeArgs t
996+
| Tunivar _ -> t
997+
| Tconstr (path, args, memo) ->
998+
{t with desc = Tconstr (path, args |> List.map loop, memo)}
999+
| Tsubst t -> loop t
1000+
| Tvariant rd -> {t with desc = Tvariant (rowDesc rd)}
1001+
| Tnil -> t
1002+
| Tarrow (lbl, t1, t2, c) ->
1003+
{t with desc = Tarrow (lbl, loop t1, loop t2, c)}
1004+
| Ttuple tl -> {t with desc = Ttuple (tl |> List.map loop)}
1005+
| Tobject (t, r) -> {t with desc = Tobject (loop t, r)}
1006+
| Tfield (n, k, t1, t2) -> {t with desc = Tfield (n, k, loop t1, loop t2)}
1007+
| Tpoly (t, []) -> loop t
1008+
| Tpoly (t, tl) -> {t with desc = Tpoly (loop t, tl |> List.map loop)}
1009+
| Tpackage (p, l, tl) ->
1010+
{t with desc = Tpackage (p, l, tl |> List.map loop)}
1011+
and rowDesc (rd : Types.row_desc) =
1012+
let row_fields =
1013+
rd.row_fields |> List.map (fun (l, rf) -> (l, rowField rf))
1014+
in
1015+
let row_more = loop rd.row_more in
1016+
let row_name =
1017+
match rd.row_name with
1018+
| None -> None
1019+
| Some (p, tl) -> Some (p, tl |> List.map loop)
1020+
in
1021+
{rd with row_fields; row_more; row_name}
1022+
and rowField (rf : Types.row_field) =
1023+
match rf with
1024+
| Rpresent None -> rf
1025+
| Rpresent (Some t) -> Rpresent (Some (loop t))
1026+
| Reither (b1, tl, b2, r) -> Reither (b1, tl |> List.map loop, b2, r)
1027+
| Rabsent -> Rabsent
1028+
in
1029+
loop t
1030+
9831031
let rec extractRecordType ~env ~package (t : Types.type_expr) =
9841032
match t.desc with
9851033
| Tlink t1 | Tsubst t1 | Tpoly (t1, []) -> extractRecordType ~env ~package t1
986-
| Tconstr (path, args, _) -> (
1034+
| Tconstr (path, typeArgs, _) -> (
9871035
match References.digConstructor ~env ~package path with
9881036
| Some (env, ({item = {kind = Record fields}} as typ)) ->
989-
Some (env, fields, typ, args)
1037+
let typeParams = typ.item.decl.type_params in
1038+
let fields =
1039+
fields
1040+
|> List.map (fun field ->
1041+
let fieldTyp =
1042+
field.typ |> instantiateType ~typeParams ~typeArgs
1043+
in
1044+
{field with typ = fieldTyp})
1045+
in
1046+
Some (env, fields, typ)
9901047
| Some (env, {item = {decl = {type_manifest = Some t1}}}) ->
9911048
extractRecordType ~env ~package t1
9921049
| _ -> None)
@@ -1087,54 +1144,6 @@ let completionsGetTypeEnv = function
10871144
| {Completion.kind = Field ({typ}, _); env} :: _ -> Some (typ, env)
10881145
| _ -> None
10891146

1090-
let instantiateType ~typeParams ~typeArgs (t : Types.type_expr) =
1091-
if typeParams = [] || typeArgs = [] then t
1092-
else
1093-
let rec applySub tp ta t =
1094-
match (tp, ta) with
1095-
| t1 :: tRest1, t2 :: tRest2 ->
1096-
if t1 = t then t2 else applySub tRest1 tRest2 t
1097-
| [], _ | _, [] -> assert false
1098-
in
1099-
let rec loop (t : Types.type_expr) =
1100-
match t.desc with
1101-
| Tlink t -> loop t
1102-
| Tvar _ -> applySub typeParams typeArgs t
1103-
| Tunivar _ -> t
1104-
| Tconstr (path, args, memo) ->
1105-
{t with desc = Tconstr (path, args |> List.map loop, memo)}
1106-
| Tsubst t -> loop t
1107-
| Tvariant rd -> {t with desc = Tvariant (rowDesc rd)}
1108-
| Tnil -> t
1109-
| Tarrow (lbl, t1, t2, c) ->
1110-
{t with desc = Tarrow (lbl, loop t1, loop t2, c)}
1111-
| Ttuple tl -> {t with desc = Ttuple (tl |> List.map loop)}
1112-
| Tobject (t, r) -> {t with desc = Tobject (loop t, r)}
1113-
| Tfield (n, k, t1, t2) -> {t with desc = Tfield (n, k, loop t1, loop t2)}
1114-
| Tpoly (t, []) -> loop t
1115-
| Tpoly (t, tl) -> {t with desc = Tpoly (loop t, tl |> List.map loop)}
1116-
| Tpackage (p, l, tl) ->
1117-
{t with desc = Tpackage (p, l, tl |> List.map loop)}
1118-
and rowDesc (rd : Types.row_desc) =
1119-
let row_fields =
1120-
rd.row_fields |> List.map (fun (l, rf) -> (l, rowField rf))
1121-
in
1122-
let row_more = loop rd.row_more in
1123-
let row_name =
1124-
match rd.row_name with
1125-
| None -> None
1126-
| Some (p, tl) -> Some (p, tl |> List.map loop)
1127-
in
1128-
{rd with row_fields; row_more; row_name}
1129-
and rowField (rf : Types.row_field) =
1130-
match rf with
1131-
| Rpresent None -> rf
1132-
| Rpresent (Some t) -> Rpresent (Some (loop t))
1133-
| Reither (b1, tl, b2, r) -> Reither (b1, tl |> List.map loop, b2, r)
1134-
| Rabsent -> Rabsent
1135-
in
1136-
loop t
1137-
11381147
let rec getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos
11391148
~env ~exact ~scope (contextPath : Completable.contextPath) =
11401149
match contextPath with
@@ -1211,14 +1220,9 @@ let rec getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos
12111220
with
12121221
| Some (typ, env) -> (
12131222
match typ |> extractRecordType ~env ~package with
1214-
| Some (env, fields, typDecl, typeArgs) ->
1215-
let typeParams = typDecl.item.decl.type_params in
1223+
| Some (env, fields, typDecl) ->
12161224
fields
12171225
|> Utils.filterMap (fun field ->
1218-
let fieldTyp =
1219-
field.typ |> instantiateType ~typeParams ~typeArgs
1220-
in
1221-
let field = {field with typ = fieldTyp} in
12221226
if checkName field.fname.txt ~prefix:fieldName ~exact then
12231227
Some
12241228
(Completion.create ~name:field.fname.txt ~env

0 commit comments

Comments
 (0)