Better errors for array/dictionary method calls that return mutable (#3370)
This commit is contained in:
parent
a1f111dfa6
commit
17d687b6a2
@ -7,7 +7,7 @@ use crate::syntax::ast::{self, AstNode};
|
||||
|
||||
/// Access an expression mutably.
|
||||
pub(crate) trait Access {
|
||||
/// Access the value.
|
||||
/// Access the expression's evaluated value mutably.
|
||||
fn access<'a>(self, vm: &'a mut Vm) -> SourceResult<&'a mut Value>;
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ impl Array {
|
||||
let len = self.len();
|
||||
self.locate_opt(index, false)
|
||||
.and_then(move |i| self.0.make_mut().get_mut(i))
|
||||
.ok_or_else(|| out_of_bounds_no_default(index, len))
|
||||
.ok_or_else(|| out_of_bounds(index, len))
|
||||
}
|
||||
|
||||
/// Resolve an index or throw an out of bounds error.
|
||||
|
@ -8,7 +8,7 @@ use ecow::{eco_format, EcoString};
|
||||
use smallvec::SmallVec;
|
||||
use unicode_math_class::MathClass;
|
||||
|
||||
use crate::diag::{At, SourceResult, StrResult};
|
||||
use crate::diag::{At, HintedStrResult, SourceResult, StrResult};
|
||||
use crate::foundations::{array, repr, NativeElement, Packed, Repr, Str, Type, Value};
|
||||
use crate::syntax::{Span, Spanned};
|
||||
|
||||
@ -233,6 +233,12 @@ impl<T: IntoValue> IntoResult for StrResult<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IntoValue> IntoResult for HintedStrResult<T> {
|
||||
fn into_result(self, span: Span) -> SourceResult<Value> {
|
||||
self.map(IntoValue::into_value).at(span)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: IntoValue> IntoResult for SourceResult<T> {
|
||||
fn into_result(self, _: Span) -> SourceResult<Value> {
|
||||
self.map(IntoValue::into_value)
|
||||
|
@ -7,7 +7,7 @@ use ecow::{eco_format, EcoString};
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use crate::diag::StrResult;
|
||||
use crate::diag::{Hint, HintedStrResult, StrResult};
|
||||
use crate::foundations::{array, func, repr, scope, ty, Array, Repr, Str, Value};
|
||||
use crate::syntax::is_ident;
|
||||
use crate::util::ArcExt;
|
||||
@ -83,10 +83,11 @@ impl Dict {
|
||||
}
|
||||
|
||||
/// Mutably borrow the value the given `key` maps to.
|
||||
pub fn at_mut(&mut self, key: &str) -> StrResult<&mut Value> {
|
||||
pub fn at_mut(&mut self, key: &str) -> HintedStrResult<&mut Value> {
|
||||
Arc::make_mut(&mut self.0)
|
||||
.get_mut(key)
|
||||
.ok_or_else(|| missing_key_no_default(key))
|
||||
.ok_or_else(|| missing_key(key))
|
||||
.hint("use `insert` to add or update values")
|
||||
}
|
||||
|
||||
/// Remove the value if the dictionary contains the given key.
|
||||
@ -354,7 +355,7 @@ fn missing_key(key: &str) -> EcoString {
|
||||
eco_format!("dictionary does not contain key {}", key.repr())
|
||||
}
|
||||
|
||||
/// The missing key access error message when no default was fiven.
|
||||
/// The missing key access error message when no default was given.
|
||||
#[cold]
|
||||
fn missing_key_no_default(key: &str) -> EcoString {
|
||||
eco_format!(
|
||||
|
109
tests/typ/bugs/3154-array-dict-mut-entry.typ
Normal file
109
tests/typ/bugs/3154-array-dict-mut-entry.typ
Normal file
@ -0,0 +1,109 @@
|
||||
// Issue #3154: Confusing errors from methods supposed to return a mutable entry
|
||||
// https://github.com/typst/typst/issues/3154
|
||||
// Ref: false
|
||||
|
||||
---
|
||||
#{
|
||||
let array = ()
|
||||
// Error: 3-16 array is empty
|
||||
array.first()
|
||||
}
|
||||
|
||||
---
|
||||
#{
|
||||
let array = ()
|
||||
// Error: 3-16 array is empty
|
||||
array.first() = 9
|
||||
}
|
||||
|
||||
---
|
||||
#{
|
||||
let array = ()
|
||||
// Error: 3-15 array is empty
|
||||
array.last()
|
||||
}
|
||||
|
||||
---
|
||||
#{
|
||||
let array = ()
|
||||
// Error: 3-15 array is empty
|
||||
array.last() = 9
|
||||
}
|
||||
|
||||
---
|
||||
#{
|
||||
let array = (1,)
|
||||
// Error: 3-14 array index out of bounds (index: 1, len: 1) and no default value was specified
|
||||
array.at(1)
|
||||
}
|
||||
|
||||
---
|
||||
#{
|
||||
let array = (1,)
|
||||
test(array.at(1, default: 0), 0)
|
||||
}
|
||||
|
||||
---
|
||||
#{
|
||||
let array = (1,)
|
||||
// Error: 3-14 array index out of bounds (index: 1, len: 1)
|
||||
array.at(1) = 9
|
||||
}
|
||||
|
||||
---
|
||||
#{
|
||||
let array = (1,)
|
||||
// Error: 3-26 array index out of bounds (index: 1, len: 1)
|
||||
array.at(1, default: 0) = 9
|
||||
}
|
||||
|
||||
---
|
||||
#{
|
||||
let dict = (a: 1)
|
||||
// Error: 3-15 dictionary does not contain key "b" and no default value was specified
|
||||
dict.at("b")
|
||||
}
|
||||
|
||||
---
|
||||
#{
|
||||
let dict = (a: 1)
|
||||
test(dict.at("b", default: 0), 0)
|
||||
}
|
||||
|
||||
---
|
||||
#{
|
||||
let dict = (a: 1)
|
||||
// Error: 3-15 dictionary does not contain key "b"
|
||||
// Hint: 3-15 use `insert` to add or update values
|
||||
dict.at("b") = 9
|
||||
}
|
||||
|
||||
---
|
||||
#{
|
||||
let dict = (a: 1)
|
||||
// Error: 3-27 dictionary does not contain key "b"
|
||||
// Hint: 3-27 use `insert` to add or update values
|
||||
dict.at("b", default: 0) = 9
|
||||
}
|
||||
|
||||
---
|
||||
#{
|
||||
let dict = (a: 1)
|
||||
// Error: 8-9 dictionary does not contain key "b"
|
||||
dict.b
|
||||
}
|
||||
|
||||
---
|
||||
#{
|
||||
let dict = (a: 1)
|
||||
dict.b = 9
|
||||
test(dict, (a: 1, b: 9))
|
||||
}
|
||||
|
||||
---
|
||||
#{
|
||||
let dict = (a: 1)
|
||||
// Error: 3-9 dictionary does not contain key "b"
|
||||
// Hint: 3-9 use `insert` to add or update values
|
||||
dict.b += 9
|
||||
}
|
@ -54,7 +54,7 @@
|
||||
// Test lvalue out of bounds.
|
||||
#{
|
||||
let array = (1, 2, 3)
|
||||
// Error: 3-14 array index out of bounds (index: 3, len: 3) and no default value was specified
|
||||
// Error: 3-14 array index out of bounds (index: 3, len: 3)
|
||||
array.at(3) = 5
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,8 @@
|
||||
// Missing lvalue is not automatically none-initialized.
|
||||
#{
|
||||
let dict = (:)
|
||||
// Error: 3-9 dictionary does not contain key "b" and no default value was specified
|
||||
// Error: 3-9 dictionary does not contain key "b"
|
||||
// Hint: 3-9 use `insert` to add or update values
|
||||
dict.b += 1
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user