git.delta.rocks / jrsonnet / refs/commits / b857448d5312

difftreelog

feat thunk conversion avoiding lazy

tozttkqwYaroslav Bolyukin2026-04-04parent: #3791235.patch.diff
in: master

1 file changed

modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
1use std::{collections::BTreeMap, marker::PhantomData, ops::Deref};1use std::{any::TypeId, collections::BTreeMap, marker::PhantomData, mem::transmute, ops::Deref};
22
3use jrsonnet_gcmodule::Trace;3use jrsonnet_gcmodule::Trace;
4use jrsonnet_interner::{IBytes, IStr};4use jrsonnet_interner::{IBytes, IStr};
5use jrsonnet_types::{ComplexValType, ValType};5use jrsonnet_types::{ComplexValType, ValType};
66
7use crate::{7use crate::{
8 ObjValue, ObjValueBuilder, Result, ResultExt, Thunk, Val,
9 arr::{ArrValue, BytesArray},8 arr::{ArrValue, BytesArray},
10 bail,9 bail,
11 function::FuncVal,10 function::FuncVal,
12 typed::CheckType,11 typed::CheckType,
13 val::{IndexableVal, NumValue, StrValue, ThunkMapper},12 val::{IndexableVal, NumValue, StrValue, ThunkMapper},
13 ObjValue, ObjValueBuilder, Result, ResultExt, Thunk, Val,
14};14};
1515
16#[doc(hidden)]16#[doc(hidden)]
17pub mod __typed_macro_prelude {17pub mod __typed_macro_prelude {
18 pub use ::jrsonnet_evaluator::{18 pub use ::jrsonnet_evaluator::{
19 IStr, ObjValue, ObjValueBuilder, State, Val,
20 error::{ErrorKind, Result as JrResult},19 error::{ErrorKind, Result as JrResult},
21 typed::{20 typed::{
22 CheckType, ComplexValType, FromUntyped, IntoUntyped, ParseTypedObj, SerializeTypedObj,21 CheckType, ComplexValType, FromUntyped, IntoUntyped, ParseTypedObj, SerializeTypedObj,
23 Typed,22 Typed,
24 },23 },
24 IStr, ObjValue, ObjValueBuilder, State, Val,
25 };25 };
26}26}
27pub use jrsonnet_macros::{FromUntyped, IntoUntyped, Typed};27pub use jrsonnet_macros::{FromUntyped, IntoUntyped, Typed};
127 const TYPE: &'static ComplexValType = &ComplexValType::Lazy(T::TYPE);127 const TYPE: &'static ComplexValType = &ComplexValType::Lazy(T::TYPE);
128}128}
129129
130fn try_cast_thunk_val<T: 'static>(typed: Thunk<T>) -> Result<Thunk<Val>, Thunk<T>> {
131 if TypeId::of::<T>() == TypeId::of::<Val>() {
132 // SAFETY: We know that it is exactly the same type, and we discard the original after that
133 // to avoid double-free.
134 let transmuted = unsafe { transmute::<Thunk<T>, Thunk<Val>>(typed) };
135 Ok(transmuted)
136 } else {
137 Err(typed)
138 }
139}
130impl IntoUntyped for Thunk<Val> {140impl<T> IntoUntyped for Thunk<T>
141where
142 T: IntoUntyped + Trace + Clone,
143{
131 fn into_untyped(typed: Self) -> Result<Val> {144 fn into_untyped(typed: Self) -> Result<Val> {
132 typed.evaluate()145 T::into_untyped(typed.evaluate()?)
133 }146 }
134 fn provides_lazy() -> bool {147 fn provides_lazy() -> bool {
135 true148 true
136 }149 }
137150
138 fn into_lazy_untyped(inner: Self) -> Thunk<Val> {151 fn into_lazy_untyped(inner: Self) -> Thunk<Val> {
152 // Avoid lazy mapping
139 inner153 let inner = match try_cast_thunk_val(inner) {
154 Ok(v) => return v,
155 Err(e) => e,
156 };
157 inner.map(<ThunkIntoUntyped<T>>::default())
140 }158 }
141}159}
142160
161fn try_cast_thunk_t<T: 'static>(typed: Thunk<Val>) -> Result<Thunk<T>, Thunk<Val>> {
162 if TypeId::of::<T>() == TypeId::of::<Val>() {
163 // SAFETY: We know that it is exactly the same type, and we discard the original after that
164 // to avoid double-free.
165 let transmuted = unsafe { transmute::<Thunk<Val>, Thunk<T>>(typed) };
166 Ok(transmuted)
167 } else {
168 Err(typed)
169 }
170}
143impl<T> FromUntyped for Thunk<T>171impl<T> FromUntyped for Thunk<T>
144where172where
145 T: Typed + FromUntyped + Trace + Clone,173 T: Typed + FromUntyped + Trace + Clone,
153 }181 }
154182
155 fn from_lazy_untyped(inner: Thunk<Val>) -> Result<Self> {183 fn from_lazy_untyped(inner: Thunk<Val>) -> Result<Self> {
184 // Avoid lazy mapping
185 let inner = match try_cast_thunk_t(inner) {
186 Ok(v) => return Ok(v),
187 Err(e) => e,
188 };
156 Ok(inner.map(<ThunkFromUntyped<T>>::default()))189 Ok(inner.map(<ThunkFromUntyped<T>>::default()))
157 }190 }
158}191}