--- a/crates/jrsonnet-evaluator/src/arr/mod.rs +++ b/crates/jrsonnet-evaluator/src/arr/mod.rs @@ -1,44 +1,20 @@ -use std::rc::Rc; +use std::any::Any; use jrsonnet_gcmodule::{Cc, Trace}; use jrsonnet_interner::IBytes; use jrsonnet_parser::LocExpr; -use crate::{function::FuncVal, Context, Result, Thunk, Val}; +use crate::{function::FuncVal, gc::TraceBox, tb, Context, Result, Thunk, Val}; mod spec; -use spec::*; +pub use spec::ArrayLike; +pub(crate) use spec::*; /// Represents a Jsonnet array value. #[derive(Debug, Clone, Trace)] // may contrain other ArrValue #[trace(tracking(force))] -pub enum ArrValue { - /// Layout optimized byte array. - Bytes(BytesArray), - /// Layout optimized char array. - Chars(CharArray), - /// Every element is lazy evaluated. - Lazy(LazyArray), - /// Every element is defined somewhere in source code - Expr(ExprArray), - /// Every field is already evaluated. - Eager(EagerArray), - /// Concatenation of two arrays of any kind. - Extended(Cc), - /// Represents a integer array in form `[start, start + 1, ... end - 1, end]`. - /// This kind of arrays is generated by `std.range(start, end)` call, and used for loops. - Range(RangeArray), - /// Sliced array view. - Slice(Cc), - /// Reversed array view. - /// Returned by `std.reverse(other)` call - Reverse(Cc), - /// Returned by `std.map` call - Mapped(MappedArray), - /// Returned by `std.repeat` call - Repeated(RepeatedArray), -} +pub struct ArrValue(Cc>); pub trait ArrayLikeIter: Iterator + DoubleEndedIterator + ExactSizeIterator {} impl ArrayLikeIter for I where @@ -47,36 +23,39 @@ } impl ArrValue { + pub fn new(v: impl ArrayLike) -> Self { + Self(Cc::new(tb!(v))) + } pub fn empty() -> Self { - Self::Range(RangeArray::empty()) + Self::new(RangeArray::empty()) } pub fn expr(ctx: Context, exprs: impl IntoIterator) -> Self { - Self::Expr(ExprArray::new(ctx, exprs)) + Self::new(ExprArray::new(ctx, exprs)) } - pub fn lazy(thunks: Cc>>) -> Self { - Self::Lazy(LazyArray(thunks)) + pub fn lazy(thunks: Vec>) -> Self { + Self::new(LazyArray(thunks)) } pub fn eager(values: Vec) -> Self { - Self::Eager(EagerArray(Cc::new(values))) + Self::new(EagerArray(values)) } pub fn repeated(data: ArrValue, repeats: usize) -> Option { - Some(Self::Repeated(RepeatedArray::new(data, repeats)?)) + Some(Self::new(RepeatedArray::new(data, repeats)?)) } pub fn bytes(bytes: IBytes) -> Self { - Self::Bytes(BytesArray(bytes)) + Self::new(BytesArray(bytes)) } pub fn chars(chars: impl Iterator) -> Self { - Self::Chars(CharArray(Rc::new(chars.collect()))) + Self::new(CharArray(chars.collect())) } #[must_use] pub fn map(self, mapper: FuncVal) -> Self { - Self::Mapped(MappedArray::new(self, mapper)) + Self::new(MappedArray::new(self, mapper)) } pub fn filter(self, filter: impl Fn(&Val) -> Result) -> Result { @@ -100,7 +79,7 @@ } else if b.is_empty() { a } else if a.len() + b.len() > ARR_EXTEND_THRESHOLD { - Self::Extended(Cc::new(ExtendedArray::new(a, b))) + Self::new(ExtendedArray::new(a, b)) } else if let (Some(a), Some(b)) = (a.iter_cheap(), b.iter_cheap()) { let mut out = Vec::with_capacity(a.len() + b.len()); out.extend(a); @@ -110,15 +89,15 @@ let mut out = Vec::with_capacity(a.len() + b.len()); out.extend(a.iter_lazy()); out.extend(b.iter_lazy()); - Self::lazy(Cc::new(out)) + Self::lazy(out) } } pub fn range_exclusive(a: i32, b: i32) -> Self { - Self::Range(RangeArray::new_exclusive(a, b)) + Self::new(RangeArray::new_exclusive(a, b)) } pub fn range_inclusive(a: i32, b: i32) -> Self { - Self::Range(RangeArray::new_inclusive(a, b)) + Self::new(RangeArray::new_inclusive(a, b)) } #[must_use] @@ -136,53 +115,42 @@ if from >= to || step == 0 { return None; } - // match self { - // ArrValue::Slice(slice) => { - // return Some(Self::Slice(Cc::new(SliceArray { - // inner: slice.inner.clone(), - // from: slice.from + slice.step * (from as u32), - // to: slice.from + (to as u32) * slice.step, - // step: slice.step * step as u32, - // }))) - // } - // _ => {} - // } - Some(Self::Slice(Cc::new(SliceArray { + Some(Self::new(SliceArray { inner: self, from: from as u32, to: to as u32, step: step as u32, - }))) + })) } /// Array length. pub fn len(&self) -> usize { - pass!(self.len()) + self.0.len() } /// Is array contains no elements? pub fn is_empty(&self) -> bool { - pass!(self.is_empty()) + self.0.is_empty() } /// Get array element by index, evaluating it, if it is lazy. /// /// Returns `None` on out-of-bounds condition. pub fn get(&self, index: usize) -> Result> { - pass!(self.get(index)) + self.0.get(index) } /// Returns None if get is either non cheap, or out of bounds fn get_cheap(&self, index: usize) -> Option { - pass!(self.get_cheap(index)) + self.0.get_cheap(index) } /// Get array element by index, without evaluation. /// /// Returns `None` on out-of-bounds condition. pub fn get_lazy(&self, index: usize) -> Option> { - pass!(self.get_lazy(index)) + self.0.get_lazy(index) } pub fn iter(&self) -> impl ArrayLikeIter> + '_ { @@ -205,33 +173,20 @@ /// Return a reversed view on current array. #[must_use] pub fn reversed(self) -> Self { - Self::Reverse(Cc::new(ReverseArray(self))) + Self::new(ReverseArray(self)) } pub fn ptr_eq(a: &Self, b: &Self) -> bool { - match (a, b) { - (ArrValue::Bytes(a), ArrValue::Bytes(b)) => a.0 == b.0, - (ArrValue::Lazy(a), ArrValue::Lazy(b)) => Cc::ptr_eq(&a.0, &b.0), - (ArrValue::Expr(a), ArrValue::Expr(b)) => Cc::ptr_eq(&a.0, &b.0), - (ArrValue::Eager(a), ArrValue::Eager(b)) => Cc::ptr_eq(&a.0, &b.0), - (ArrValue::Extended(a), ArrValue::Extended(b)) => Cc::ptr_eq(a, b), - (ArrValue::Range(a), ArrValue::Range(b)) => a == b, - _ => false, - } + Cc::ptr_eq(&a.0, &b.0) } /// Is this vec supports `.get_cheap()?` pub fn is_cheap(&self) -> bool { - match self { - ArrValue::Eager(_) | ArrValue::Range(..) | ArrValue::Bytes(_) | ArrValue::Chars(_) => { - true - } - ArrValue::Extended(v) => v.a.is_cheap() && v.b.is_cheap(), - ArrValue::Slice(r) => r.inner.is_cheap(), - ArrValue::Reverse(i) => i.0.is_cheap(), - ArrValue::Repeated(v) => v.is_cheap(), - ArrValue::Expr(_) | ArrValue::Lazy(_) | ArrValue::Mapped(_) => false, - } + self.0.is_cheap() + } + + pub fn as_any(&self) -> &dyn Any { + &self.0 } } impl From> for ArrValue { @@ -241,7 +196,7 @@ } impl From>> for ArrValue { fn from(value: Vec>) -> Self { - Self::lazy(Cc::new(value)) + Self::lazy(value) } } impl FromIterator for ArrValue { @@ -249,6 +204,27 @@ Self::eager(iter.into_iter().collect()) } } +impl ArrayLike for ArrValue { + fn len(&self) -> usize { + self.0.len() + } + fn get(&self, index: usize) -> Result> { + self.0.get(index) + } + + fn get_lazy(&self, index: usize) -> Option> { + self.0.get_lazy(index) + } + + fn get_cheap(&self, index: usize) -> Option { + self.0.get_cheap(index) + } + + fn is_cheap(&self) -> bool { + self.0.is_cheap() + } +} + #[cfg(target_pointer_width = "64")] -static_assertions::assert_eq_size!(ArrValue, [u8; 16]); +static_assertions::assert_eq_size!(ArrValue, [u8; 8]); --- a/crates/jrsonnet-evaluator/src/arr/spec.rs +++ b/crates/jrsonnet-evaluator/src/arr/spec.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, iter, mem::replace, rc::Rc}; +use std::{any::Any, cell::RefCell, fmt::Debug, iter, mem::replace}; use jrsonnet_gcmodule::{Cc, Trace}; use jrsonnet_interner::{IBytes, IStr}; @@ -13,7 +13,7 @@ Context, Error, Result, Thunk, Val, }; -pub trait ArrayLike: Sized + Into { +pub trait ArrayLike: Any + Trace + Debug { fn len(&self) -> usize; fn is_empty(&self) -> bool { self.len() == 0 @@ -22,12 +22,10 @@ fn get_lazy(&self, index: usize) -> Option>; fn get_cheap(&self, index: usize) -> Option; - fn reverse(self) -> ArrValue { - ArrValue::Reverse(Cc::new(ReverseArray(self.into()))) - } + fn is_cheap(&self) -> bool; } -#[derive(Debug, Clone, Trace)] +#[derive(Debug, Trace)] pub struct SliceArray { pub(crate) inner: ArrValue, pub(crate) from: u32, @@ -81,15 +79,13 @@ fn get_cheap(&self, index: usize) -> Option { self.iter_cheap()?.nth(index) } -} -impl From for ArrValue { - fn from(value: SliceArray) -> Self { - Self::Slice(Cc::new(value)) + fn is_cheap(&self) -> bool { + self.inner.is_cheap() } } -#[derive(Trace, Debug, Clone)] -pub struct CharArray(pub Rc>); +#[derive(Trace, Debug)] +pub struct CharArray(pub Vec); impl ArrayLike for CharArray { fn len(&self) -> usize { self.0.len() @@ -108,14 +104,12 @@ .get(index) .map(|v| Val::Str(StrValue::Flat(IStr::from(*v)))) } -} -impl From for ArrValue { - fn from(value: CharArray) -> Self { - ArrValue::Chars(value) + fn is_cheap(&self) -> bool { + true } } -#[derive(Trace, Debug, Clone)] +#[derive(Trace, Debug)] pub struct BytesArray(pub IBytes); impl ArrayLike for BytesArray { fn len(&self) -> usize { @@ -133,10 +127,8 @@ fn get_cheap(&self, index: usize) -> Option { self.0.get(index).map(|v| Val::Num(f64::from(*v))) } -} -impl From for ArrValue { - fn from(value: BytesArray) -> Self { - ArrValue::Bytes(value) + fn is_cheap(&self) -> bool { + true } } @@ -148,30 +140,30 @@ Pending, } -#[derive(Debug, Trace)] -pub struct ExprArrayInner { +#[derive(Debug, Trace, Clone)] +pub struct ExprArray { ctx: Context, - cached: RefCell>>, + cached: Cc>>>, } -#[derive(Debug, Trace, Clone)] -pub struct ExprArray(pub Cc); impl ExprArray { pub fn new(ctx: Context, items: impl IntoIterator) -> Self { - Self(Cc::new(ExprArrayInner { + Self { ctx, - cached: RefCell::new(items.into_iter().map(ArrayThunk::Waiting).collect()), - })) + cached: Cc::new(RefCell::new( + items.into_iter().map(ArrayThunk::Waiting).collect(), + )), + } } } impl ArrayLike for ExprArray { fn len(&self) -> usize { - self.0.cached.borrow().len() + self.cached.borrow().len() } fn get(&self, index: usize) -> Result> { if index >= self.len() { return Ok(None); } - match &self.0.cached.borrow()[index] { + match &self.cached.borrow()[index] { ArrayThunk::Computed(c) => return Ok(Some(c.clone())), ArrayThunk::Errored(e) => return Err(e.clone()), ArrayThunk::Pending => return Err(InfiniteRecursionDetected.into()), @@ -179,19 +171,19 @@ }; let ArrayThunk::Waiting(expr) = - replace(&mut self.0.cached.borrow_mut()[index], ArrayThunk::Pending) + replace(&mut self.cached.borrow_mut()[index], ArrayThunk::Pending) else { unreachable!() }; - let new_value = match evaluate(self.0.ctx.clone(), &expr) { + let new_value = match evaluate(self.ctx.clone(), &expr) { Ok(v) => v, Err(e) => { - self.0.cached.borrow_mut()[index] = ArrayThunk::Errored(e.clone()); + self.cached.borrow_mut()[index] = ArrayThunk::Errored(e.clone()); return Err(e); } }; - self.0.cached.borrow_mut()[index] = ArrayThunk::Computed(new_value.clone()); + self.cached.borrow_mut()[index] = ArrayThunk::Computed(new_value.clone()); Ok(Some(new_value)) } fn get_lazy(&self, index: usize) -> Option> { @@ -215,7 +207,7 @@ if index >= self.len() { return None; } - match &self.0.cached.borrow()[index] { + match &self.cached.borrow()[index] { ArrayThunk::Computed(c) => return Some(Thunk::evaluated(c.clone())), ArrayThunk::Errored(e) => return Some(Thunk::errored(e.clone())), ArrayThunk::Waiting(_) | ArrayThunk::Pending => {} @@ -229,14 +221,12 @@ fn get_cheap(&self, _index: usize) -> Option { None } -} -impl From for ArrValue { - fn from(value: ExprArray) -> Self { - Self::Expr(value) + fn is_cheap(&self) -> bool { + false } } -#[derive(Trace, Debug, Clone)] +#[derive(Trace, Debug)] pub struct ExtendedArray { pub a: ArrValue, pub b: ArrValue, @@ -319,15 +309,13 @@ self.b.get_cheap(index - self.split) } } -} -impl From for ArrValue { - fn from(value: ExtendedArray) -> Self { - Self::Extended(Cc::new(value)) + fn is_cheap(&self) -> bool { + self.a.is_cheap() && self.b.is_cheap() } } -#[derive(Trace, Debug, Clone)] -pub struct LazyArray(pub Cc>>); +#[derive(Trace, Debug)] +pub struct LazyArray(pub Vec>); impl ArrayLike for LazyArray { fn len(&self) -> usize { self.0.len() @@ -344,15 +332,13 @@ fn get_lazy(&self, index: usize) -> Option> { self.0.get(index).cloned() } -} -impl From for ArrValue { - fn from(value: LazyArray) -> Self { - Self::Lazy(value) + fn is_cheap(&self) -> bool { + false } } -#[derive(Trace, Debug, Clone)] -pub struct EagerArray(pub Cc>); +#[derive(Trace, Debug)] +pub struct EagerArray(pub Vec); impl ArrayLike for EagerArray { fn len(&self) -> usize { self.0.len() @@ -369,15 +355,13 @@ fn get_cheap(&self, index: usize) -> Option { self.0.get(index).cloned() } -} -impl From for ArrValue { - fn from(value: EagerArray) -> Self { - Self::Eager(value) + fn is_cheap(&self) -> bool { + true } } /// Inclusive range type -#[derive(Debug, Trace, Clone, PartialEq, Eq)] +#[derive(Debug, Trace, PartialEq, Eq)] pub struct RangeArray { start: i32, end: i32, @@ -422,14 +406,12 @@ fn get_cheap(&self, index: usize) -> Option { self.range().nth(index).map(|i| Val::Num(f64::from(i))) } -} -impl From for ArrValue { - fn from(value: RangeArray) -> Self { - Self::Range(value) + fn is_cheap(&self) -> bool { + true } } -#[derive(Debug, Trace, Clone)] +#[derive(Debug, Trace)] pub struct ReverseArray(pub ArrValue); impl ArrayLike for ReverseArray { fn len(&self) -> usize { @@ -447,44 +429,37 @@ fn get_cheap(&self, index: usize) -> Option { self.0.get_cheap(self.0.len() - index - 1) } - fn reverse(self) -> ArrValue { - self.0 - } -} -impl From for ArrValue { - fn from(value: ReverseArray) -> Self { - Self::Reverse(Cc::new(value)) + fn is_cheap(&self) -> bool { + self.0.is_cheap() } } -#[derive(Trace, Debug)] -pub struct MappedArrayInner { +#[derive(Trace, Debug, Clone)] +pub struct MappedArray { inner: ArrValue, - cached: RefCell>>, + cached: Cc>>>, mapper: FuncVal, } -#[derive(Trace, Debug, Clone)] -pub struct MappedArray(Cc); impl MappedArray { pub fn new(inner: ArrValue, mapper: FuncVal) -> Self { let len = inner.len(); - Self(Cc::new(MappedArrayInner { + Self { inner, - cached: RefCell::new(vec![ArrayThunk::Waiting(()); len]), + cached: Cc::new(RefCell::new(vec![ArrayThunk::Waiting(()); len])), mapper, - })) + } } } impl ArrayLike for MappedArray { fn len(&self) -> usize { - self.0.cached.borrow().len() + self.cached.borrow().len() } fn get(&self, index: usize) -> Result> { if index >= self.len() { return Ok(None); } - match &self.0.cached.borrow()[index] { + match &self.cached.borrow()[index] { ArrayThunk::Computed(c) => return Ok(Some(c.clone())), ArrayThunk::Errored(e) => return Err(e.clone()), ArrayThunk::Pending => return Err(InfiniteRecursionDetected.into()), @@ -492,27 +467,26 @@ }; let ArrayThunk::Waiting(_) = - replace(&mut self.0.cached.borrow_mut()[index], ArrayThunk::Pending) + replace(&mut self.cached.borrow_mut()[index], ArrayThunk::Pending) else { unreachable!() }; let val = self - .0 .inner .get(index) .transpose() .expect("index checked") - .and_then(|r| self.0.mapper.evaluate_simple(&(r,), false)); + .and_then(|r| self.mapper.evaluate_simple(&(r,), false)); let new_value = match val { Ok(v) => v, Err(e) => { - self.0.cached.borrow_mut()[index] = ArrayThunk::Errored(e.clone()); + self.cached.borrow_mut()[index] = ArrayThunk::Errored(e.clone()); return Err(e); } }; - self.0.cached.borrow_mut()[index] = ArrayThunk::Computed(new_value.clone()); + self.cached.borrow_mut()[index] = ArrayThunk::Computed(new_value.clone()); Ok(Some(new_value)) } fn get_lazy(&self, index: usize) -> Option> { @@ -536,7 +510,7 @@ if index >= self.len() { return None; } - match &self.0.cached.borrow()[index] { + match &self.cached.borrow()[index] { ArrayThunk::Computed(c) => return Some(Thunk::evaluated(c.clone())), ArrayThunk::Errored(e) => return Some(Thunk::errored(e.clone())), ArrayThunk::Waiting(_) | ArrayThunk::Pending => {} @@ -551,82 +525,54 @@ fn get_cheap(&self, _index: usize) -> Option { None } -} -impl From for ArrValue { - fn from(value: MappedArray) -> Self { - Self::Mapped(value) + fn is_cheap(&self) -> bool { + false } } #[derive(Trace, Debug)] -pub struct RepeatedArrayInner { +pub struct RepeatedArray { data: ArrValue, repeats: usize, total_len: usize, } -#[derive(Trace, Debug, Clone)] -pub struct RepeatedArray(Cc); impl RepeatedArray { pub fn new(data: ArrValue, repeats: usize) -> Option { let total_len = data.len().checked_mul(repeats)?; - Some(Self(Cc::new(RepeatedArrayInner { + Some(Self { data, repeats, total_len, - }))) - } - pub fn is_cheap(&self) -> bool { - self.0.data.is_cheap() + }) } } impl ArrayLike for RepeatedArray { fn len(&self) -> usize { - self.0.total_len + self.total_len } fn get(&self, index: usize) -> Result> { - if index > self.0.total_len { + if index > self.total_len { return Ok(None); } - self.0.data.get(index % self.0.data.len()) + self.data.get(index % self.data.len()) } fn get_lazy(&self, index: usize) -> Option> { - if index > self.0.total_len { + if index > self.total_len { return None; } - self.0.data.get_lazy(index % self.0.data.len()) + self.data.get_lazy(index % self.data.len()) } fn get_cheap(&self, index: usize) -> Option { - if index > self.0.total_len { + if index > self.total_len { return None; } - self.0.data.get_cheap(index % self.0.data.len()) + self.data.get_cheap(index % self.data.len()) } -} -impl From for ArrValue { - fn from(value: RepeatedArray) -> Self { - Self::Repeated(value) + fn is_cheap(&self) -> bool { + self.data.is_cheap() } } - -macro_rules! pass { - ($t:ident.$m:ident($($ident:ident),*)) => { - match $t { - Self::Bytes(e) => e.$m($($ident)*), - Self::Chars(e) => e.$m($($ident)*), - Self::Expr(e) => e.$m($($ident)*), - Self::Lazy(e) => e.$m($($ident)*), - Self::Eager(e) => e.$m($($ident)*), - Self::Range(e) => e.$m($($ident)*), - Self::Slice(e) => e.$m($($ident)*), - Self::Extended(e) => e.$m($($ident)*), - Self::Reverse(e) => e.$m($($ident)*), - Self::Mapped(e) => e.$m($($ident)*), - Self::Repeated(e) => e.$m($($ident)*), - } - }; -} -pub(super) use pass; --- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs +++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs @@ -573,10 +573,10 @@ evaluate(self.ctx, &self.item) } } - Val::Arr(ArrValue::lazy(Cc::new(vec![Thunk::new(ArrayElement { + Val::Arr(ArrValue::lazy(vec![Thunk::new(ArrayElement { ctx, item: items[0].clone(), - })]))) + })])) } else { Val::Arr(ArrValue::expr(ctx, items.iter().cloned())) } --- a/crates/jrsonnet-evaluator/src/obj.rs +++ b/crates/jrsonnet-evaluator/src/obj.rs @@ -17,7 +17,7 @@ operator::evaluate_add_op, tb, throw, val::ThunkValue, - MaybeUnbound, Result, ResultExt, State, Thunk, Unbound, Val, + MaybeUnbound, Result, State, Thunk, Unbound, Val, }; #[cfg(not(feature = "exp-preserve-order"))] --- a/crates/jrsonnet-evaluator/src/typed/conversions.rs +++ b/crates/jrsonnet-evaluator/src/typed/conversions.rs @@ -6,7 +6,7 @@ use jrsonnet_types::{ComplexValType, ValType}; use crate::{ - arr::ArrValue, + arr::{ArrValue, BytesArray}, error::Result, function::{native::NativeDesc, FuncDesc, FuncVal}, throw, @@ -434,12 +434,13 @@ } fn from_untyped(value: Val) -> Result { - if let Val::Arr(ArrValue::Bytes(bytes)) = value { - return Ok(bytes.0); - } - ::TYPE.check(&value)?; - match value { + match &value { Val::Arr(a) => { + if let Some(bytes) = a.as_any().downcast_ref::() { + return Ok(bytes.0.as_slice().into()); + }; + ::TYPE.check(&value)?; + // Any::downcast_ref::(&a); let mut out = Vec::with_capacity(a.len()); for e in a.iter() { let r = e?; @@ -447,7 +448,10 @@ } Ok(out.as_slice().into()) } - _ => unreachable!(), + _ => { + ::TYPE.check(&value)?; + unreachable!() + } } } } --- a/crates/jrsonnet-evaluator/src/val.rs +++ b/crates/jrsonnet-evaluator/src/val.rs @@ -9,7 +9,7 @@ use jrsonnet_interner::IStr; use jrsonnet_types::ValType; -pub use crate::arr::ArrValue; +pub use crate::arr::{ArrValue, ArrayLike}; use crate::{ error::{Error, ErrorKind::*}, function::FuncVal, --- a/crates/jrsonnet-stdlib/src/sets.rs +++ b/crates/jrsonnet-stdlib/src/sets.rs @@ -7,7 +7,6 @@ val::ArrValue, Thunk, Val, }; -use jrsonnet_gcmodule::Cc; use jrsonnet_parser::BinaryOpType; #[builtin] @@ -70,5 +69,5 @@ } }; } - Ok(ArrValue::lazy(Cc::new(out))) + Ok(ArrValue::lazy(out)) } --- a/crates/jrsonnet-stdlib/src/sort.rs +++ b/crates/jrsonnet-stdlib/src/sort.rs @@ -10,7 +10,6 @@ val::{equals, ArrValue}, Thunk, Val, }; -use jrsonnet_gcmodule::Cc; use jrsonnet_parser::BinaryOpType; use crate::eval_on_empty; @@ -136,7 +135,7 @@ values.iter().collect::>>()?, )?)) } else { - Ok(ArrValue::lazy(Cc::new(sort_keyf(values, key_getter)?))) + Ok(ArrValue::lazy(sort_keyf(values, key_getter)?)) } } @@ -186,7 +185,7 @@ arr.iter().collect::>>()?, )?)) } else { - Ok(ArrValue::lazy(Cc::new(uniq_keyf(arr, keyF)?))) + Ok(ArrValue::lazy(uniq_keyf(arr, keyF)?)) } } @@ -204,8 +203,8 @@ Ok(ArrValue::eager(arr)) } else { let arr = sort_keyf(arr, keyF.clone())?; - let arr = uniq_keyf(ArrValue::lazy(Cc::new(arr)), keyF)?; - Ok(ArrValue::lazy(Cc::new(arr))) + let arr = uniq_keyf(ArrValue::lazy(arr), keyF)?; + Ok(ArrValue::lazy(arr)) } }