Repository navigation
Commit b23f95b
* Keep @tag and runtime annotations when printing a type declaration
Why:
The printer of type declarations kept only @Immediate and @unboxed.
@tag, @notundefined, @instanceof and @typeof were dropped, so a
signature mismatch about them printed two declarations that looked the
same, hover hid them, and createInterface wrote an interface for an
applied functor that does not match its implementation (#9134).
Diagnostic modified (@tag mismatch):
Example:
// Foo.res
@tag("type")
type t =
| @as("a") A
| B
// Foo.resi
@tag("kind")
type t =
| @as("a") A
| B
Before (diagnostic):
Actual declaration (Foo.res:2:1-4:5):
type t = @as("a") A | B
Expected declaration (Foo.resi:2:1-4:5):
type t = @as("a") A | B
Their @tag annotations differ.
After (diagnostic):
Actual declaration (Foo.res:2:1-4:5):
@tag("type") type t = @as("a") A | B
Expected declaration (Foo.resi:2:1-4:5):
@tag("kind") type t = @as("a") A | B
Their @tag annotations differ.
Diagnostic modified (@notundefined functor parameter):
Example:
module Make = (
X: {
@notundefined type t
},
) => {
type u = X.t
}
module Applied = Make({
type t = option<int>
})
Before (diagnostic):
Actual declaration (not_undefined_functor_argument.res:10:3-22):
type t = option<int>
Expected declaration (not_undefined_functor_argument.res:3:19-24):
type t
Their runtime representations differ:
Actual declaration: can hold undefined
Expected declaration: @notundefined
After (diagnostic):
Actual declaration (not_undefined_functor_argument.res:10:3-22):
type t = option<int>
Expected declaration (not_undefined_functor_argument.res:3:19-24):
@notundefined type t
Their runtime representations differ:
Actual declaration: can hold undefined
Expected declaration: @notundefined
Format modified (createInterface for an applied functor):
Example:
module Tagged = (X: Type) => {
@tag("kind") type wrapped = Value({value: X.t}) | Empty({reason: string})
}
module IntTagged = Tagged({
type t = int
})
Before (rescript): the interface does not compile against the implementation
module IntTagged: {
type wrapped = Value({value: int}) | Empty({reason: string})
}
After (rescript):
module IntTagged: {
@tag("kind") type wrapped = Value({value: int}) | Empty({reason: string})
}
Representation modified (printed declaration annotations, Printtyp.tree_of_type_decl):
Before (representation):
otype_immediate: bool ↦ @Immediate
otype_unboxed: bool ↦ @unboxed
After (representation):
otype_attributes: string list ↦ @Immediate @unboxed @tag("…") @notundefined | @instanceof("…") | @typeof("…")
source: what the declaration itself states, not what it inherits from an abbreviated type
Review: Why read the attributes rather than the declaration's runtime shape? The shape of an abbreviation can come from the type it abbreviates; the printed declaration should show what it states itself, as the source does.
Review: Can printing raise for a malformed annotation? No. The annotations are parsed by the functions that typing uses, which raise on malformed payloads; those were reported when the declaration was typed, and the printer then leaves the annotation out.
Fixes: #9134
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>
* 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>
* Escape a @tag name when printing it
Codex review of #9136: the printed @tag put the decoded name between quotes
as it is, so a tag with a quote printed as invalid source and a backslash
changed its value when reparsed, also in interfaces written by
createInterface. It is now encoded as a string literal, which keeps
non-ASCII letters as they are.
Diagnostic modified (@tag names with a quote, a backslash and a non-ASCII letter):
Example:
module M: {
@tag("k\"ind") type t = A({x: int}) | B({y: int})
} = {
@tag("typ\\é") type t = A({x: int}) | B({y: int})
}
Before (diagnostic):
Actual declaration (tag_name_escaped.res:6:18-51):
@tag("typ\é") type t = A({x: int}) | B({y: int})
Expected declaration (tag_name_escaped.res:4:18-51):
@tag("k"ind") type t = A({x: int}) | B({y: int})
After (diagnostic):
Actual declaration (tag_name_escaped.res:6:18-51):
@tag("typ\\é") type t = A({x: int}) | B({y: int})
Expected declaration (tag_name_escaped.res:4:18-51):
@tag("k\"ind") type t = A({x: int}) | B({y: int})
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>
---------
Signed-off-by: Christoph Knittel <ck@cca.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent acdf563 commit b23f95b
23 files changed
Lines changed: 151 additions & 44 deletions
File tree
- changes
- compiler
- ml
- syntax/src
- tests
- analysis_tests/tests/src
- expected
- build_tests
- super_errors_multi/expected
- super_errors
- expected
- fixtures
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
201 | 201 | | |
202 | 202 | | |
203 | 203 | | |
204 | | - | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
205 | 207 | | |
206 | 208 | | |
207 | 209 | | |
| |||
243 | 245 | | |
244 | 246 | | |
245 | 247 | | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
250 | | - | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
251 | 252 | | |
252 | | - | |
253 | | - | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
254 | 257 | | |
255 | | - | |
256 | | - | |
257 | | - | |
258 | | - | |
259 | | - | |
260 | | - | |
261 | | - | |
262 | | - | |
263 | | - | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
264 | 283 | | |
265 | 284 | | |
266 | 285 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
70 | | - | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
583 | 583 | | |
584 | 584 | | |
585 | 585 | | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
586 | 593 | | |
587 | | - | |
| 594 | + | |
| 595 | + | |
588 | 596 | | |
589 | 597 | | |
590 | 598 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
70 | 70 | | |
71 | 71 | | |
72 | 72 | | |
73 | | - | |
74 | | - | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
75 | 76 | | |
76 | 77 | | |
77 | 78 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
892 | 892 | | |
893 | 893 | | |
894 | 894 | | |
895 | | - | |
| 895 | + | |
| 896 | + | |
| 897 | + | |
| 898 | + | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
896 | 918 | | |
897 | 919 | | |
898 | 920 | | |
899 | 921 | | |
900 | 922 | | |
901 | | - | |
902 | | - | |
| 923 | + | |
903 | 924 | | |
904 | 925 | | |
905 | 926 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
661 | 661 | | |
662 | 662 | | |
663 | 663 | | |
664 | | - | |
665 | | - | |
666 | | - | |
667 | | - | |
668 | | - | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
669 | 668 | | |
670 | 669 | | |
671 | 670 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
Large diffs are not rendered by default.
0 commit comments