mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-07 14:44:59 +00:00
Special-case some more list error messages
This commit is contained in:
parent
a017569916
commit
bdc9997157
12 changed files with 243 additions and 44 deletions
|
@ -332,6 +332,7 @@ pub fn checkExpr(self: *Self, expr_idx: CIR.Expr.Idx) void {
|
|||
.incompatible_elem_var = @enumFromInt(@intFromEnum(elem_expr_id)),
|
||||
.incompatible_elem_snapshot = incompatible_snapshot,
|
||||
.incompatible_elem_index = i,
|
||||
.list_length = elems.len,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -222,38 +222,54 @@ pub const Problem = union(enum) {
|
|||
|
||||
// Add description
|
||||
buf.clearRetainingCapacity();
|
||||
try buf.appendSlice("The ");
|
||||
try appendOrdinal(buf, data.first_elem_index + 1);
|
||||
try buf.appendSlice(" and ");
|
||||
try appendOrdinal(buf, data.incompatible_elem_index + 1);
|
||||
try buf.appendSlice(" elements in this list have incompatible types:");
|
||||
if (data.list_length == 2) {
|
||||
// Special case for lists with exactly 2 elements
|
||||
try buf.appendSlice("The two elements in this list have incompatible types:");
|
||||
} else if (data.first_elem_index == 0 and data.incompatible_elem_index == 1) {
|
||||
// Special case for first two elements in longer lists
|
||||
try buf.appendSlice("The first two elements in this list have incompatible types:");
|
||||
} else {
|
||||
try buf.appendSlice("The ");
|
||||
try appendOrdinal(buf, data.first_elem_index + 1);
|
||||
try buf.appendSlice(" and ");
|
||||
try appendOrdinal(buf, data.incompatible_elem_index + 1);
|
||||
try buf.appendSlice(" elements in this list have incompatible types:");
|
||||
}
|
||||
const owned_description = try report.addOwnedString(buf.items);
|
||||
try report.document.addText(owned_description);
|
||||
try report.document.addLineBreak();
|
||||
|
||||
// Show a single region spanning both mismatched elements
|
||||
const span_start = if (data.first_elem_region.start.offset < data.incompatible_elem_region.start.offset)
|
||||
data.first_elem_region.start
|
||||
else
|
||||
data.incompatible_elem_region.start;
|
||||
|
||||
const span_end = if (data.first_elem_region.end.offset > data.incompatible_elem_region.end.offset)
|
||||
data.first_elem_region.end
|
||||
else
|
||||
data.incompatible_elem_region.end;
|
||||
|
||||
const span_region_info = base.RegionInfo.position(
|
||||
// Show the two elements with separate underlines
|
||||
// First element
|
||||
const first_elem_region_info = base.RegionInfo.position(
|
||||
source,
|
||||
module_env.line_starts.items,
|
||||
span_start.offset,
|
||||
span_end.offset,
|
||||
data.first_elem_region.start.offset,
|
||||
data.first_elem_region.end.offset,
|
||||
) catch return report;
|
||||
try report.document.addSourceRegion(
|
||||
source,
|
||||
span_region_info.start_line_idx,
|
||||
span_region_info.start_col_idx,
|
||||
span_region_info.end_line_idx,
|
||||
span_region_info.end_col_idx,
|
||||
first_elem_region_info.start_line_idx,
|
||||
first_elem_region_info.start_col_idx,
|
||||
first_elem_region_info.end_line_idx,
|
||||
first_elem_region_info.end_col_idx,
|
||||
.error_highlight,
|
||||
filename,
|
||||
);
|
||||
|
||||
// Second element
|
||||
const incompatible_elem_region_info = base.RegionInfo.position(
|
||||
source,
|
||||
module_env.line_starts.items,
|
||||
data.incompatible_elem_region.start.offset,
|
||||
data.incompatible_elem_region.end.offset,
|
||||
) catch return report;
|
||||
try report.document.addSourceRegion(
|
||||
source,
|
||||
incompatible_elem_region_info.start_line_idx,
|
||||
incompatible_elem_region_info.start_col_idx,
|
||||
incompatible_elem_region_info.end_line_idx,
|
||||
incompatible_elem_region_info.end_col_idx,
|
||||
.error_highlight,
|
||||
filename,
|
||||
);
|
||||
|
@ -454,6 +470,7 @@ pub const IncompatibleListElements = struct {
|
|||
incompatible_elem_var: Var,
|
||||
incompatible_elem_snapshot: SnapshotContentIdx,
|
||||
incompatible_elem_index: usize, // 0-based index of the incompatible element
|
||||
list_length: usize, // Total number of elements in the list
|
||||
};
|
||||
|
||||
/// A two var problem
|
||||
|
|
11
src/snapshots/can_list_first_concrete.md
generated
11
src/snapshots/can_list_first_concrete.md
generated
|
@ -9,12 +9,17 @@ type=expr
|
|||
~~~
|
||||
# PROBLEMS
|
||||
**INCOMPATIBLE LIST ELEMENTS**
|
||||
The first and second elements in this list have incompatible types:
|
||||
**can_list_first_concrete.md:1:2:1:13:**
|
||||
The first two elements in this list have incompatible types:
|
||||
**can_list_first_concrete.md:1:2:1:4:**
|
||||
```roc
|
||||
[42, "world", 3.14]
|
||||
```
|
||||
^^^^^^^^^^^
|
||||
^^
|
||||
**can_list_first_concrete.md:1:6:1:13:**
|
||||
```roc
|
||||
[42, "world", 3.14]
|
||||
```
|
||||
^^^^^^^
|
||||
|
||||
The first element has this type:
|
||||
_Num(*)_
|
||||
|
|
11
src/snapshots/can_list_heterogeneous.md
generated
11
src/snapshots/can_list_heterogeneous.md
generated
|
@ -9,12 +9,17 @@ type=expr
|
|||
~~~
|
||||
# PROBLEMS
|
||||
**INCOMPATIBLE LIST ELEMENTS**
|
||||
The first and second elements in this list have incompatible types:
|
||||
**can_list_heterogeneous.md:1:2:1:12:**
|
||||
The first two elements in this list have incompatible types:
|
||||
**can_list_heterogeneous.md:1:2:1:3:**
|
||||
```roc
|
||||
[1, "hello", 3.14]
|
||||
```
|
||||
^^^^^^^^^^
|
||||
^
|
||||
**can_list_heterogeneous.md:1:5:1:12:**
|
||||
```roc
|
||||
[1, "hello", 3.14]
|
||||
```
|
||||
^^^^^^^
|
||||
|
||||
The first element has this type:
|
||||
_Num(*)_
|
||||
|
|
72
src/snapshots/can_list_multiline_mismatch.md
generated
Normal file
72
src/snapshots/can_list_multiline_mismatch.md
generated
Normal file
|
@ -0,0 +1,72 @@
|
|||
# META
|
||||
~~~ini
|
||||
description=Multiline list with type mismatch
|
||||
type=expr
|
||||
~~~
|
||||
# SOURCE
|
||||
~~~roc
|
||||
[
|
||||
42,
|
||||
"hello world",
|
||||
100
|
||||
]
|
||||
~~~
|
||||
# PROBLEMS
|
||||
**INCOMPATIBLE LIST ELEMENTS**
|
||||
The first two elements in this list have incompatible types:
|
||||
**can_list_multiline_mismatch.md:2:5:2:7:**
|
||||
```roc
|
||||
42,
|
||||
```
|
||||
^^
|
||||
**can_list_multiline_mismatch.md:3:5:3:18:**
|
||||
```roc
|
||||
"hello world",
|
||||
```
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
The first element has this type:
|
||||
_Num(*)_
|
||||
|
||||
However, the second element has this type:
|
||||
_Str_
|
||||
|
||||
All elements in a list must have compatible types.
|
||||
|
||||
# TOKENS
|
||||
~~~zig
|
||||
OpenSquare(1:1-1:2),Newline(1:1-1:1),
|
||||
Int(2:5-2:7),Comma(2:7-2:8),Newline(1:1-1:1),
|
||||
StringStart(3:5-3:6),StringPart(3:6-3:17),StringEnd(3:17-3:18),Comma(3:18-3:19),Newline(1:1-1:1),
|
||||
Int(4:5-4:8),Newline(1:1-1:1),
|
||||
CloseSquare(5:1-5:2),EndOfFile(5:2-5:2),
|
||||
~~~
|
||||
# PARSE
|
||||
~~~clojure
|
||||
(e-list @1-1-5-2
|
||||
(e-int @2-5-2-7 (raw "42"))
|
||||
(e-string @3-5-3-18
|
||||
(e-string-part @3-6-3-17 (raw "hello world")))
|
||||
(e-int @4-5-4-8 (raw "100")))
|
||||
~~~
|
||||
# FORMATTED
|
||||
~~~roc
|
||||
[
|
||||
42,
|
||||
"hello world",
|
||||
100,
|
||||
]
|
||||
~~~
|
||||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(e-list @1-1-5-2 (elem-var 72) (id 76)
|
||||
(elems
|
||||
(e-int @2-5-2-7 (value "42"))
|
||||
(e-string @3-5-3-18
|
||||
(e-literal @3-6-3-17 (string "hello world")))
|
||||
(e-int @4-5-4-8 (value "100"))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(expr (id 76) (type "List(Error)"))
|
||||
~~~
|
9
src/snapshots/can_list_nested_heterogeneous.md
generated
9
src/snapshots/can_list_nested_heterogeneous.md
generated
|
@ -10,11 +10,16 @@ type=expr
|
|||
# PROBLEMS
|
||||
**INCOMPATIBLE LIST ELEMENTS**
|
||||
The second and third elements in this list have incompatible types:
|
||||
**can_list_nested_heterogeneous.md:1:6:1:20:**
|
||||
**can_list_nested_heterogeneous.md:1:6:1:9:**
|
||||
```roc
|
||||
[[], [1], ["hello"]]
|
||||
```
|
||||
^^^^^^^^^^^^^^
|
||||
^^^
|
||||
**can_list_nested_heterogeneous.md:1:11:1:20:**
|
||||
```roc
|
||||
[[], [1], ["hello"]]
|
||||
```
|
||||
^^^^^^^^^
|
||||
|
||||
The second element has this type:
|
||||
_List(Num(*))_
|
||||
|
|
11
src/snapshots/can_list_number_doesnt_fit.md
generated
11
src/snapshots/can_list_number_doesnt_fit.md
generated
|
@ -15,12 +15,17 @@ This number literal is not valid: 1u8
|
|||
This number literal is not valid: 2u8
|
||||
|
||||
**INCOMPATIBLE LIST ELEMENTS**
|
||||
The first and second elements in this list have incompatible types:
|
||||
**can_list_number_doesnt_fit.md:1:2:1:10:**
|
||||
The first two elements in this list have incompatible types:
|
||||
**can_list_number_doesnt_fit.md:1:2:1:5:**
|
||||
```roc
|
||||
[1u8, 2u8, 300]
|
||||
```
|
||||
^^^^^^^^
|
||||
^^^
|
||||
**can_list_number_doesnt_fit.md:1:7:1:10:**
|
||||
```roc
|
||||
[1u8, 2u8, 300]
|
||||
```
|
||||
^^^
|
||||
|
||||
The first element has this type:
|
||||
_Error_
|
||||
|
|
|
@ -10,11 +10,16 @@ type=expr
|
|||
# PROBLEMS
|
||||
**INCOMPATIBLE LIST ELEMENTS**
|
||||
The second and third elements in this list have incompatible types:
|
||||
**can_list_triple_nested_heterogeneous.md:1:6:1:32:**
|
||||
**can_list_triple_nested_heterogeneous.md:1:6:1:15:**
|
||||
```roc
|
||||
[[], [[], [1]], [[], ["hello"]]]
|
||||
```
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^
|
||||
**can_list_triple_nested_heterogeneous.md:1:17:1:32:**
|
||||
```roc
|
||||
[[], [[], [1]], [[], ["hello"]]]
|
||||
```
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
The second element has this type:
|
||||
_List(List(Num(*)))_
|
||||
|
|
58
src/snapshots/can_list_two_elements.md
generated
Normal file
58
src/snapshots/can_list_two_elements.md
generated
Normal file
|
@ -0,0 +1,58 @@
|
|||
# META
|
||||
~~~ini
|
||||
description=List with exactly two incompatible elements
|
||||
type=expr
|
||||
~~~
|
||||
# SOURCE
|
||||
~~~roc
|
||||
[1, "hello"]
|
||||
~~~
|
||||
# PROBLEMS
|
||||
**INCOMPATIBLE LIST ELEMENTS**
|
||||
The two elements in this list have incompatible types:
|
||||
**can_list_two_elements.md:1:2:1:3:**
|
||||
```roc
|
||||
[1, "hello"]
|
||||
```
|
||||
^
|
||||
**can_list_two_elements.md:1:5:1:12:**
|
||||
```roc
|
||||
[1, "hello"]
|
||||
```
|
||||
^^^^^^^
|
||||
|
||||
The first element has this type:
|
||||
_Num(*)_
|
||||
|
||||
However, the second element has this type:
|
||||
_Str_
|
||||
|
||||
All elements in a list must have compatible types.
|
||||
|
||||
# TOKENS
|
||||
~~~zig
|
||||
OpenSquare(1:1-1:2),Int(1:2-1:3),Comma(1:3-1:4),StringStart(1:5-1:6),StringPart(1:6-1:11),StringEnd(1:11-1:12),CloseSquare(1:12-1:13),EndOfFile(1:13-1:13),
|
||||
~~~
|
||||
# PARSE
|
||||
~~~clojure
|
||||
(e-list @1-1-1-13
|
||||
(e-int @1-2-1-3 (raw "1"))
|
||||
(e-string @1-5-1-12
|
||||
(e-string-part @1-6-1-11 (raw "hello"))))
|
||||
~~~
|
||||
# FORMATTED
|
||||
~~~roc
|
||||
NO CHANGE
|
||||
~~~
|
||||
# CANONICALIZE
|
||||
~~~clojure
|
||||
(e-list @1-1-1-13 (elem-var 72) (id 75)
|
||||
(elems
|
||||
(e-int @1-2-1-3 (value "1"))
|
||||
(e-string @1-5-1-12
|
||||
(e-literal @1-6-1-11 (string "hello")))))
|
||||
~~~
|
||||
# TYPES
|
||||
~~~clojure
|
||||
(expr (id 75) (type "List(Error)"))
|
||||
~~~
|
22
src/snapshots/can_nested_heterogeneous_lists.md
generated
22
src/snapshots/can_nested_heterogeneous_lists.md
generated
|
@ -9,12 +9,17 @@ type=expr
|
|||
~~~
|
||||
# PROBLEMS
|
||||
**INCOMPATIBLE LIST ELEMENTS**
|
||||
The first and second elements in this list have incompatible types:
|
||||
**can_nested_heterogeneous_lists.md:1:3:1:13:**
|
||||
The two elements in this list have incompatible types:
|
||||
**can_nested_heterogeneous_lists.md:1:3:1:4:**
|
||||
```roc
|
||||
[[1, "hello"], [2, 3]]
|
||||
```
|
||||
^^^^^^^^^^
|
||||
^
|
||||
**can_nested_heterogeneous_lists.md:1:6:1:13:**
|
||||
```roc
|
||||
[[1, "hello"], [2, 3]]
|
||||
```
|
||||
^^^^^^^
|
||||
|
||||
The first element has this type:
|
||||
_Num(*)_
|
||||
|
@ -25,12 +30,17 @@ However, the second element has this type:
|
|||
All elements in a list must have compatible types.
|
||||
|
||||
**INCOMPATIBLE LIST ELEMENTS**
|
||||
The first and second elements in this list have incompatible types:
|
||||
**can_nested_heterogeneous_lists.md:1:2:1:22:**
|
||||
The two elements in this list have incompatible types:
|
||||
**can_nested_heterogeneous_lists.md:1:2:1:14:**
|
||||
```roc
|
||||
[[1, "hello"], [2, 3]]
|
||||
```
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^
|
||||
**can_nested_heterogeneous_lists.md:1:16:1:22:**
|
||||
```roc
|
||||
[[1, "hello"], [2, 3]]
|
||||
```
|
||||
^^^^^^
|
||||
|
||||
The first element has this type:
|
||||
_List(Error)_
|
||||
|
|
|
@ -10,11 +10,16 @@ type=expr
|
|||
# PROBLEMS
|
||||
**INCOMPATIBLE LIST ELEMENTS**
|
||||
The second and third elements in this list have incompatible types:
|
||||
**list_type_err.md:1:5:1:15:**
|
||||
**list_type_err.md:1:5:1:6:**
|
||||
```roc
|
||||
[1, 2, "hello"]
|
||||
```
|
||||
^^^^^^^^^^
|
||||
^
|
||||
**list_type_err.md:1:8:1:15:**
|
||||
```roc
|
||||
[1, 2, "hello"]
|
||||
```
|
||||
^^^^^^^
|
||||
|
||||
The second element has this type:
|
||||
_Num(*)_
|
||||
|
|
11
test_list_messages.txt
Normal file
11
test_list_messages.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
List with 2 elements, both incompatible:
|
||||
[1, "hello"]
|
||||
→ "The two elements in this list have incompatible types"
|
||||
|
||||
List with 3+ elements, first two incompatible:
|
||||
[1, "hello", 3.14]
|
||||
→ "The first two elements in this list have incompatible types"
|
||||
|
||||
List with 3+ elements, later elements incompatible:
|
||||
[1, 2, "hello"]
|
||||
→ "The second and third elements in this list have incompatible types"
|
Loading…
Add table
Add a link
Reference in a new issue