git.delta.rocks / jrsonnet / refs/commits / 9f4360cc82b9

difftreelog

refactor drop array iteration inlining

Yaroslav Bolyukin2023-07-26parent: #992351c.patch.diff
in: master

3 files changed

modifiedCargo.tomldiffbeforeafterboth
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,6 +3,7 @@
 package.repository = "https://github.com/CertainLach/jrsonnet"
 members = ["crates/*", "bindings/jsonnet", "cmds/jrsonnet", "tests"]
 default-members = ["cmds/jrsonnet"]
+resolver = "2"
 
 [workspace.dependencies]
 jrsonnet-evaluator = { path = "./crates/jrsonnet-evaluator", version = "0.5.0-pre9" }
modifiedcrates/jrsonnet-evaluator/src/arr/mod.rsdiffbeforeafterboth
after · crates/jrsonnet-evaluator/src/arr/mod.rs
1use std::rc::Rc;23use jrsonnet_gcmodule::{Cc, Trace};4use jrsonnet_interner::IBytes;5use jrsonnet_parser::LocExpr;67use crate::{function::FuncVal, Context, Result, Thunk, Val};89mod spec;10use spec::*;1112/// Represents a Jsonnet array value.13#[derive(Debug, Clone, Trace)]14// may contrain other ArrValue15#[trace(tracking(force))]16pub enum ArrValue {17	/// Layout optimized byte array.18	Bytes(BytesArray),19	/// Layout optimized char array.20	Chars(CharArray),21	/// Every element is lazy evaluated.22	Lazy(LazyArray),23	/// Every element is defined somewhere in source code24	Expr(ExprArray),25	/// Every field is already evaluated.26	Eager(EagerArray),27	/// Concatenation of two arrays of any kind.28	Extended(Cc<ExtendedArray>),29	/// Represents a integer array in form `[start, start + 1, ... end - 1, end]`.30	/// This kind of arrays is generated by `std.range(start, end)` call, and used for loops.31	Range(RangeArray),32	/// Sliced array view.33	Slice(Cc<SliceArray>),34	/// Reversed array view.35	/// Returned by `std.reverse(other)` call36	Reverse(Cc<ReverseArray>),37	/// Returned by `std.map` call38	Mapped(MappedArray),39	/// Returned by `std.repeat` call40	Repeated(RepeatedArray),41}4243pub trait ArrayLikeIter<T>: Iterator<Item = T> + DoubleEndedIterator + ExactSizeIterator {}44impl<I, T> ArrayLikeIter<T> for I where45	I: Iterator<Item = T> + DoubleEndedIterator + ExactSizeIterator46{47}4849impl ArrValue {50	pub fn empty() -> Self {51		Self::Range(RangeArray::empty())52	}5354	pub fn expr(ctx: Context, exprs: impl IntoIterator<Item = LocExpr>) -> Self {55		Self::Expr(ExprArray::new(ctx, exprs))56	}5758	pub fn lazy(thunks: Cc<Vec<Thunk<Val>>>) -> Self {59		Self::Lazy(LazyArray(thunks))60	}6162	pub fn eager(values: Vec<Val>) -> Self {63		Self::Eager(EagerArray(Cc::new(values)))64	}6566	pub fn repeated(data: ArrValue, repeats: usize) -> Option<Self> {67		Some(Self::Repeated(RepeatedArray::new(data, repeats)?))68	}6970	pub fn bytes(bytes: IBytes) -> Self {71		Self::Bytes(BytesArray(bytes))72	}73	pub fn chars(chars: impl Iterator<Item = char>) -> Self {74		Self::Chars(CharArray(Rc::new(chars.collect())))75	}7677	#[must_use]78	pub fn map(self, mapper: FuncVal) -> Self {79		Self::Mapped(MappedArray::new(self, mapper))80	}8182	pub fn filter(self, filter: impl Fn(&Val) -> Result<bool>) -> Result<Self> {83		// TODO: ArrValue::Picked(inner, indexes) for large arrays84		let mut out = Vec::new();85		for i in self.iter() {86			let i = i?;87			if filter(&i)? {88				out.push(i);89			};90		}91		Ok(Self::eager(out))92	}9394	pub fn extended(a: ArrValue, b: ArrValue) -> Self {95		// TODO: benchmark for an optimal value, currently just a arbitrary choice96		const ARR_EXTEND_THRESHOLD: usize = 100;9798		if a.is_empty() {99			b100		} else if b.is_empty() {101			a102		} else if a.len() + b.len() > ARR_EXTEND_THRESHOLD {103			Self::Extended(Cc::new(ExtendedArray::new(a, b)))104		} else if let (Some(a), Some(b)) = (a.iter_cheap(), b.iter_cheap()) {105			let mut out = Vec::with_capacity(a.len() + b.len());106			out.extend(a);107			out.extend(b);108			Self::eager(out)109		} else {110			let mut out = Vec::with_capacity(a.len() + b.len());111			out.extend(a.iter_lazy());112			out.extend(b.iter_lazy());113			Self::lazy(Cc::new(out))114		}115	}116117	pub fn range_exclusive(a: i32, b: i32) -> Self {118		Self::Range(RangeArray::new_exclusive(a, b))119	}120	pub fn range_inclusive(a: i32, b: i32) -> Self {121		Self::Range(RangeArray::new_inclusive(a, b))122	}123124	#[must_use]125	pub fn slice(126		self,127		from: Option<usize>,128		to: Option<usize>,129		step: Option<usize>,130	) -> Option<Self> {131		let len = self.len();132		let from = from.unwrap_or(0);133		let to = to.unwrap_or(len).min(len);134		let step = step.unwrap_or(1);135136		if from >= to || step == 0 {137			return None;138		}139		// match self {140		// 	ArrValue::Slice(slice) => {141		// 		return Some(Self::Slice(Cc::new(SliceArray {142		// 			inner: slice.inner.clone(),143		// 			from: slice.from + slice.step * (from as u32),144		// 			to: slice.from + (to as u32) * slice.step,145		// 			step: slice.step * step as u32,146		// 		})))147		// 	}148		// 	_ => {}149		// }150151		Some(Self::Slice(Cc::new(SliceArray {152			inner: self,153			from: from as u32,154			to: to as u32,155			step: step as u32,156		})))157	}158159	/// Array length.160	pub fn len(&self) -> usize {161		pass!(self.len())162	}163164	/// Is array contains no elements?165	pub fn is_empty(&self) -> bool {166		pass!(self.is_empty())167	}168169	/// Get array element by index, evaluating it, if it is lazy.170	///171	/// Returns `None` on out-of-bounds condition.172	pub fn get(&self, index: usize) -> Result<Option<Val>> {173		pass!(self.get(index))174	}175176	/// Returns None if get is either non cheap, or out of bounds177	fn get_cheap(&self, index: usize) -> Option<Val> {178		pass!(self.get_cheap(index))179	}180181	/// Get array element by index, without evaluation.182	///183	/// Returns `None` on out-of-bounds condition.184	pub fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {185		pass!(self.get_lazy(index))186	}187188	pub fn iter(&self) -> impl ArrayLikeIter<Result<Val>> + '_ {189		(0..self.len()).map(|i| self.get(i).transpose().expect("length checked"))190	}191192	/// Iterate over elements, returning lazy values.193	pub fn iter_lazy(&self) -> impl ArrayLikeIter<Thunk<Val>> + '_ {194		(0..self.len()).map(|i| self.get_lazy(i).expect("length checked"))195	}196197	pub fn iter_cheap(&self) -> Option<impl ArrayLikeIter<Val> + '_> {198		if self.is_cheap() {199			Some((0..self.len()).map(|i| self.get_cheap(i).expect("length and is_cheap checked")))200		} else {201			None202		}203	}204205	/// Return a reversed view on current array.206	#[must_use]207	pub fn reversed(self) -> Self {208		Self::Reverse(Cc::new(ReverseArray(self)))209	}210211	pub fn ptr_eq(a: &Self, b: &Self) -> bool {212		match (a, b) {213			(ArrValue::Bytes(a), ArrValue::Bytes(b)) => a.0 == b.0,214			(ArrValue::Lazy(a), ArrValue::Lazy(b)) => Cc::ptr_eq(&a.0, &b.0),215			(ArrValue::Expr(a), ArrValue::Expr(b)) => Cc::ptr_eq(&a.0, &b.0),216			(ArrValue::Eager(a), ArrValue::Eager(b)) => Cc::ptr_eq(&a.0, &b.0),217			(ArrValue::Extended(a), ArrValue::Extended(b)) => Cc::ptr_eq(a, b),218			(ArrValue::Range(a), ArrValue::Range(b)) => a == b,219			_ => false,220		}221	}222223	/// Is this vec supports `.get_cheap()?`224	pub fn is_cheap(&self) -> bool {225		match self {226			ArrValue::Eager(_) | ArrValue::Range(..) | ArrValue::Bytes(_) | ArrValue::Chars(_) => {227				true228			}229			ArrValue::Extended(v) => v.a.is_cheap() && v.b.is_cheap(),230			ArrValue::Slice(r) => r.inner.is_cheap(),231			ArrValue::Reverse(i) => i.0.is_cheap(),232			ArrValue::Repeated(v) => v.is_cheap(),233			ArrValue::Expr(_) | ArrValue::Lazy(_) | ArrValue::Mapped(_) => false,234		}235	}236}237impl From<Vec<Val>> for ArrValue {238	fn from(value: Vec<Val>) -> Self {239		Self::eager(value)240	}241}242impl From<Vec<Thunk<Val>>> for ArrValue {243	fn from(value: Vec<Thunk<Val>>) -> Self {244		Self::lazy(Cc::new(value))245	}246}247impl FromIterator<Val> for ArrValue {248	fn from_iter<T: IntoIterator<Item = Val>>(iter: T) -> Self {249		Self::eager(iter.into_iter().collect())250	}251}252253#[cfg(target_pointer_width = "64")]254static_assertions::assert_eq_size!(ArrValue, [u8; 16]);
modifiedcrates/jrsonnet-evaluator/src/arr/spec.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/arr/spec.rs
+++ b/crates/jrsonnet-evaluator/src/arr/spec.rs
@@ -1,6 +1,3 @@
-//! Those implementations are a bit sketchy, as this is mostly performance experiments
-//! of not yet finished nightly rust features
-
 use std::{cell::RefCell, iter, mem::replace, rc::Rc};
 
 use jrsonnet_gcmodule::{Cc, Trace};
