Skip to content

Commit 0a6e8b4

Browse files
riaqnspiessimon
authored andcommitted
"module type of" zap modalities to floor (ocaml-flambda#3922)
1 parent 487e5b8 commit 0a6e8b4

File tree

4 files changed

+121
-31
lines changed

4 files changed

+121
-31
lines changed

testsuite/tests/typing-modes/val_modalities.ml

+94-12
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,48 @@ module Module_type_of_comonadic = struct
7373
module M = struct
7474
let x @ portable = fun x -> x
7575
end
76-
(* for comonadic axes, we default to id = meet_with_max, which is the
77-
weakest. *)
76+
(* for comonadic axes, we default to meet_with_min, which is the strongest.
77+
*)
7878
module M' : module type of M = struct
7979
let x @ portable = fun x -> x
8080
end
8181
let _ = portable_use M.x (* The original inferred modality is zapped *)
8282
end
8383
[%%expect{|
84-
Line 10, characters 25-28:
85-
10 | let _ = portable_use M.x (* The original inferred modality is zapped *)
86-
^^^
87-
Error: This value is "nonportable" but expected to be "portable".
84+
module Module_type_of_comonadic :
85+
sig
86+
module M : sig val x : 'a -> 'a @@ stateless end
87+
module M' : sig val x : 'a -> 'a @@ stateless end
88+
end
89+
|}]
90+
91+
(* zapping behavior can cause type error that shouldn't happen in upstream ocaml *)
92+
module Module_type_of_error = struct
93+
module M = struct
94+
let x = fun x -> x
95+
end
96+
97+
module M' : module type of M = struct
98+
let y = ref 42
99+
let x = fun x -> ignore !y; x
100+
end
101+
end
102+
[%%expect{|
103+
Lines 6-9, characters 33-5:
104+
6 | .................................struct
105+
7 | let y = ref 42
106+
8 | let x = fun x -> ignore !y; x
107+
9 | end
108+
Error: Signature mismatch:
109+
Modules do not match:
110+
sig val y : int ref val x : 'a -> 'a end
111+
is not included in
112+
sig val x : 'a -> 'a @@ stateless end
113+
Values do not match:
114+
val x : 'a -> 'a
115+
is not included in
116+
val x : 'a -> 'a @@ stateless
117+
The second is portable and the first is nonportable.
88118
|}]
89119

90120
module Module_type_of_monadic = struct
@@ -95,13 +125,28 @@ module Module_type_of_monadic = struct
95125
(* for monadic axes, we try to push to the id = join_with_min. The original
96126
modality is pushed to floor. *)
97127
module M' : module type of M = struct
98-
let x @ contended = ref "hello"
128+
let x @ contended = ref "hello"
99129
end
100130
end
101131
[%%expect{|
102132
Lines 8-10, characters 35-7:
103133
8 | ...................................struct
104-
9 | let x @ contended = ref "hello"
134+
9 | let x @ contended = ref "hello"
135+
10 | end
136+
Error: Signature mismatch:
137+
Modules do not match:
138+
sig val x : string ref @@ contended end
139+
is not included in
140+
sig val x : string ref @@ stateless end
141+
Values do not match:
142+
val x : string ref @@ contended
143+
is not included in
144+
val x : string ref @@ stateless
145+
The second is uncontended and the first is contended.
146+
|}, Principal{|
147+
Lines 8-10, characters 35-7:
148+
8 | ...................................struct
149+
9 | let x @ contended = ref "hello"
105150
10 | end
106151
Error: Signature mismatch:
107152
Modules do not match:
@@ -123,28 +168,65 @@ module Module_type_nested = struct
123168
end
124169
end
125170
module M' : module type of M = struct
126-
let x @ nonportable = fun t -> t
171+
let x @ portable = fun t -> t
127172
module N = struct
128173
let y @ contended = ref "hello"
129174
end
130175
end
131176
end
177+
(* CR zqian: Need to add mode crossing at binding to remove the principality
178+
issue. See
179+
https://github.com/ocaml-flambda/flambda-backend/pull/3922#discussion_r2059000469
180+
*)
132181
[%%expect{|
133182
Lines 8-13, characters 35-7:
134183
8 | ...................................struct
135-
9 | let x @ nonportable = fun t -> t
184+
9 | let x @ portable = fun t -> t
185+
10 | module N = struct
186+
11 | let y @ contended = ref "hello"
187+
12 | end
188+
13 | end
189+
Error: Signature mismatch:
190+
Modules do not match:
191+
sig
192+
val x : 'a -> 'a @@ stateless
193+
module N : sig val y : string ref @@ contended end
194+
end
195+
is not included in
196+
sig
197+
val x : 'a -> 'a @@ stateless
198+
module N : sig val y : string ref @@ stateless end
199+
end
200+
In module "N":
201+
Modules do not match:
202+
sig val y : string ref @@ contended end
203+
is not included in
204+
sig val y : string ref @@ stateless end
205+
In module "N":
206+
Values do not match:
207+
val y : string ref @@ contended
208+
is not included in
209+
val y : string ref @@ stateless
210+
The second is uncontended and the first is contended.
211+
|}, Principal{|
212+
Lines 8-13, characters 35-7:
213+
8 | ...................................struct
214+
9 | let x @ portable = fun t -> t
136215
10 | module N = struct
137216
11 | let y @ contended = ref "hello"
138217
12 | end
139218
13 | end
140219
Error: Signature mismatch:
141220
Modules do not match:
142221
sig
143-
val x : 'a -> 'a
222+
val x : 'a -> 'a @@ stateless
144223
module N : sig val y : string ref @@ contended end
145224
end
146225
is not included in
147-
sig val x : 'a -> 'a module N : sig val y : string ref end end
226+
sig
227+
val x : 'a -> 'a @@ stateless
228+
module N : sig val y : string ref end
229+
end
148230
In module "N":
149231
Modules do not match:
150232
sig val y : string ref @@ contended end

testsuite/tests/typing-modules/aliases.ml

+4-1
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,10 @@ module type S =
663663
sig
664664
module N : sig module I = Int end
665665
module P :
666-
sig module I : sig type t = int val compare : 'a -> 'a -> int end end
666+
sig
667+
module I :
668+
sig type t = int val compare : 'a -> 'a -> int @@ portable end
669+
end
667670
module Q :
668671
sig type wrap' = wrap = W of (Set.Make(Int).t, Set.Make(N.I).t) eq end
669672
end

testsuite/tests/typing-zero-alloc/signatures.ml

+22-15
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,8 @@ end
865865

866866
[%%expect{|
867867
module M_base_for_mto : sig val f : int -> int [@@zero_alloc] end
868-
module type S_base_mto = sig val f : int -> int [@@zero_alloc] end
868+
module type S_base_mto =
869+
sig val f : int -> int @@ portable [@@zero_alloc] end
869870
module M_mto_base_good : S_base_mto
870871
Lines 11-13, characters 37-3:
871872
11 | .....................................struct
@@ -879,7 +880,7 @@ Error: Signature mismatch:
879880
Values do not match:
880881
val f : int -> int [@@zero_alloc opt]
881882
is not included in
882-
val f : int -> int [@@zero_alloc]
883+
val f : int -> int @@ portable [@@zero_alloc]
883884
The former provides a weaker "zero_alloc" guarantee than the latter.
884885
|}]
885886

@@ -899,7 +900,8 @@ end
899900

900901
[%%expect{|
901902
module M_strict_for_mto : sig val f : int -> int [@@zero_alloc strict] end
902-
module type S_strict_mto = sig val f : int -> int [@@zero_alloc strict] end
903+
module type S_strict_mto =
904+
sig val f : int -> int @@ portable [@@zero_alloc strict] end
903905
module M_mto_strict_good : S_strict_mto
904906
Lines 11-13, characters 41-3:
905907
11 | .........................................struct
@@ -913,7 +915,7 @@ Error: Signature mismatch:
913915
Values do not match:
914916
val f : int -> int [@@zero_alloc]
915917
is not included in
916-
val f : int -> int [@@zero_alloc strict]
918+
val f : int -> int @@ portable [@@zero_alloc strict]
917919
The former provides a weaker "zero_alloc" guarantee than the latter.
918920
|}]
919921

@@ -937,9 +939,11 @@ module type S_no_nrn = module type of M_nrn_for_mto
937939

938940
[%%expect{|
939941
module M_assume_for_mto : sig val f : int -> int * int [@@zero_alloc] end
940-
module type S_no_assume = sig val f : int -> int * int [@@zero_alloc] end
942+
module type S_no_assume =
943+
sig val f : int -> int * int @@ portable [@@zero_alloc] end
941944
module M_nrn_for_mto : sig val f : int -> int * int [@@zero_alloc] end
942-
module type S_no_nrn = sig val f : int -> int * int [@@zero_alloc] end
945+
module type S_no_nrn =
946+
sig val f : int -> int * int @@ portable [@@zero_alloc] end
943947
|}]
944948

945949
(**********************************************)
@@ -1047,8 +1051,8 @@ module type S = module type of M_infer2
10471051
[%%expect{|
10481052
module type S =
10491053
sig
1050-
val f : 'a -> 'a [@@zero_alloc strict]
1051-
val g : 'a -> 'a [@@zero_alloc]
1054+
val f : 'a -> 'a @@ stateless [@@zero_alloc strict]
1055+
val g : 'a -> 'a @@ stateless [@@zero_alloc]
10521056
end
10531057
|}]
10541058

@@ -1127,7 +1131,10 @@ module type S = module type of M_explicit_arity_2
11271131
[%%expect{|
11281132
module M_explicit_arity_2 : sig type t = int -> int val f : int -> t end
11291133
module type S =
1130-
sig type t = int -> int val f : int -> t [@@zero_alloc arity 2] end
1134+
sig
1135+
type t = int -> int
1136+
val f : int -> t @@ stateless [@@zero_alloc arity 2]
1137+
end
11311138
|}]
11321139

11331140
(***************************)
@@ -1146,7 +1153,7 @@ end
11461153
module type S = module type of M_for_mto
11471154
[%%expect{|
11481155
module M_for_mto : sig val f : int -> int end
1149-
module type S = sig val f : int -> int end
1156+
module type S = sig val f : int -> int @@ portable end
11501157
|}]
11511158

11521159
(* [S] itself is fixed. *)
@@ -1157,11 +1164,11 @@ Line 1, characters 61-62:
11571164
^
11581165
Error: Signature mismatch:
11591166
Modules do not match:
1160-
sig val f : int -> int end
1167+
sig val f : int -> int @@ portable end
11611168
is not included in
11621169
sig val f : int -> int [@@zero_alloc] end
11631170
Values do not match:
1164-
val f : int -> int
1171+
val f : int -> int @@ portable
11651172
is not included in
11661173
val f : int -> int [@@zero_alloc]
11671174
The former provides a weaker "zero_alloc" guarantee than the latter.
@@ -1178,18 +1185,18 @@ module type S' = module type of M_for_mto
11781185
module F' (X : S') : sig val[@zero_alloc] f : int -> int end = X
11791186
module F (X : S) : sig val[@zero_alloc] f : int -> int end = X
11801187
[%%expect{|
1181-
module type S' = sig val f : int -> int [@@zero_alloc] end
1188+
module type S' = sig val f : int -> int @@ portable [@@zero_alloc] end
11821189
module F' : functor (X : S') -> sig val f : int -> int [@@zero_alloc] end
11831190
Line 7, characters 61-62:
11841191
7 | module F (X : S) : sig val[@zero_alloc] f : int -> int end = X
11851192
^
11861193
Error: Signature mismatch:
11871194
Modules do not match:
1188-
sig val f : int -> int end
1195+
sig val f : int -> int @@ portable end
11891196
is not included in
11901197
sig val f : int -> int [@@zero_alloc] end
11911198
Values do not match:
1192-
val f : int -> int
1199+
val f : int -> int @@ portable
11931200
is not included in
11941201
val f : int -> int [@@zero_alloc]
11951202
The former provides a weaker "zero_alloc" guarantee than the latter.

typing/typemod.ml

+1-3
Original file line numberDiff line numberDiff line change
@@ -3562,11 +3562,9 @@ let type_module_type_of env smod =
35623562
let mty = Mtype.scrape_for_type_of ~remove_aliases env tmty.mod_type in
35633563
(* PR#5036: must not contain non-generalized type variables *)
35643564
check_nongen_modtype env smod.pmod_loc mty;
3565-
(* for [module type of], we zap to identity modality for best legacy
3566-
compatibility *)
35673565
let mty =
35683566
remove_modality_and_zero_alloc_variables_mty env
3569-
~zap_modality:Mode.Modality.Value.zap_to_id mty
3567+
~zap_modality:Mode.Modality.Value.zap_to_floor mty
35703568
in
35713569
tmty, mty
35723570

0 commit comments

Comments
 (0)