Skip to content

Commit 19cd7e9

Browse files
cknittclaude
andcommitted
Compare every runtime shape claim of an interface in one place
Interface inclusion compared classes and kinds in Includecore and @notundefined in Includemod, the two levels of one declared shape. Includecore.compare_runtime_annotations now checks both; the messages are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CMkrYaktctdKc4M41WF36t Signed-off-by: Christoph Knittel <ck@cca.io>
1 parent 18bb267 commit 19cd7e9

3 files changed

Lines changed: 18 additions & 26 deletions

File tree

‎compiler/ml/UntaggedVariants.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ for functor arguments and `with type` constraints.
501501
`ast_untagged_variants.ml:has_not_undefined`;
502502
`variant_layout.ml:declaration_shape`;
503503
`typeopt.ml:type_cannot_contain_undefined`;
504-
`includemod.ml:not_undefined_mismatch`.
504+
`includecore.ml:compare_runtime_annotations`.
505505
- Tests: `spec_test` rule 13; fixtures `invalid_attribute_not_undefined.res`,
506506
`not_undefined_functor_argument.res`, `not_undefined_functor_parameter.res`;
507507
`tests/tests/src/not_undefined_interface_test.res`,

‎compiler/ml/includecore.ml‎

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -345,13 +345,25 @@ and compare_records env params1_ params2_ n_
345345
in
346346
aux ~fast:true params1_ params2_ n_ labels1_ labels2_
347347

348-
(* Values are recognized by the class or [typeof] the second declaration
349-
states, so the first must state the same. Stating nothing hides it. *)
350-
let compare_runtime_annotations env decl1 decl2 =
348+
(* What the second declaration states about its values at run time must
349+
hold for the first. Values are recognized by the class or [typeof] the
350+
second states, so the first must state the same; stating nothing hides it.
351+
[@notUndefined] lets clients unbox [option] of the type, so the first must
352+
be a type that cannot hold [undefined] either, or one whose representation
353+
the compiler does not see, which has none that contradicts it. *)
354+
let compare_runtime_annotations env id decl1 decl2 =
351355
(* The second declaration's shape was resolved in its own environment, so
352356
it is what users of the second declaration see *)
353357
match decl2.type_shape with
354-
| Unstated | Never_undefined -> []
358+
| Unstated -> []
359+
| Never_undefined -> (
360+
let env = Env.add_type ~check:false id decl1 env in
361+
let ty =
362+
Btype.newgenty (Tconstr (Pident id, decl1.type_params, ref Mnil))
363+
in
364+
match Typeopt.undefinedness env ty with
365+
| Cannot_be_undefined | Unseen -> []
366+
| Stands_for_another | Can_be_undefined -> [Not_undefined])
355367
| Recognized_as block_type2 ->
356368
let declared2 = Some block_type2 in
357369
let declared1 =
@@ -395,7 +407,7 @@ let type_declarations ?(equality = false) ~loc env name decl1 id decl2 =
395407
else [Constraint]
396408
in
397409
let err =
398-
if err <> [] then err else compare_runtime_annotations env decl1 decl2
410+
if err <> [] then err else compare_runtime_annotations env id decl1 decl2
399411
in
400412
if err <> [] then err
401413
else

‎compiler/ml/includemod.ml‎

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -62,32 +62,12 @@ let value_descriptions ~loc env cxt subst id vd1 vd2 =
6262

6363
(* Inclusion between type declarations *)
6464

65-
(* [@notUndefined] lets clients unbox [option] of the type, so the
66-
implementation must be a type that cannot hold [undefined] either, or one
67-
whose representation the compiler does not see, which has none that
68-
contradicts it. *)
69-
let not_undefined_mismatch env id (decl1 : Types.type_declaration)
70-
(decl2 : Types.type_declaration) =
71-
match decl2.type_shape with
72-
| Unstated | Recognized_as _ -> []
73-
| Never_undefined -> (
74-
let env = Env.add_type ~check:false id decl1 env in
75-
let ty =
76-
Btype.newgenty (Tconstr (Pident id, decl1.type_params, ref Mnil))
77-
in
78-
match Typeopt.undefinedness env ty with
79-
| Cannot_be_undefined | Unseen -> []
80-
| Stands_for_another | Can_be_undefined -> [Includecore.Not_undefined])
81-
8265
let type_declarations ~loc env ?(old_env = env) cxt subst id decl1 decl2 =
8366
Env.mark_type_used env (Ident.name id) decl1;
8467
let decl2 = Subst.type_declaration subst decl2 in
8568
let err =
8669
Includecore.type_declarations ~loc env (Ident.name id) decl1 id decl2
8770
in
88-
let err =
89-
if err <> [] then err else not_undefined_mismatch env id decl1 decl2
90-
in
9171
if err <> [] then
9272
raise (Error [(cxt, old_env, Type_declarations (id, decl1, decl2, err))])
9373

0 commit comments

Comments
 (0)