@@ -17,19 +14,6 @@
 };
 
 pub trait ArrayLike: Sized + Into<ArrValue> {
-	#[cfg(feature = "nightly")]
-	type Iter<'t>
-	where
-		Self: 't;
-	#[cfg(feature = "nightly")]
-	type IterLazy<'t>
-	where
-		Self: 't;
-	#[cfg(feature = "nightly")]
-	type IterCheap<'t>
-	where
-		Self: 't;
-
 	fn len(&self) -> usize;
 	fn is_empty(&self) -> bool {
 		self.len() == 0
@@ -37,13 +21,6 @@
 	fn get(&self, index: usize) -> Result<Option<Val>>;
 	fn get_lazy(&self, index: usize) -> Option<Thunk<Val>>;
 	fn get_cheap(&self, index: usize) -> Option<Val>;
-	#[cfg(feature = "nightly")]
-	#[allow(clippy::iter_not_returning_iterator)]
-	fn iter(&self) -> Self::Iter<'_>;
-	#[cfg(feature = "nightly")]
-	fn iter_lazy(&self) -> Self::IterLazy<'_>;
-	#[cfg(feature = "nightly")]
-	fn iter_cheap(&self) -> Option<Self::IterCheap<'_>>;
 
 	fn reverse(self) -> ArrValue {
 		ArrValue::Reverse(Cc::new(ReverseArray(self.into())))
@@ -59,7 +36,6 @@
 }
 
 impl SliceArray {
-	#[cfg(not(feature = "nightly"))]
 	fn iter(&self) -> impl Iterator<Item = Result<Val>> + '_ {
 		self.inner
 			.iter()
@@ -68,7 +44,6 @@
 			.step_by(self.step as usize)
 	}
 
-	#[cfg(not(feature = "nightly"))]
 	fn iter_lazy(&self) -> impl Iterator<Item = Thunk<Val>> + '_ {
 		self.inner
 			.iter_lazy()
@@ -77,7 +52,6 @@
 			.step_by(self.step as usize)
 	}
 
-	#[cfg(not(feature = "nightly"))]
 	fn iter_cheap(&self) -> Option<impl crate::arr::ArrayLikeIter<Val> + '_> {
 		Some(
 			self.inner
@@ -88,20 +62,7 @@
 		)
 	}
 }
