Skip to content

Commit 922b663

Browse files
cknittclaude
andcommitted
Say when declarations that differ read the same
Why: With the annotations printed, two declarations can still read the same and not match, when a type they mention differs between the two sides, e.g. a base class that the interface leaves abstract. The error then showed the same text twice, which reads as a bug in the compiler. The reasons now start with a note saying so, which replaces the lead-in of a difference in runtime representation. Diagnostic modified (declarations that print the same): Example: // Classes.res @instanceof("Animal") type animal @instanceof("Dog") type dog = private animal // Classes.resi type animal @instanceof("Dog") type dog = private animal Before (diagnostic): Actual declaration (Classes.res:2:20-44): @instanceof("Dog") type dog = private animal Expected declaration (Classes.resi:2:20-44): @instanceof("Dog") type dog = private animal Their runtime representations differ: Actual declaration: instances of Dog, a subclass of Animal Expected declaration: instances of Dog After (diagnostic): Actual declaration (Classes.res:2:20-44): @instanceof("Dog") type dog = private animal Expected declaration (Classes.resi:2:20-44): @instanceof("Dog") type dog = private animal The declarations read the same, but a type they mention differs: Actual declaration: instances of Dog, a subclass of Animal Expected declaration: instances of Dog Review: Why compare the printed text? It is what the reader sees, and the case to catch is exactly two declarations that look the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kbf3gLpf7RN1MiRcubPgRn Signed-off-by: Christoph Knittel <ck@cca.io>
1 parent 08279c2 commit 922b663

4 files changed

Lines changed: 53 additions & 20 deletions

File tree

‎compiler/ml/includecore.ml‎

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,9 @@ let label side decl =
201201
in
202202
String.capitalize_ascii (side ^ " " ^ decl)
203203

204-
let report_type_mismatch0 first second decl ppf err =
204+
(* [lead_in] introduces the two lines of a difference in runtime
205+
representation; without it they stand under a lead-in printed before *)
206+
let report_type_mismatch0 ?(lead_in = true) first second decl ppf err =
205207
let pr fmt = Format.fprintf ppf fmt in
206208
match err with
207209
| Arity -> pr "They have different arities"
@@ -243,24 +245,41 @@ let report_type_mismatch0 first second decl ppf err =
243245
| Variant_representation s ->
244246
pr "The internal representations for case %s are not equal" (Ident.name s)
245247
| Not_undefined ->
246-
pr
247-
"@[<v 2>Their runtime representations differ:@,\
248-
%s: can hold undefined@,\
249-
%s: @notUndefined@]"
250-
(label first decl) (label second decl)
248+
if lead_in then pr "@[<v 2>Their runtime representations differ:@,";
249+
pr "%s: can hold undefined@,%s: @notUndefined" (label first decl)
250+
(label second decl);
251+
if lead_in then pr "@]"
251252
| Runtime_annotation (declared1, declared2) ->
252-
pr "@[<v 2>Their runtime representations differ:@,%s: %s@,%s: %s@]"
253-
(label first decl) declared1 (label second decl) declared2
253+
if lead_in then pr "@[<v 2>Their runtime representations differ:@,";
254+
pr "%s: %s@,%s: %s" (label first decl) declared1 (label second decl)
255+
declared2;
256+
if lead_in then pr "@]"
254257

255-
let report_type_mismatch first second decl ppf =
256-
List.iter (fun err ->
257-
match err with
258-
| Manifest -> ()
259-
(* Its lines are labels, not sentences *)
260-
| Runtime_annotation _ | Not_undefined ->
261-
Format.fprintf ppf "@ %a" (report_type_mismatch0 first second decl) err
262-
| _ ->
263-
Format.fprintf ppf "@ %a." (report_type_mismatch0 first second decl) err)
258+
(* Each reason on a line after a break. [read_the_same] puts them under a note
259+
that the declarations print the same, which then replaces the lead-in of a
260+
difference in runtime representation. *)
261+
let report_type_mismatch ?(read_the_same = false) first second decl ppf errs =
262+
let report ppf =
263+
List.iter (fun err ->
264+
match err with
265+
| Manifest -> ()
266+
(* Its lines are labels, not sentences *)
267+
| Runtime_annotation _ | Not_undefined ->
268+
Format.fprintf ppf "@ %a"
269+
(report_type_mismatch0 ~lead_in:(not read_the_same) first second
270+
decl)
271+
err
272+
| _ ->
273+
Format.fprintf ppf "@ %a."
274+
(report_type_mismatch0 first second decl)
275+
err)
276+
in
277+
if read_the_same then
278+
Format.fprintf ppf
279+
"@ @[<v 2>The declarations read the same, but a type they mention \
280+
differs:%a@]"
281+
report errs
282+
else report ppf errs
264283

265284
let rec compare_constructor_arguments env cstr params1 params2 arg1 arg2 =
266285
match (arg1, arg2) with

‎compiler/ml/includecore.mli‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,10 @@ val extension_constructors :
6767
Env.t -> Ident.t -> extension_constructor -> extension_constructor -> bool
6868

6969
val report_type_mismatch :
70-
string -> string -> string -> Format.formatter -> type_mismatch list -> unit
70+
?read_the_same:bool ->
71+
string ->
72+
string ->
73+
string ->
74+
Format.formatter ->
75+
type_mismatch list ->
76+
unit

‎compiler/ml/includemod.ml‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,8 +583,16 @@ let include_symptom ~swapped env ppf = function
583583
if swapped then ("the expected", "the actual")
584584
else ("the actual", "the expected")
585585
in
586+
(* Declarations can print the same and still differ, when a type they
587+
mention differs between the two sides, e.g. a class the interface
588+
leaves abstract. The reasons then say that first. *)
589+
let read_the_same =
590+
Format.asprintf "%a" (type_declaration id) d1
591+
= Format.asprintf "%a" (type_declaration id) d2
592+
in
586593
fprintf ppf "@,%a"
587-
(Includecore.report_type_mismatch first second "declaration")
594+
(Includecore.report_type_mismatch ~read_the_same first second
595+
"declaration")
588596
errs
589597
| Extension_constructors (id, x1, x2) ->
590598
show_declarations ~swapped (extension_constructor id) ppf

‎tests/build_tests/super_errors_multi/expected/Cross_runtime_annotation_hidden_base.expected‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616
Expected declaration (/.../fixtures/Cross_runtime_annotation_hidden_base/Classes.resi:2:20-44):
1717
@instanceOf("Dog") type dog = private animal
1818

19-
Their runtime representations differ:
19+
The declarations read the same, but a type they mention differs:
2020
Actual declaration: instances of Dog, a subclass of Animal
2121
Expected declaration: instances of Dog

0 commit comments

Comments
 (0)