Skip to content
This repository was archived by the owner on Nov 12, 2020. It is now read-only.

Commit 02c4df6

Browse files
committed
Fix PR#7348
1 parent a1bb26c commit 02c4df6

File tree

7 files changed

+80
-15
lines changed

7 files changed

+80
-15
lines changed

Changes

+3
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,9 @@ The complete list of changes is listed below.
685685
bytecode compiler (even when not using Flambda)
686686
(Mark Shinwell, Leo White, code review by Pierre Chambart)
687687

688+
- PR#7348: Private row variables can escape their scope
689+
(Jacques Garrigue, report by Leo White)
690+
688691
- PR#7407: Two not-quite-standard C idioms rejected by SUNWSPro compilers
689692
(Xavier Leroy)
690693

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
module F (X : sig type t = private < foo:int; ..> val x : t end) = struct
2+
let x : < foo: int; ..> = X.x
3+
end;;
4+
[%%expect{|
5+
module F :
6+
functor (X : sig type t = private < foo : int; .. > val x : t end) ->
7+
sig val x : X.t end
8+
|}]
9+
10+
module M = struct
11+
type t = < foo: int; bar: int>
12+
let x = object
13+
method foo = 0
14+
method bar = 0
15+
end
16+
end;;
17+
[%%expect{|
18+
module M :
19+
sig type t = < bar : int; foo : int > val x : < bar : int; foo : int > end
20+
|}]
21+
22+
module N = F(M);;
23+
[%%expect{|
24+
module N : sig val x : M.t end
25+
|}]
26+
27+
module A : sig end = struct
28+
module F (X : sig type t = private < foo:int; ..> val x : t end) = struct
29+
let x : < foo: int; ..> = X.x
30+
end
31+
32+
module N = F(M)
33+
let _ = (N.x = M.x)
34+
end;;
35+
[%%expect{|
36+
module A : sig end
37+
|}]

typing/btype.ml

+16-11
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ let newmarkedgenvar () =
5959

6060
let is_Tvar = function {desc=Tvar _} -> true | _ -> false
6161
let is_Tunivar = function {desc=Tunivar _} -> true | _ -> false
62+
let is_Tconstr = function {desc=Tconstr _} -> true | _ -> false
6263

6364
let dummy_method = "*dummy method*"
6465
let default_mty = function
@@ -208,27 +209,31 @@ let proxy ty =
208209

209210
(**** Utilities for fixed row private types ****)
210211

211-
let has_constr_row t =
212+
let row_of_type t =
212213
match (repr t).desc with
213214
Tobject(t,_) ->
214-
let rec check_row t =
215-
match (repr t).desc with
216-
Tfield(_,_,_,t) -> check_row t
217-
| Tconstr _ -> true
218-
| _ -> false
219-
in check_row t
215+
let rec get_row t =
216+
let t = repr t in
217+
match t.desc with
218+
Tfield(_,_,_,t) -> get_row t
219+
| _ -> t
220+
in get_row t
220221
| Tvariant row ->
221-
(match row_more row with {desc=Tconstr _} -> true | _ -> false)
222+
row_more row
222223
| _ ->
223-
false
224+
t
225+
226+
let has_constr_row t =
227+
not (is_Tconstr t) && is_Tconstr (row_of_type t)
224228

225229
let is_row_name s =
226230
let l = String.length s in
227231
if l < 4 then false else String.sub s (l-4) 4 = "#row"
228232

229-
let is_constr_row t =
233+
let is_constr_row ~allow_ident t =
230234
match t.desc with
231-
Tconstr (Path.Pident id, _, _) -> is_row_name (Ident.name id)
235+
Tconstr (Path.Pident id, _, _) when allow_ident ->
236+
is_row_name (Ident.name id)
232237
| Tconstr (Path.Pdot (_, s, _), _, _) -> is_row_name s
233238
| _ -> false
234239

typing/btype.mli

+3-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ val newmarkedgenvar: unit -> type_expr
4646

4747
val is_Tvar: type_expr -> bool
4848
val is_Tunivar: type_expr -> bool
49+
val is_Tconstr: type_expr -> bool
4950
val dummy_method: label
5051
val default_mty: module_type option -> module_type
5152

@@ -80,9 +81,10 @@ val proxy: type_expr -> type_expr
8081
or a row variable *)
8182

8283
(**** Utilities for private abbreviations with fixed rows ****)
84+
val row_of_type: type_expr -> type_expr
8385
val has_constr_row: type_expr -> bool
8486
val is_row_name: string -> bool
85-
val is_constr_row: type_expr -> bool
87+
val is_constr_row: allow_ident:bool -> type_expr -> bool
8688

8789
(**** Utilities for type traversal ****)
8890

typing/ctype.ml

+9-1
Original file line numberDiff line numberDiff line change
@@ -4205,7 +4205,15 @@ let rec normalize_type_rec env visited ty =
42054205
let ty = repr ty in
42064206
if not (TypeSet.mem ty !visited) then begin
42074207
visited := TypeSet.add ty !visited;
4208-
begin match ty.desc with
4208+
let tm = row_of_type ty in
4209+
begin if not (is_Tconstr ty) && is_constr_row ~allow_ident:false tm then
4210+
match tm.desc with (* PR#7348 *)
4211+
Tconstr (Path.Pdot(m,i,pos), tl, _abbrev) ->
4212+
let i' = String.sub i 0 (String.length i - 4) in
4213+
log_type ty;
4214+
ty.desc <- Tconstr(Path.Pdot(m,i',pos), tl, ref Mnil)
4215+
| _ -> assert false
4216+
else match ty.desc with
42094217
| Tvariant row ->
42104218
let row = row_repr row in
42114219
let fields = List.map

typing/printtyp.ml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1330,7 +1330,8 @@ let rec filter_trace keep_last = function
13301330
[]
13311331
| (t1, t1') :: (t2, t2') :: rem ->
13321332
let rem' = filter_trace keep_last rem in
1333-
if is_constr_row t1' || is_constr_row t2'
1333+
if is_constr_row ~allow_ident:true t1'
1334+
|| is_constr_row ~allow_ident:true t2'
13341335
|| same_path t1 t1' && same_path t2 t2' && not (keep_last && rem' = [])
13351336
then rem'
13361337
else (t1, t1') :: (t2, t2') :: rem'

typing/subst.ml

+10-1
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,20 @@ let rec typexp s ty =
139139
| _ ->
140140
let desc = ty.desc in
141141
save_desc ty desc;
142+
let tm = row_of_type ty in
143+
let has_fixed_row =
144+
not (is_Tconstr ty) && is_constr_row ~allow_ident:false tm in
142145
(* Make a stub *)
143146
let ty' = if s.for_saving then newpersty (Tvar None) else newgenvar () in
144147
ty.desc <- Tsubst ty';
145148
ty'.desc <-
146-
begin match desc with
149+
begin if has_fixed_row then
150+
match tm.desc with (* PR#7348 *)
151+
Tconstr (Pdot(m,i,pos), tl, _abbrev) ->
152+
let i' = String.sub i 0 (String.length i - 4) in
153+
Tconstr(type_path s (Pdot(m,i',pos)), tl, ref Mnil)
154+
| _ -> assert false
155+
else match desc with
147156
| Tconstr(p, tl, _abbrev) ->
148157
Tconstr(type_path s p, List.map (typexp s) tl, ref Mnil)
149158
| Tpackage(p, n, tl) ->

0 commit comments

Comments
 (0)