-#[cfg(feature = "nightly")]
-type SliceArrayIter<'t> = impl DoubleEndedIterator<Item = Result<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type SliceArrayLazyIter<'t> = impl DoubleEndedIterator<Item = Thunk<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type SliceArrayCheapIter<'t> = impl DoubleEndedIterator<Item = Val> + ExactSizeIterator + 't;
 impl ArrayLike for SliceArray {
-	#[cfg(feature = "nightly")]
-	type Iter<'t> = SliceArrayIter<'t>;
-	#[cfg(feature = "nightly")]
-	type IterLazy<'t> = SliceArrayLazyIter<'t>;
-	#[cfg(feature = "nightly")]
-	type IterCheap<'t> = SliceArrayCheapIter<'t>;
-
 	fn len(&self) -> usize {
 		iter::repeat(())
 			.take((self.to - self.from) as usize)
@@ -120,35 +81,6 @@
 	fn get_cheap(&self, index: usize) -> Option<Val> {
 		self.iter_cheap()?.nth(index)
 	}
-
-	#[cfg(feature = "nightly")]
-	fn iter(&self) -> SliceArrayIter<'_> {
-		self.inner
-			.iter()
-			.skip(self.from as usize)
-			.take((self.to - self.from) as usize)
-			.step_by(self.step as usize)
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_lazy(&self) -> SliceArrayLazyIter<'_> {
-		self.inner
-			.iter_lazy()
-			.skip(self.from as usize)
-			.take((self.to - self.from) as usize)
-			.step_by(self.step as usize)
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_cheap(&self) -> Option<SliceArrayCheapIter<'_>> {
-		Some(
-			self.inner
-				.iter_cheap()?
-				.skip(self.from as usize)
-				.take((self.to - self.from) as usize)
-				.step_by(self.step as usize),
-		)
-	}
 }
 impl From<SliceArray> for ArrValue {
 	fn from(value: SliceArray) -> Self {
@@ -158,20 +90,7 @@
 
 #[derive(Trace, Debug, Clone)]
 pub struct CharArray(pub Rc<Vec<char>>);
-#[cfg(feature = "nightly")]
-type CharArrayIter<'t> = impl DoubleEndedIterator<Item = Result<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type CharArrayLazyIter<'t> = impl DoubleEndedIterator<Item = Thunk<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type CharArrayCheapIter<'t> = impl DoubleEndedIterator<Item = Val> + ExactSizeIterator + 't;
 impl ArrayLike for CharArray {
-	#[cfg(feature = "nightly")]
-	type Iter<'t> = CharArrayIter<'t>;
-	#[cfg(feature = "nightly")]
-	type IterLazy<'t> = CharArrayLazyIter<'t>;
-	#[cfg(feature = "nightly")]
-	type IterCheap<'t> = CharArrayCheapIter<'t>;
-
 	fn len(&self) -> usize {
 		self.0.len()
 	}
@@ -188,30 +107,7 @@
 		self.0
 			.get(index)
 			.map(|v| Val::Str(StrValue::Flat(IStr::from(*v))))
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter(&self) -> CharArrayIter<'_> {
-		self.0
-			.iter()
-			.map(|v| Ok(Val::Str(StrValue::Flat(IStr::from(*v)))))
 	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_lazy(&self) -> CharArrayLazyIter<'_> {
-		self.0
-			.iter()
-			.map(|v| Thunk::evaluated(Val::Str(StrValue::Flat(IStr::from(*v)))))
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_cheap(&self) -> Option<CharArrayCheapIter<'_>> {
-		Some(
-			self.0
-				.iter()
-				.map(|v| Val::Str(StrValue::Flat(IStr::from(*v)))),
-		)
-	}
 }
 impl From<CharArray> for ArrValue {
 	fn from(value: CharArray) -> Self {
@@ -221,20 +117,7 @@
 
 #[derive(Trace, Debug, Clone)]
 pub struct BytesArray(pub IBytes);
-#[cfg(feature = "nightly")]
-type BytesArrayIter<'t> = impl DoubleEndedIterator<Item = Result<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type BytesArrayLazyIter<'t> = impl DoubleEndedIterator<Item = Thunk<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type BytesArrayCheapIter<'t> = impl DoubleEndedIterator<Item = Val> + ExactSizeIterator + 't;
 impl ArrayLike for BytesArray {
-	#[cfg(feature = "nightly")]
-	type Iter<'t> = BytesArrayIter<'t>;
-	#[cfg(feature = "nightly")]
-	type IterLazy<'t> = BytesArrayLazyIter<'t>;
-	#[cfg(feature = "nightly")]
-	type IterCheap<'t> = BytesArrayCheapIter<'t>;
-
 	fn len(&self) -> usize {
 		self.0.len()
 	}
@@ -250,23 +133,6 @@
 	fn get_cheap(&self, index: usize) -> Option<Val> {
 		self.0.get(index).map(|v| Val::Num(f64::from(*v)))
 	}
-
-	#[cfg(feature = "nightly")]
-	fn iter(&self) -> BytesArrayIter<'_> {
-		self.0.iter().map(|v| Ok(Val::Num(f64::from(*v))))
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_lazy(&self) -> BytesArrayLazyIter<'_> {
-		self.0
-			.iter()
-			.map(|v| Thunk::evaluated(Val::Num(f64::from(*v))))
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_cheap(&self) -> Option<BytesArrayCheapIter<'_>> {
-		Some(self.0.iter().map(|v| Val::Num(f64::from(*v))))
-	}
 }
 impl From<BytesArray> for ArrValue {
 	fn from(value: BytesArray) -> Self {
@@ -297,20 +163,7 @@
 		}))
 	}
 }
