difftreelog
refactor Option<&ExprLocation> -> &Option<_>
in: master
6 files changed
crates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/builtin/mod.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/mod.rs
@@ -22,7 +22,7 @@
fn std_format(str: IStr, vals: Val) -> Result<Val> {
push(
- &Some(ExprLocation(Rc::from(PathBuf::from("std.jsonnet")), 0, 0)),
+ Some(&ExprLocation(Rc::from(PathBuf::from("std.jsonnet")), 0, 0)),
|| format!("std.format of {}", str),
|| {
Ok(match vals {
@@ -34,7 +34,7 @@
)
}
-type Builtin = fn(context: Context, loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val>;
+type Builtin = fn(context: Context, loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val>;
type BuiltinsType = HashMap<Box<str>, Builtin>;
@@ -78,7 +78,7 @@
};
}
-fn builtin_length(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_length(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "length", args, 1, [
0, x: ty!((string | object | array));
], {
@@ -96,7 +96,7 @@
})
}
-fn builtin_type(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_type(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "type", args, 1, [
0, x: ty!(any);
], {
@@ -106,7 +106,7 @@
fn builtin_make_array(
context: Context,
- _loc: &Option<ExprLocation>,
+ _loc: Option<&ExprLocation>,
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "makeArray", args, 2, [
@@ -126,7 +126,7 @@
fn builtin_codepoint(
context: Context,
- _loc: &Option<ExprLocation>,
+ _loc: Option<&ExprLocation>,
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "codepoint", args, 1, [
@@ -138,7 +138,7 @@
fn builtin_object_fields_ex(
context: Context,
- _loc: &Option<ExprLocation>,
+ _loc: Option<&ExprLocation>,
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "objectFieldsEx", args, 2, [
@@ -157,7 +157,7 @@
fn builtin_object_has_ex(
context: Context,
- _loc: &Option<ExprLocation>,
+ _loc: Option<&ExprLocation>,
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "objectHasEx", args, 3, [
@@ -175,7 +175,7 @@
}
// faster
-fn builtin_slice(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_slice(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "slice", args, 4, [
0, indexable: ty!((string | array));
1, index: ty!((number | null));
@@ -216,7 +216,7 @@
// faster
fn builtin_primitive_equals(
context: Context,
- _loc: &Option<ExprLocation>,
+ _loc: Option<&ExprLocation>,
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "primitiveEquals", args, 2, [
@@ -228,7 +228,7 @@
}
// faster
-fn builtin_equals(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_equals(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "equals", args, 2, [
0, a: ty!(any);
1, b: ty!(any);
@@ -237,7 +237,7 @@
})
}
-fn builtin_modulo(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_modulo(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "modulo", args, 2, [
0, a: ty!(number) => Val::Num;
1, b: ty!(number) => Val::Num;
@@ -246,7 +246,7 @@
})
}
-fn builtin_mod(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_mod(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "mod", args, 2, [
0, a: ty!((number | string));
1, b: ty!(any);
@@ -259,7 +259,7 @@
})
}
-fn builtin_floor(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_floor(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "floor", args, 1, [
0, x: ty!(number) => Val::Num;
], {
@@ -267,7 +267,7 @@
})
}
-fn builtin_log(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_log(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "log", args, 1, [
0, n: ty!(number) => Val::Num;
], {
@@ -275,7 +275,7 @@
})
}
-fn builtin_pow(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_pow(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "pow", args, 2, [
0, x: ty!(number) => Val::Num;
1, n: ty!(number) => Val::Num;
@@ -284,7 +284,7 @@
})
}
-fn builtin_ext_var(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_ext_var(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "extVar", args, 1, [
0, x: ty!(string) => Val::Str;
], {
@@ -292,7 +292,7 @@
})
}
-fn builtin_native(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_native(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "native", args, 1, [
0, x: ty!(string) => Val::Str;
], {
@@ -300,7 +300,7 @@
})
}
-fn builtin_filter(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_filter(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "filter", args, 2, [
0, func: ty!(function) => Val::Func;
1, arr: ty!(array) => Val::Arr;
@@ -318,7 +318,7 @@
})
}
-fn builtin_foldl(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_foldl(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "foldl", args, 3, [
0, func: ty!(function) => Val::Func;
1, arr: ty!(array) => Val::Arr;
@@ -332,7 +332,7 @@
})
}
-fn builtin_foldr(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_foldr(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "foldr", args, 3, [
0, func: ty!(function) => Val::Func;
1, arr: ty!(array) => Val::Arr;
@@ -349,7 +349,7 @@
#[allow(non_snake_case)]
fn builtin_sort_impl(
context: Context,
- _loc: &Option<ExprLocation>,
+ _loc: Option<&ExprLocation>,
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "sort", args, 2, [
@@ -364,7 +364,7 @@
}
// faster
-fn builtin_format(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_format(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "format", args, 2, [
0, str: ty!(string) => Val::Str;
1, vals: ty!(any)
@@ -373,7 +373,7 @@
})
}
-fn builtin_range(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_range(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "range", args, 2, [
0, from: ty!(number) => Val::Num;
1, to: ty!(number) => Val::Num;
@@ -386,7 +386,7 @@
})
}
-fn builtin_char(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_char(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "char", args, 1, [
0, n: ty!(number) => Val::Num;
], {
@@ -400,7 +400,7 @@
fn builtin_encode_utf8(
context: Context,
- _loc: &Option<ExprLocation>,
+ _loc: Option<&ExprLocation>,
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "encodeUTF8", args, 1, [
@@ -410,7 +410,7 @@
})
}
-fn builtin_md5(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_md5(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "md5", args, 1, [
0, str: ty!(string) => Val::Str;
], {
@@ -418,7 +418,7 @@
})
}
-fn builtin_trace(context: Context, loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_trace(context: Context, loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "trace", args, 2, [
0, str: ty!(string) => Val::Str;
1, rest: ty!(any);
@@ -435,7 +435,7 @@
})
}
-fn builtin_base64(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_base64(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "base64", args, 1, [
0, input: ty!((string | (Array<number>)));
], {
@@ -453,7 +453,7 @@
})
}
-fn builtin_join(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_join(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "join", args, 2, [
0, sep: ty!((string | array));
1, arr: ty!(array) => Val::Arr;
@@ -513,7 +513,7 @@
// faster
fn builtin_escape_string_json(
context: Context,
- _loc: &Option<ExprLocation>,
+ _loc: Option<&ExprLocation>,
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "escapeStringJson", args, 1, [
@@ -526,7 +526,7 @@
// faster
fn builtin_manifest_json_ex(
context: Context,
- _loc: &Option<ExprLocation>,
+ _loc: Option<&ExprLocation>,
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "manifestJsonEx", args, 2, [
@@ -541,7 +541,7 @@
}
// faster
-fn builtin_reverse(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_reverse(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "reverse", args, 1, [
0, value: ty!(array) => Val::Arr;
], {
@@ -549,7 +549,7 @@
})
}
-fn builtin_id(context: Context, _loc: &Option<ExprLocation>, args: &ArgsDesc) -> Result<Val> {
+fn builtin_id(context: Context, _loc: Option<&ExprLocation>, args: &ArgsDesc) -> Result<Val> {
parse_args!(context, "id", args, 1, [
0, v: ty!(any);
], {
@@ -560,7 +560,7 @@
// faster
fn builtin_str_replace(
context: Context,
- _loc: &Option<ExprLocation>,
+ _loc: Option<&ExprLocation>,
args: &ArgsDesc,
) -> Result<Val> {
parse_args!(context, "strReplace", args, 3, [
@@ -583,10 +583,9 @@
})
}
-#[allow(clippy::cognitive_complexity)]
pub fn call_builtin(
context: Context,
- loc: &Option<ExprLocation>,
+ loc: Option<&ExprLocation>,
name: &str,
args: &ArgsDesc,
) -> Result<Val> {
crates/jrsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate.rs
@@ -385,7 +385,7 @@
context: Context,
value: &LocExpr,
args: &ArgsDesc,
- loc: &Option<ExprLocation>,
+ loc: Option<&ExprLocation>,
tailstrict: bool,
) -> Result<Val> {
let value = evaluate(context.clone(), value)?;
@@ -430,7 +430,7 @@
BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, v1, *o, v2)?,
UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,
Var(name) => push(
- loc,
+ loc.as_ref(),
|| format!("variable <{}>", name),
|| Ok(context.binding(name.clone())?.evaluate()?),
)?,
@@ -448,7 +448,7 @@
(Val::Obj(v), Val::Str(s)) => {
let sn = s.clone();
push(
- loc,
+ loc.as_ref(),
|| format!("field <{}> access", sn),
|| {
if let Some(v) = v.get(s.clone())? {
@@ -540,14 +540,14 @@
&evaluate(context.clone(), s)?,
&Val::Obj(evaluate_object(context, t)?),
)?,
- Apply(value, args, tailstrict) => evaluate_apply(context, value, args, loc, *tailstrict)?,
+ Apply(value, args, tailstrict) => evaluate_apply(context, value, args, loc.as_ref(), *tailstrict)?,
Function(params, body) => {
evaluate_method(context, "anonymous".into(), params.clone(), body.clone())
}
Intrinsic(name) => Val::Func(Rc::new(FuncVal::Intrinsic(name.clone()))),
AssertExpr(AssertStmt(value, msg), returned) => {
let assertion_result = push(
- &value.1,
+ value.1.as_ref(),
|| "assertion condition".to_owned(),
|| {
evaluate(context.clone(), value)?
@@ -558,7 +558,7 @@
evaluate(context, returned)?
} else {
push(
- &value.1,
+ value.1.as_ref(),
|| "assertion failure".to_owned(),
|| {
if let Some(msg) = msg {
@@ -571,7 +571,7 @@
}
}
ErrorStmt(e) => push(
- loc,
+ loc.as_ref(),
|| "error statement".to_owned(),
|| {
throw!(RuntimeError(
@@ -585,7 +585,7 @@
cond_else,
} => {
if push(
- loc,
+ loc.as_ref(),
|| "if condition".to_owned(),
|| evaluate(context.clone(), &cond.0)?.try_cast_bool("in if condition"),
)? {
@@ -605,7 +605,7 @@
let import_location = Rc::make_mut(&mut tmp);
import_location.pop();
push(
- loc,
+ loc.as_ref(),
|| format!("import {:?}", path),
|| with_state(|s| s.import_file(import_location, path)),
)?
crates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function.rs
+++ b/crates/jrsonnet-evaluator/src/function.rs
@@ -160,7 +160,7 @@
throw!(IntrinsicArgumentReorderingIsNotSupportedYet);
}
}
- let $name = push(&None, || format!("evaluating argument"), || {
+ let $name = push(None, || format!("evaluating argument"), || {
let value = evaluate($ctx.clone(), &$name.1)?;
$ty.check(&value)?;
Ok(value)
crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/lib.rs
+++ b/crates/jrsonnet-evaluator/src/lib.rs
@@ -128,7 +128,7 @@
EVAL_STATE.with(|s| f(s.borrow().as_ref().unwrap()))
}
pub(crate) fn push<T>(
- e: &Option<ExprLocation>,
+ e: Option<&ExprLocation>,
frame_desc: impl FnOnce() -> String,
f: impl FnOnce() -> Result<T>,
) -> Result<T> {
crates/jrsonnet-evaluator/src/typed.rsdiffbeforeafterboth1use std::{fmt::Display, rc::Rc};23use crate::{4 error::{Error, LocError, Result},5 push, Val,6};7use jrsonnet_parser::ExprLocation;8use jrsonnet_types::{ComplexValType, ValType};9use thiserror::Error;1011#[derive(Debug, Error, Clone)]12pub enum TypeError {13 #[error("expected {0}, got {1}")]14 ExpectedGot(ComplexValType, ValType),15 #[error("missing property {0} from {1:?}")]16 MissingProperty(Rc<str>, ComplexValType),17 #[error("every failed from {0}:\n{1}")]18 UnionFailed(ComplexValType, TypeLocErrorList),19 #[error("number out of bounds: {0} not in {1:?}..{2:?}")]20 BoundsFailed(f64, Option<f64>, Option<f64>),21}22impl From<TypeError> for LocError {23 fn from(e: TypeError) -> Self {24 Error::TypeError(e.into()).into()25 }26}2728#[derive(Debug, Clone)]29pub struct TypeLocError(Box<TypeError>, ValuePathStack);30impl From<TypeError> for TypeLocError {31 fn from(e: TypeError) -> Self {32 TypeLocError(Box::new(e), ValuePathStack(Vec::new()))33 }34}35impl From<TypeLocError> for LocError {36 fn from(e: TypeLocError) -> Self {37 Error::TypeError(e).into()38 }39}40impl Display for TypeLocError {41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {42 write!(f, "{}", self.0)?;43 if !(self.1).0.is_empty() {44 write!(f, "at {}", self.1)?;45 }46 Ok(())47 }48}4950#[derive(Debug, Clone)]51pub struct TypeLocErrorList(Vec<TypeLocError>);52impl Display for TypeLocErrorList {53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {54 use std::fmt::Write;55 let mut out = String::new();56 for (i, err) in self.0.iter().enumerate() {57 if i != 0 {58 writeln!(f)?;59 }60 out.clear();61 write!(out, "{}", err)?;6263 for (i, line) in out.lines().enumerate() {64 if line.trim().len() == 0 {65 continue;66 }67 if i != 0 {68 writeln!(f)?;69 write!(f, " ")?;70 } else {71 write!(f, " - ")?;72 }73 write!(f, "{}", line)?;74 }75 }76 Ok(())77 }78}7980fn push_type(81 location: &Option<ExprLocation>,82 error_reason: impl Fn() -> String,83 path: impl Fn() -> ValuePathItem,84 item: impl Fn() -> Result<()>,85) -> Result<()> {86 push(location, error_reason, || match item() {87 Ok(_) => Ok(()),88 Err(mut e) => {89 if let Error::TypeError(e) = &mut e.error_mut() {90 (e.1).0.push(path())91 }92 Err(e)93 }94 })95}9697// TODO: check_fast for fast path of union type checking98pub trait CheckType {99 fn check(&self, value: &Val) -> Result<()>;100}101102impl CheckType for ValType {103 fn check(&self, value: &Val) -> Result<()> {104 let got = value.value_type();105 if got != *self {106 let loc_error: TypeLocError = TypeError::ExpectedGot((*self).into(), got).into();107 return Err(loc_error.into());108 }109 Ok(())110 }111}112113#[derive(Clone, Debug)]114enum ValuePathItem {115 Field(Rc<str>),116 Index(u64),117}118impl Display for ValuePathItem {119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {120 match self {121 ValuePathItem::Field(name) => write!(f, ".{}", name)?,122 ValuePathItem::Index(idx) => write!(f, "[{}]", idx)?,123 }124 Ok(())125 }126}127128#[derive(Clone, Debug)]129struct ValuePathStack(Vec<ValuePathItem>);130impl Display for ValuePathStack {131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {132 write!(f, "self")?;133 for elem in self.0.iter().rev() {134 write!(f, "{}", elem)?;135 }136 Ok(())137 }138}139140impl CheckType for ComplexValType {141 fn check(&self, value: &Val) -> Result<()> {142 match self {143 ComplexValType::Any => Ok(()),144 ComplexValType::Simple(s) => s.check(value),145 ComplexValType::Char => match value {146 Val::Str(s) if s.len() == 1 || s.chars().count() == 1 => Ok(()),147 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),148 },149 ComplexValType::BoundedNumber(from, to) => {150 if let Val::Num(n) = value {151 if from.map(|from| from > *n).unwrap_or(false)152 || to.map(|to| to <= *n).unwrap_or(false)153 {154 return Err(TypeError::BoundsFailed(*n, from.clone(), to.clone()).into());155 }156 Ok(())157 } else {158 Err(TypeError::ExpectedGot(self.clone(), value.value_type()).into())159 }160 }161 ComplexValType::Array(elem_type) => match value {162 Val::Arr(a) => {163 for (i, item) in a.iter().enumerate() {164 push_type(165 &None,166 || format!("array index {}", i),167 || ValuePathItem::Index(i as u64),168 || Ok(elem_type.check(&item.clone()?)?),169 )?;170 }171 Ok(())172 }173 v => return Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),174 },175 ComplexValType::ArrayRef(elem_type) => match value {176 Val::Arr(a) => {177 for (i, item) in a.iter().enumerate() {178 push_type(179 &None,180 || format!("array index {}", i),181 || ValuePathItem::Index(i as u64),182 || Ok(elem_type.check(&item.clone()?)?),183 )?;184 }185 Ok(())186 }187 v => return Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),188 },189 ComplexValType::ObjectRef(elems) => match value {190 Val::Obj(obj) => {191 for (k, v) in elems.iter() {192 if let Some(got_v) = obj.get((*k).into())? {193 push_type(194 &None,195 || format!("property {}", k),196 || ValuePathItem::Field((*k).into()),197 || v.check(&got_v),198 )?199 } else {200 return Err(201 TypeError::MissingProperty((*k).into(), self.clone()).into()202 );203 }204 }205 return Ok(());206 }207 v => return Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),208 },209 ComplexValType::Union(types) => {210 let mut errors = Vec::new();211 for ty in types.iter() {212 match ty.check(value) {213 Ok(()) => {214 return Ok(());215 }216 Err(e) => match e.error() {217 Error::TypeError(e) => errors.push(e.clone()),218 _ => return Err(e),219 },220 }221 }222 return Err(TypeError::UnionFailed(self.clone(), TypeLocErrorList(errors)).into());223 }224 ComplexValType::UnionRef(types) => {225 let mut errors = Vec::new();226 for ty in types.iter() {227 match ty.check(value) {228 Ok(()) => {229 return Ok(());230 }231 Err(e) => match e.error() {232 Error::TypeError(e) => errors.push(e.clone()),233 _ => return Err(e),234 },235 }236 }237 return Err(TypeError::UnionFailed(self.clone(), TypeLocErrorList(errors)).into());238 }239 ComplexValType::Sum(types) => {240 for ty in types.iter() {241 ty.check(value)?242 }243 Ok(())244 }245 ComplexValType::SumRef(types) => {246 for ty in types.iter() {247 ty.check(value)?248 }249 Ok(())250 }251 }252 }253}1use std::{fmt::Display, rc::Rc};23use crate::{4 error::{Error, LocError, Result},5 push, Val,6};7use jrsonnet_parser::ExprLocation;8use jrsonnet_types::{ComplexValType, ValType};9use thiserror::Error;1011#[derive(Debug, Error, Clone)]12pub enum TypeError {13 #[error("expected {0}, got {1}")]14 ExpectedGot(ComplexValType, ValType),15 #[error("missing property {0} from {1:?}")]16 MissingProperty(Rc<str>, ComplexValType),17 #[error("every failed from {0}:\n{1}")]18 UnionFailed(ComplexValType, TypeLocErrorList),19 #[error("number out of bounds: {0} not in {1:?}..{2:?}")]20 BoundsFailed(f64, Option<f64>, Option<f64>),21}22impl From<TypeError> for LocError {23 fn from(e: TypeError) -> Self {24 Error::TypeError(e.into()).into()25 }26}2728#[derive(Debug, Clone)]29pub struct TypeLocError(Box<TypeError>, ValuePathStack);30impl From<TypeError> for TypeLocError {31 fn from(e: TypeError) -> Self {32 TypeLocError(Box::new(e), ValuePathStack(Vec::new()))33 }34}35impl From<TypeLocError> for LocError {36 fn from(e: TypeLocError) -> Self {37 Error::TypeError(e).into()38 }39}40impl Display for TypeLocError {41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {42 write!(f, "{}", self.0)?;43 if !(self.1).0.is_empty() {44 write!(f, "at {}", self.1)?;45 }46 Ok(())47 }48}4950#[derive(Debug, Clone)]51pub struct TypeLocErrorList(Vec<TypeLocError>);52impl Display for TypeLocErrorList {53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {54 use std::fmt::Write;55 let mut out = String::new();56 for (i, err) in self.0.iter().enumerate() {57 if i != 0 {58 writeln!(f)?;59 }60 out.clear();61 write!(out, "{}", err)?;6263 for (i, line) in out.lines().enumerate() {64 if line.trim().len() == 0 {65 continue;66 }67 if i != 0 {68 writeln!(f)?;69 write!(f, " ")?;70 } else {71 write!(f, " - ")?;72 }73 write!(f, "{}", line)?;74 }75 }76 Ok(())77 }78}7980fn push_type(81 location: Option<&ExprLocation>,82 error_reason: impl Fn() -> String,83 path: impl Fn() -> ValuePathItem,84 item: impl Fn() -> Result<()>,85) -> Result<()> {86 push(location, error_reason, || match item() {87 Ok(_) => Ok(()),88 Err(mut e) => {89 if let Error::TypeError(e) = &mut e.error_mut() {90 (e.1).0.push(path())91 }92 Err(e)93 }94 })95}9697// TODO: check_fast for fast path of union type checking98pub trait CheckType {99 fn check(&self, value: &Val) -> Result<()>;100}101102impl CheckType for ValType {103 fn check(&self, value: &Val) -> Result<()> {104 let got = value.value_type();105 if got != *self {106 let loc_error: TypeLocError = TypeError::ExpectedGot((*self).into(), got).into();107 return Err(loc_error.into());108 }109 Ok(())110 }111}112113#[derive(Clone, Debug)]114enum ValuePathItem {115 Field(Rc<str>),116 Index(u64),117}118impl Display for ValuePathItem {119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {120 match self {121 ValuePathItem::Field(name) => write!(f, ".{}", name)?,122 ValuePathItem::Index(idx) => write!(f, "[{}]", idx)?,123 }124 Ok(())125 }126}127128#[derive(Clone, Debug)]129struct ValuePathStack(Vec<ValuePathItem>);130impl Display for ValuePathStack {131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {132 write!(f, "self")?;133 for elem in self.0.iter().rev() {134 write!(f, "{}", elem)?;135 }136 Ok(())137 }138}139140impl CheckType for ComplexValType {141 fn check(&self, value: &Val) -> Result<()> {142 match self {143 ComplexValType::Any => Ok(()),144 ComplexValType::Simple(s) => s.check(value),145 ComplexValType::Char => match value {146 Val::Str(s) if s.len() == 1 || s.chars().count() == 1 => Ok(()),147 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),148 },149 ComplexValType::BoundedNumber(from, to) => {150 if let Val::Num(n) = value {151 if from.map(|from| from > *n).unwrap_or(false)152 || to.map(|to| to <= *n).unwrap_or(false)153 {154 return Err(TypeError::BoundsFailed(*n, from.clone(), to.clone()).into());155 }156 Ok(())157 } else {158 Err(TypeError::ExpectedGot(self.clone(), value.value_type()).into())159 }160 }161 ComplexValType::Array(elem_type) => match value {162 Val::Arr(a) => {163 for (i, item) in a.iter().enumerate() {164 push_type(165 None,166 || format!("array index {}", i),167 || ValuePathItem::Index(i as u64),168 || Ok(elem_type.check(&item.clone()?)?),169 )?;170 }171 Ok(())172 }173 v => return Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),174 },175 ComplexValType::ArrayRef(elem_type) => match value {176 Val::Arr(a) => {177 for (i, item) in a.iter().enumerate() {178 push_type(179 None,180 || format!("array index {}", i),181 || ValuePathItem::Index(i as u64),182 || Ok(elem_type.check(&item.clone()?)?),183 )?;184 }185 Ok(())186 }187 v => return Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),188 },189 ComplexValType::ObjectRef(elems) => match value {190 Val::Obj(obj) => {191 for (k, v) in elems.iter() {192 if let Some(got_v) = obj.get((*k).into())? {193 push_type(194 None,195 || format!("property {}", k),196 || ValuePathItem::Field((*k).into()),197 || v.check(&got_v),198 )?199 } else {200 return Err(201 TypeError::MissingProperty((*k).into(), self.clone()).into()202 );203 }204 }205 return Ok(());206 }207 v => return Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),208 },209 ComplexValType::Union(types) => {210 let mut errors = Vec::new();211 for ty in types.iter() {212 match ty.check(value) {213 Ok(()) => {214 return Ok(());215 }216 Err(e) => match e.error() {217 Error::TypeError(e) => errors.push(e.clone()),218 _ => return Err(e),219 },220 }221 }222 return Err(TypeError::UnionFailed(self.clone(), TypeLocErrorList(errors)).into());223 }224 ComplexValType::UnionRef(types) => {225 let mut errors = Vec::new();226 for ty in types.iter() {227 match ty.check(value) {228 Ok(()) => {229 return Ok(());230 }231 Err(e) => match e.error() {232 Error::TypeError(e) => errors.push(e.clone()),233 _ => return Err(e),234 },235 }236 }237 return Err(TypeError::UnionFailed(self.clone(), TypeLocErrorList(errors)).into());238 }239 ComplexValType::Sum(types) => {240 for ty in types.iter() {241 ty.check(value)?242 }243 Ok(())244 }245 ComplexValType::SumRef(types) => {246 for ty in types.iter() {247 ty.check(value)?248 }249 Ok(())250 }251 }252 }253}crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -102,7 +102,7 @@
pub fn evaluate(
&self,
call_ctx: Context,
- loc: &Option<ExprLocation>,
+ loc: Option<&ExprLocation>,
args: &ArgsDesc,
tailstrict: bool,
) -> Result<Val> {