summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPg Biel <9021226+PgBiel@users.noreply.github.com>2023-07-26 18:03:33 -0300
committerGitHub <noreply@github.com>2023-07-26 23:03:33 +0200
commit5bd97e218b698b2ad14fad0470b3b800469ee748 (patch)
treecf3bdca070d0cc1f0bf72267fbe117f39eefd1f6
parent8c6addeb9be07eebaefc78ec9e3d3d302e8baf34 (diff)
Update field mutation error message (#1742)
-rw-r--r--crates/typst/src/eval/mod.rs25
-rw-r--r--tests/typ/compiler/dict.typ7
-rw-r--r--tests/typ/compiler/field.typ50
3 files changed, 69 insertions, 13 deletions
diff --git a/crates/typst/src/eval/mod.rs b/crates/typst/src/eval/mod.rs
index b4048e1b..15f0fddd 100644
--- a/crates/typst/src/eval/mod.rs
+++ b/crates/typst/src/eval/mod.rs
@@ -68,7 +68,7 @@ use unicode_segmentation::UnicodeSegmentation;
use self::func::{CapturesVisitor, Closure};
use crate::diag::{
- bail, error, warning, At, FileError, SourceDiagnostic, SourceResult, StrResult,
+ bail, error, warning, At, FileError, Hint, SourceDiagnostic, SourceResult, StrResult,
Trace, Tracepoint,
};
use crate::model::{
@@ -1962,11 +1962,24 @@ fn access_dict<'a>(
) -> SourceResult<&'a mut Dict> {
match access.target().access(vm)? {
Value::Dict(dict) => Ok(dict),
- value => bail!(
- access.target().span(),
- "expected dictionary, found {}",
- value.type_name(),
- ),
+ value => {
+ let type_name = value.type_name();
+ let span = access.target().span();
+ if matches!(
+ value, // those types have their own field getters
+ Value::Symbol(_) | Value::Content(_) | Value::Module(_) | Value::Func(_)
+ ) {
+ bail!(span, "cannot mutate fields on {type_name}");
+ } else if fields::fields_on(type_name).is_empty() {
+ bail!(span, "{type_name} does not have accessible fields");
+ } else {
+ // type supports static fields, which don't yet have
+ // setters
+ Err(eco_format!("fields on {type_name} are not yet mutable"))
+ .hint(eco_format!("try creating a new {type_name} with the updated field value instead"))
+ .at(span)
+ }
+ }
}
}
diff --git a/tests/typ/compiler/dict.typ b/tests/typ/compiler/dict.typ
index 6a2f1c7c..b257394f 100644
--- a/tests/typ/compiler/dict.typ
+++ b/tests/typ/compiler/dict.typ
@@ -92,10 +92,3 @@
---
// Error: 3-15 cannot mutate a temporary value
#((key: "val").other = "some")
-
----
-#{
- let object = none
- // Error: 3-9 expected dictionary, found none
- object.property = "value"
-}
diff --git a/tests/typ/compiler/field.typ b/tests/typ/compiler/field.typ
index 5c28a92c..a99959ea 100644
--- a/tests/typ/compiler/field.typ
+++ b/tests/typ/compiler/field.typ
@@ -148,3 +148,53 @@
#test((top + start).y, top)
#test((bottom + end).y, bottom)
#test((horizon + center).y, horizon)
+
+---
+#{
+ let object = sym.eq.not
+ // Error: 3-9 cannot mutate fields on symbol
+ object.property = "value"
+}
+
+---
+#{
+ let object = [hi]
+ // Error: 3-9 cannot mutate fields on content
+ object.property = "value"
+}
+
+---
+#{
+ let object = calc
+ // Error: 3-9 cannot mutate fields on module
+ object.property = "value"
+}
+
+---
+#{
+ let object = calc.sin
+ // Error: 3-9 cannot mutate fields on function
+ object.property = "value"
+}
+
+---
+#{
+ let object = none
+ // Error: 3-9 none does not have accessible fields
+ object.property = "value"
+}
+
+---
+#{
+ let object = 10
+ // Error: 3-9 integer does not have accessible fields
+ object.property = "value"
+}
+
+---
+#{
+ let s = 1pt + red
+ // Error: 3-4 fields on stroke are not yet mutable
+ // Hint: 3-4 try creating a new stroke with the updated field value instead
+ s.thickness = 5pt
+}