-#[cfg(feature = "nightly")]
-type ExprArrayIter<'t> = impl DoubleEndedIterator<Item = Result<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type ExprArrayLazyIter<'t> = impl DoubleEndedIterator<Item = Thunk<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type ExprArrayCheapIter<'t> = iter::Empty<Val>;
 impl ArrayLike for ExprArray {
-	#[cfg(feature = "nightly")]
-	type Iter<'t> = ExprArrayIter<'t>;
-	#[cfg(feature = "nightly")]
-	type IterLazy<'t> = ExprArrayLazyIter<'t>;
-	#[cfg(feature = "nightly")]
-	type IterCheap<'t> = ExprArrayCheapIter<'t>;
-
 	fn len(&self) -> usize {
 		self.0.cached.borrow().len()
 	}
@@ -374,19 +227,6 @@
 	fn get_cheap(&self, _index: usize) -> Option<Val> {
 		None
 	}
-
-	#[cfg(feature = "nightly")]
-	fn iter(&self) -> ExprArrayIter<'_> {
-		(0..self.len()).map(|i| self.get(i).transpose().expect("index checked"))
-	}
-	#[cfg(feature = "nightly")]
-	fn iter_lazy(&self) -> ExprArrayLazyIter<'_> {
-		(0..self.len()).map(|i| self.get_lazy(i).expect("index checked"))
-	}
-	#[cfg(feature = "nightly")]
-	fn iter_cheap(&self) -> Option<Self::IterCheap<'_>> {
-		None
-	}
 }
 impl From<ExprArray> for ArrValue {
 	fn from(value: ExprArray) -> Self {
@@ -401,14 +241,6 @@
 	split: usize,
 	len: usize,
 }
-#[cfg(feature = "nightly")]
-
-type ExtendedArrayIter<'t> = impl DoubleEndedIterator<Item = Result<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type ExtendedArrayLazyIter<'t> =
-	impl DoubleEndedIterator<Item = Thunk<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type ExtendedArrayCheapIter<'t> = impl DoubleEndedIterator<Item = Val> + ExactSizeIterator + 't;
 impl ExtendedArray {
 	pub fn new(a: ArrValue, b: ArrValue) -> Self {
 		let a_len = a.len();
@@ -459,13 +291,6 @@
 	}
 }
 impl ArrayLike for ExtendedArray {
-	#[cfg(feature = "nightly")]
-	type Iter<'t> = ExtendedArrayIter<'t>;
-	#[cfg(feature = "nightly")]
-	type IterLazy<'t> = ExtendedArrayLazyIter<'t>;
-	#[cfg(feature = "nightly")]
-	type IterCheap<'t> = ExtendedArrayCheapIter<'t>;
-
 	fn get(&self, index: usize) -> Result<Option<Val>> {
 		if self.split > index {
 			self.a.get(index)
@@ -492,21 +317,6 @@
 			self.b.get_cheap(index - self.split)
 		}
 	}
-
-	#[cfg(feature = "nightly")]
-	fn iter(&self) -> ExtendedArrayIter<'_> {
-		WithExactSize(self.a.iter().chain(self.b.iter()), self.len)
-	}
-	#[cfg(feature = "nightly")]
-	fn iter_lazy(&self) -> ExtendedArrayLazyIter<'_> {
-		WithExactSize(self.a.iter_lazy().chain(self.b.iter_lazy()), self.len)
-	}
-	#[cfg(feature = "nightly")]
-	fn iter_cheap(&self) -> Option<ExtendedArrayCheapIter<'_>> {
-		let a = self.a.iter_cheap()?;
-		let b = self.b.iter_cheap()?;
-		Some(WithExactSize(a.chain(b), self.len))
-	}
 }
 impl From<ExtendedArray> for ArrValue {
 	fn from(value: ExtendedArray) -> Self {
@@ -516,22 +326,7 @@
 
 #[derive(Trace, Debug, Clone)]
 pub struct LazyArray(pub Cc<Vec<Thunk<Val>>>);
-#[cfg(feature = "nightly")]
-type LazyArrayIter<'t> = impl DoubleEndedIterator<Item = Result<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type LazyArrayLazyIter<'t> = impl DoubleEndedIterator<Item = Thunk<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type LazyArrayCheapIter<'t> = iter::Empty<Val>;
 impl ArrayLike for LazyArray {
-	#[cfg(feature = "nightly")]
-	type Iter<'t> = LazyArrayIter<'t>;
-
-	#[cfg(feature = "nightly")]
-	type IterLazy<'t> = LazyArrayLazyIter<'t>;
-
-	#[cfg(feature = "nightly")]
-	type IterCheap<'t> = LazyArrayCheapIter<'t>;
-
 	fn len(&self) -> usize {
 		self.0.len()
 	}
@@ -547,18 +342,6 @@
 	fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
 		self.0.get(index).cloned()
 	}
-	#[cfg(feature = "nightly")]
-	fn iter(&self) -> LazyArrayIter<'_> {
-		self.0.iter().map(Thunk::evaluate)
-	}
-	#[cfg(feature = "nightly")]
-	fn iter_lazy(&self) -> LazyArrayLazyIter<'_> {
-		self.0.iter().cloned()
-	}
-	#[cfg(feature = "nightly")]
-	fn iter_cheap(&self) -> Option<LazyArrayCheapIter<'_>> {
-		None
-	}
 }
 impl From<LazyArray> for ArrValue {
 	fn from(value: LazyArray) -> Self {
@@ -568,22 +351,7 @@
 
 #[derive(Trace, Debug, Clone)]
 pub struct EagerArray(pub Cc<Vec<Val>>);
-#[cfg(feature = "nightly")]
-type EagerArrayIter<'t> = impl DoubleEndedIterator<Item = Result<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type EagerArrayLazyIter<'t> = impl DoubleEndedIterator<Item = Thunk<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type EagerArrayCheapIter<'t> = impl DoubleEndedIterator<Item = Val> + ExactSizeIterator + 't;
 impl ArrayLike for EagerArray {
-	#[cfg(feature = "nightly")]
-	type Iter<'t> = EagerArrayIter<'t>;
-
-	#[cfg(feature = "nightly")]
-	type IterLazy<'t> = EagerArrayLazyIter<'t>;
-
-	#[cfg(feature = "nightly")]
-	type IterCheap<'t> = EagerArrayCheapIter<'t>;
-
 	fn len(&self) -> usize {
 		self.0.len()
 	}
@@ -599,21 +367,6 @@
 	fn get_cheap(&self, index: usize) -> Option<Val> {
 		self.0.get(index).cloned()
 	}
-
-	#[cfg(feature = "nightly")]
-	fn iter(&self) -> EagerArrayIter<'_> {
-		self.0.iter().cloned().map(Ok)
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_lazy(&self) -> EagerArrayLazyIter<'_> {
-		self.0.iter().cloned().map(Thunk::evaluated)
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_cheap(&self) -> Option<EagerArrayCheapIter<'_>> {
-		Some(self.0.iter().cloned())
-	}
 }
 impl From<EagerArray> for ArrValue {
 	fn from(value: EagerArray) -> Self {
@@ -648,22 +401,7 @@
 	}
 }
 
-#[cfg(feature = "nightly")]
-type RangeArrayIter<'t> = impl DoubleEndedIterator<Item = Result<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type RangeArrayLazyIter<'t> = impl DoubleEndedIterator<Item = Thunk<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type RangeArrayCheapIter<'t> = impl DoubleEndedIterator<Item = Val> + ExactSizeIterator + 't;
 impl ArrayLike for RangeArray {
-	#[cfg(feature = "nightly")]
-	type Iter<'t> = RangeArrayIter<'t>;
-
-	#[cfg(feature = "nightly")]
-	type IterLazy<'t> = RangeArrayLazyIter<'t>;
-
-	#[cfg(feature = "nightly")]
-	type IterCheap<'t> = RangeArrayCheapIter<'t>;
-
 	fn len(&self) -> usize {
 		self.range().len()
 	}
@@ -682,22 +420,6 @@
 	fn get_cheap(&self, index: usize) -> Option<Val> {
 		self.range().nth(index).map(|i| Val::Num(f64::from(i)))
 	}
-
-	#[cfg(feature = "nightly")]
-	fn iter(&self) -> RangeArrayIter<'_> {
-		self.range().map(|i| Ok(Val::Num(f64::from(i))))
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_lazy(&self) -> RangeArrayLazyIter<'_> {
-		self.range()
-			.map(|i| Thunk::evaluated(Val::Num(f64::from(i))))
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_cheap(&self) -> Option<RangeArrayCheapIter<'_>> {
-		Some(self.range().map(|i| Val::Num(f64::from(i))))
-	}
 }
 impl From<RangeArray> for ArrValue {
 	fn from(value: RangeArray) -> Self {
@@ -708,15 +430,6 @@
 #[derive(Debug, Trace, Clone)]
 pub struct ReverseArray(pub ArrValue);
 impl ArrayLike for ReverseArray {
-	#[cfg(feature = "nightly")]
-	type Iter<'t> = iter::Rev<UnknownArrayIter<'t>>;
-
-	#[cfg(feature = "nightly")]
-	type IterLazy<'t> = iter::Rev<UnknownArrayIterLazy<'t>>;
-
-	#[cfg(feature = "nightly")]
-	type IterCheap<'t> = iter::Rev<UnknownArrayIterCheap<'t>>;
-
 	fn len(&self) -> usize {
 		self.0.len()
 	}
@@ -732,21 +445,6 @@
 	fn get_cheap(&self, index: usize) -> Option<Val> {
 		self.0.get_cheap(self.0.len() - index - 1)
 	}
-
-	#[cfg(feature = "nightly")]
-	fn iter(&self) -> iter::Rev<UnknownArrayIter<'_>> {
-		self.0.iter().rev()
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_lazy(&self) -> iter::Rev<UnknownArrayIterLazy<'_>> {
-		self.0.iter_lazy().rev()
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_cheap(&self) -> Option<iter::Rev<UnknownArrayIterCheap<'_>>> {
-		Some(self.0.iter_cheap()?.rev())
-	}
 	fn reverse(self) -> ArrValue {
 		self.0
 	}
@@ -775,20 +473,7 @@
 		}))
 	}
 }
