Improve some error messages

This commit is contained in:
Richard Feldman 2025-11-18 08:04:42 -05:00
parent cf846d13e5
commit 1d3f0ff95c
No known key found for this signature in database
8 changed files with 61 additions and 13 deletions

View file

@ -3215,7 +3215,13 @@ pub fn canonicalizeExpr(
} orelse {
// Not a module alias and not an auto-imported module
// Check if the qualifier is a type - if so, try to lookup associated items
if (self.scopeLookupTypeBinding(module_alias)) |_| {
const is_type_in_scope = self.scopeLookupTypeBinding(module_alias) != null;
const is_auto_imported_type = if (self.module_envs) |envs_map|
envs_map.contains(module_alias)
else
false;
if (is_type_in_scope or is_auto_imported_type) {
// This is a type with a potential associated item
// Build the fully qualified name and try to look it up
const type_text = self.env.getIdent(module_alias);
@ -3345,11 +3351,26 @@ pub fn canonicalizeExpr(
break :blk_qualified;
}
return CanonicalizedExpr{
.idx = try self.env.pushMalformed(Expr.Idx, Diagnostic{ .qualified_ident_does_not_exist = .{
// Generate a more helpful error for auto-imported types (List, Bool, Try, etc.)
const is_auto_imported_type = if (self.module_envs) |envs_map|
envs_map.contains(module_name)
else
false;
const diagnostic = if (is_auto_imported_type)
Diagnostic{ .nested_value_not_found = .{
.parent_name = module_name,
.nested_name = ident,
.region = region,
} }
else
Diagnostic{ .qualified_ident_does_not_exist = .{
.ident = qualified_ident,
.region = region,
} }),
} };
return CanonicalizedExpr{
.idx = try self.env.pushMalformed(Expr.Idx, diagnostic),
.free_vars = null,
};
};

View file

@ -311,6 +311,9 @@ processData : Config, List(Value) -> Try(List(Value), Error)
**DOES NOT EXIST**
`List.mapTry` does not exist.
`List` is in scope, but it has no associated `mapTry`.
It's referenced here:
**can_import_exposing_types.md:22:5:22:16:**
```roc
List.mapTry(
@ -798,7 +801,7 @@ combineTrys = |jsonTry, httpStatus|
(p-assign (ident "config"))
(p-assign (ident "values")))
(e-call
(e-runtime-error (tag "qualified_ident_does_not_exist"))
(e-runtime-error (tag "nested_value_not_found"))
(e-lookup-local
(p-assign (ident "values")))
(e-closure

View file

@ -203,6 +203,9 @@ The unused variable is declared here:
**DOES NOT EXIST**
`Set.from_list` does not exist.
`Set` is in scope, but it has no associated `from_list`.
It's referenced here:
**Color.md:68:14:68:27:**
```roc
colors = Set.from_list(["AliceBlue", "AntiqueWhite", "Aqua"])
@ -1221,7 +1224,7 @@ is_named_color = |str| {
(s-let
(p-assign (ident "colors"))
(e-call
(e-runtime-error (tag "qualified_ident_does_not_exist"))
(e-runtime-error (tag "nested_value_not_found"))
(e-list
(elems
(e-string

View file

@ -28,6 +28,9 @@ match person {
**DOES NOT EXIST**
`Str.len` does not exist.
`Str` is in scope, but it has no associated `len`.
It's referenced here:
**pattern_destructure_with_rest.md:2:33:2:40:**
```roc
{ first_name, ..others } => Str.len(first_name) > Str.len(others.last_name)
@ -38,6 +41,9 @@ match person {
**DOES NOT EXIST**
`Str.len` does not exist.
`Str` is in scope, but it has no associated `len`.
It's referenced here:
**pattern_destructure_with_rest.md:2:55:2:62:**
```roc
{ first_name, ..others } => Str.len(first_name) > Str.len(others.last_name)
@ -98,11 +104,11 @@ match person {
(value
(e-binop (op "gt")
(e-call
(e-runtime-error (tag "qualified_ident_does_not_exist"))
(e-runtime-error (tag "nested_value_not_found"))
(e-lookup-local
(p-assign (ident "first_name"))))
(e-call
(e-runtime-error (tag "qualified_ident_does_not_exist"))
(e-runtime-error (tag "nested_value_not_found"))
(e-dot-access (field "last_name")
(receiver
(e-lookup-local

View file

@ -364,6 +364,9 @@ This might be a syntax error, an unsupported language feature, or a typo.
**DOES NOT EXIST**
`Bool.true` does not exist.
`Bool` is in scope, but it has no associated `true`.
It's referenced here:
**record_different_fields_reserved_error.md:6:10:6:19:**
```roc
and: Bool.true,
@ -407,6 +410,9 @@ This might be a syntax error, an unsupported language feature, or a typo.
**DOES NOT EXIST**
`Bool.false` does not exist.
`Bool` is in scope, but it has no associated `false`.
It's referenced here:
**record_different_fields_reserved_error.md:7:9:7:19:**
```roc
or: Bool.false,
@ -550,7 +556,7 @@ EndOfFile,
(s-expr
(e-runtime-error (tag "expr_not_canonicalized")))
(s-expr
(e-runtime-error (tag "qualified_ident_does_not_exist")))
(e-runtime-error (tag "nested_value_not_found")))
(s-expr
(e-runtime-error (tag "expr_not_canonicalized")))
(s-expr
@ -558,7 +564,7 @@ EndOfFile,
(s-expr
(e-runtime-error (tag "expr_not_canonicalized")))
(s-expr
(e-runtime-error (tag "qualified_ident_does_not_exist")))
(e-runtime-error (tag "nested_value_not_found")))
(e-runtime-error (tag "expr_not_canonicalized")))
~~~
# TYPES

View file

@ -13,6 +13,9 @@ DOES NOT EXIST - record_mixed_types.md:1:35:1:44
**DOES NOT EXIST**
`Bool.true` does not exist.
`Bool` is in scope, but it has no associated `true`.
It's referenced here:
**record_mixed_types.md:1:35:1:44:**
```roc
{ name: "Alice", age: 30, active: Bool.true, scores: [95, 87, 92], balance: 1250.75 }
@ -57,7 +60,7 @@ NO CHANGE
(field (name "age")
(e-num (value "30")))
(field (name "active")
(e-runtime-error (tag "qualified_ident_does_not_exist")))
(e-runtime-error (tag "nested_value_not_found")))
(field (name "scores")
(e-list
(elems

View file

@ -39,6 +39,9 @@ UNUSED VARIABLE - rigid_var_no_instantiation_error.md:21:5:21:12
**DOES NOT EXIST**
`Bool.true` does not exist.
`Bool` is in scope, but it has no associated `true`.
It's referenced here:
**rigid_var_no_instantiation_error.md:17:21:17:30:**
```roc
result2 = swap((Bool.true, [1, 2, 3]))
@ -255,7 +258,7 @@ main! = |_| {
(p-assign (ident "swap")))
(e-tuple
(elems
(e-runtime-error (tag "qualified_ident_does_not_exist"))
(e-runtime-error (tag "nested_value_not_found"))
(e-list
(elems
(e-num (value "1"))

View file

@ -19,6 +19,9 @@ TOO MANY ARGS - type_app_multiple_args.md:3:15:3:29
**DOES NOT EXIST**
`Dict.empty` does not exist.
`Dict` is in scope, but it has no associated `empty`.
It's referenced here:
**type_app_multiple_args.md:6:25:6:35:**
```roc
main! = |_| processDict(Dict.empty().insert("one", 1))
@ -124,7 +127,7 @@ NO CHANGE
(e-dot-access (field "insert")
(receiver
(e-call
(e-runtime-error (tag "qualified_ident_does_not_exist"))))
(e-runtime-error (tag "nested_value_not_found"))))
(args
(e-string
(e-literal (string "one")))