-#[cfg(feature = "nightly")]
-type MappedArrayIter<'t> = impl DoubleEndedIterator<Item = Result<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type MappedArrayLazyIter<'t> = impl DoubleEndedIterator<Item = Thunk<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type MappedArrayCheapIter<'t> = iter::Empty<Val>;
 impl ArrayLike for MappedArray {
-	#[cfg(feature = "nightly")]
-	type Iter<'t> = MappedArrayIter<'t>;
-	#[cfg(feature = "nightly")]
-	type IterLazy<'t> = MappedArrayLazyIter<'t>;
-	#[cfg(feature = "nightly")]
-	type IterCheap<'t> = MappedArrayCheapIter<'t>;
-
 	fn len(&self) -> usize {
 		self.0.cached.borrow().len()
 	}
@@ -860,21 +545,6 @@
 	}
 
 	fn get_cheap(&self, _index: usize) -> Option<Val> {
-		None
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter(&self) -> MappedArrayIter<'_> {
-		(0..self.len()).map(|i| self.get(i).transpose().expect("length checked"))
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_lazy(&self) -> MappedArrayLazyIter<'_> {
-		(0..self.len()).map(|i| self.get_lazy(i).expect("length checked"))
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_cheap(&self) -> Option<Self::IterCheap<'_>> {
 		None
 	}
 }
@@ -906,21 +576,7 @@
 	}
 }
 
-#[cfg(feature = "nightly")]
-type RepeatedArrayIter<'t> = impl DoubleEndedIterator<Item = Result<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type RepeatedArrayLazyIter<'t> =
-	impl DoubleEndedIterator<Item = Thunk<Val>> + ExactSizeIterator + 't;
-#[cfg(feature = "nightly")]
-type RepeatedArrayCheapIter<'t> = impl DoubleEndedIterator<Item = Val> + ExactSizeIterator + 't;
 impl ArrayLike for RepeatedArray {
-	#[cfg(feature = "nightly")]
-	type Iter<'t> = RepeatedArrayIter<'t>;
-	#[cfg(feature = "nightly")]
-	type IterLazy<'t> = RepeatedArrayLazyIter<'t>;
-	#[cfg(feature = "nightly")]
-	type IterCheap<'t> = RepeatedArrayCheapIter<'t>;
-
 	fn len(&self) -> usize {
 		self.0.total_len
 	}
@@ -945,56 +601,11 @@
 		}
 		self.0.data.get_cheap(index % self.0.data.len())
 	}
-
-	#[cfg(feature = "nightly")]
-	fn iter(&self) -> RepeatedArrayIter<'_> {
-		(0..self.0.total_len)
-			.map(|i| self.get(i))
-			.map(Result::transpose)
-			.map(Option::unwrap)
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_lazy(&self) -> RepeatedArrayLazyIter<'_> {
-		(0..self.0.total_len)
-			.map(|i| self.get_lazy(i))
-			.map(Option::unwrap)
-	}
-
-	#[cfg(feature = "nightly")]
-	fn iter_cheap(&self) -> Option<RepeatedArrayCheapIter<'_>> {
-		if !self.0.data.is_cheap() {
-			return None;
-		}
-		Some(
-			(0..self.0.total_len)
-				.map(|i| self.get_cheap(i))
-				.map(Option::unwrap),
-		)
-	}
 }
 impl From<RepeatedArray> for ArrValue {
 	fn from(value: RepeatedArray) -> Self {
 		Self::Repeated(value)
 	}
-}
-
-#[cfg(feature = "nightly")]
-macro_rules! impl_iter_enum {
-	($n:ident => $v:ident) => {
-		pub enum $n<'t> {
-			Bytes(<BytesArray as ArrayLike>::$v<'t>),
-			Expr(<ExprArray as ArrayLike>::$v<'t>),
-			Lazy(<LazyArray as ArrayLike>::$v<'t>),
-			Eager(<EagerArray as ArrayLike>::$v<'t>),
-			Range(<RangeArray as ArrayLike>::$v<'t>),
-			Slice(Box<<SliceArray as ArrayLike>::$v<'t>>),
-			Extended(Box<<ExtendedArray as ArrayLike>::$v<'t>>),
-			Reverse(Box<<ReverseArray as ArrayLike>::$v<'t>>),
-			Mapped(Box<<MappedArray as ArrayLike>::$v<'t>>),
-			Repeated(Box<<RepeatedArray as ArrayLike>::$v<'t>>),
-		}
-	};
 }
 
 macro_rules! pass {
@@ -1015,81 +626,3 @@
 	};
 }
 pub(super) use pass;
-
-#[cfg(feature = "nightly")]
-macro_rules! pass_iter_call {
-	($t:ident.$c:ident $(in $wrap:ident)? => $e:ident) => {
-		match $t {
-			ArrValue::Bytes(e) => $e::Bytes($($wrap!)?(e.$c())),
-			ArrValue::Lazy(e) => $e::Lazy($($wrap!)?(e.$c())),
-			ArrValue::Expr(e) => $e::Expr($($wrap!)?(e.$c())),
-			ArrValue::Eager(e) => $e::Eager($($wrap!)?(e.$c())),
-			ArrValue::Range(e) => $e::Range($($wrap!)?(e.$c())),
-			ArrValue::Slice(e) => $e::Slice(Box::new($($wrap!)?(e.$c()))),
-			ArrValue::Extended(e) => $e::Extended(Box::new($($wrap!)?(e.$c()))),
-			ArrValue::Reverse(e) => $e::Reverse(Box::new($($wrap!)?(e.$c()))),
-			ArrValue::Mapped(e) => $e::Mapped(Box::new($($wrap!)?(e.$c()))),
-			ArrValue::Repeated(e) => $e::Repeated(Box::new($($wrap!)?(e.$c()))),
-		}
-	};
-}
-#[cfg(feature = "nightly")]
-pub(super) use pass_iter_call;
-
-#[cfg(feature = "nightly")]
-macro_rules! impl_iter {
-	($t:ident => $out:ty) => {
-		impl Iterator for $t<'_> {
-			type Item = $out;
-
-			fn next(&mut self) -> Option<Self::Item> {
-				pass!(self.next())
-			}
-			fn nth(&mut self, count: usize) -> Option<Self::Item> {
-				pass!(self.nth(count))
-			}
-			fn size_hint(&self) -> (usize, Option<usize>) {
-				pass!(self.size_hint())
-			}
-		}
-		impl DoubleEndedIterator for $t<'_> {
-			fn next_back(&mut self) -> Option<Self::Item> {
-				pass!(self.next_back())
-			}
-			fn nth_back(&mut self, count: usize) -> Option<Self::Item> {
-				pass!(self.nth_back(count))
-			}
-		}
-		impl ExactSizeIterator for $t<'_> {
-			fn len(&self) -> usize {
-				match self {
-					Self::Bytes(e) => e.len(),
-					Self::Expr(e) => e.len(),
-					Self::Lazy(e) => e.len(),
-					Self::Eager(e) => e.len(),
-					Self::Range(e) => e.len(),
-					Self::Slice(e) => e.len(),
-					Self::Extended(e) => {
-						e.size_hint().1.expect("overflow is checked in constructor")
-					}
-					Self::Reverse(e) => e.len(),
-					Self::Mapped(e) => e.len(),
-					Self::Repeated(e) => e.len(),
-				}
-			}
-		}
-	};
-}
-
-#[cfg(feature = "nightly")]
-impl_iter_enum!(UnknownArrayIter => Iter);
-#[cfg(feature = "nightly")]
-impl_iter!(UnknownArrayIter => Result<Val>);
-#[cfg(feature = "nightly")]
-impl_iter_enum!(UnknownArrayIterLazy => IterLazy);
-#[cfg(feature = "nightly")]
-impl_iter!(UnknownArrayIterLazy => Thunk<Val>);
-#[cfg(feature = "nightly")]
-impl_iter_enum!(UnknownArrayIterCheap => IterCheap);
-#[cfg(feature = "nightly")]
-impl_iter!(UnknownArrayIterCheap => Val);