difftreelog
style fix clippy warnings
in: master
17 files changed
crates/jrsonnet-evaluator/src/arr/spec.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/arr/spec.rs
+++ b/crates/jrsonnet-evaluator/src/arr/spec.rs
@@ -372,7 +372,7 @@
pub fn new_inclusive(start: i32, end: i32) -> Self {
Self { start, end }
}
- fn range(&self) -> impl Iterator<Item = i32> + ExactSizeIterator + DoubleEndedIterator {
+ fn range(&self) -> impl ExactSizeIterator<Item = i32> + DoubleEndedIterator {
WithExactSize(
self.start..=self.end,
(self.end as usize)
@@ -461,7 +461,7 @@
ArrayThunk::Waiting(..) => {}
};
- let ArrayThunk::Waiting(_) =
+ let ArrayThunk::Waiting(()) =
replace(&mut self.cached.borrow_mut()[index], ArrayThunk::Pending)
else {
unreachable!()
@@ -508,7 +508,7 @@
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 => {}
+ ArrayThunk::Waiting(()) | ArrayThunk::Pending => {}
};
Some(Thunk::new(ArrayElement {
@@ -597,9 +597,7 @@
}
fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
- let Some(key) = self.keys.get(index) else {
- return None;
- };
+ let key = self.keys.get(index)?;
Some(self.obj.get_lazy_or_bail(key.clone()))
}
@@ -649,9 +647,7 @@
}
fn get_lazy(&self, index: usize) -> Option<Thunk<Val>> {
- let Some(key) = self.keys.get(index) else {
- return None;
- };
+ let key = self.keys.get(index)?;
// Nothing can fail in the key part, yet value is still
// lazy-evaluated
Some(Thunk::evaluated(
crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -89,7 +89,7 @@
specs: &[CompSpec],
callback: &mut impl FnMut(Context) -> Result<()>,
) -> Result<()> {
- match specs.get(0) {
+ match specs.first() {
None => callback(ctx)?,
Some(CompSpec::IfSpec(IfSpecData(cond))) => {
if bool::from_untyped(evaluate(ctx.clone(), cond)?)? {
crates/jrsonnet-evaluator/src/function/builtin.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function/builtin.rs
+++ b/crates/jrsonnet-evaluator/src/function/builtin.rs
@@ -6,8 +6,8 @@
use super::{arglike::ArgsLike, parse::parse_builtin_call, CallLocation};
use crate::{gc::TraceBox, tb, Context, Result, Val};
-/// Can't have str | IStr, because constant BuiltinParam causes
-/// E0492: constant functions cannot refer to interior mutable data
+/// Can't have `str` | `IStr`, because constant `BuiltinParam` causes
+/// `E0492: constant functions cannot refer to interior mutable data`
#[derive(Clone, Trace)]
pub struct ParamName(Option<Cow<'static, str>>);
impl ParamName {
@@ -27,10 +27,9 @@
}
impl PartialEq<IStr> for ParamName {
fn eq(&self, other: &IStr) -> bool {
- match &self.0 {
- Some(s) => s.as_bytes() == other.as_bytes(),
- None => false,
- }
+ self.0
+ .as_ref()
+ .map_or(false, |s| s.as_bytes() == other.as_bytes())
}
}
@@ -87,7 +86,7 @@
params: params
.into_iter()
.map(|n| BuiltinParam {
- name: ParamName::new_dynamic(n.to_string()),
+ name: ParamName::new_dynamic(n),
has_default: false,
})
.collect(),
crates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/integrations/serde.rs
+++ b/crates/jrsonnet-evaluator/src/integrations/serde.rs
@@ -159,11 +159,11 @@
Val::Null => serializer.serialize_none(),
Val::Str(s) => serializer.serialize_str(&s.clone().into_flat()),
Val::Num(n) => {
- if n.fract() != 0.0 {
- serializer.serialize_f64(*n)
- } else {
+ if n.fract() == 0.0 {
let n = *n as i64;
serializer.serialize_i64(n)
+ } else {
+ serializer.serialize_f64(*n)
}
}
#[cfg(feature = "exp-bigint")]
crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth1//! jsonnet interpreter implementation2#![cfg_attr(feature = "nightly", feature(thread_local, type_alias_impl_trait))]3#![deny(unsafe_op_in_unsafe_fn)]4#![warn(5 clippy::all,6 clippy::nursery,7 clippy::pedantic,8 // missing_docs,9 elided_lifetimes_in_paths,10 explicit_outlives_requirements,11 noop_method_call,12 single_use_lifetimes,13 variant_size_differences,14 rustdoc::all15)]16#![allow(17 macro_expanded_macro_exports_accessed_by_absolute_paths,18 clippy::ptr_arg,19 // Too verbose20 clippy::must_use_candidate,21 // A lot of functions pass around errors thrown by code22 clippy::missing_errors_doc,23 // A lot of pointers have interior Rc24 clippy::needless_pass_by_value,25 // Its fine26 clippy::wildcard_imports,27 clippy::enum_glob_use,28 clippy::module_name_repetitions,29 // TODO: fix individual issues, however this works as intended almost everywhere30 clippy::cast_precision_loss,31 clippy::cast_possible_wrap,32 clippy::cast_possible_truncation,33 clippy::cast_sign_loss,34 // False positives35 // https://github.com/rust-lang/rust-clippy/issues/690236 clippy::use_self,37 // https://github.com/rust-lang/rust-clippy/issues/853938 clippy::iter_with_drain,39 clippy::type_repetition_in_bounds,40 // ci is being run with nightly, but library should work on stable41 clippy::missing_const_for_fn,42 // too many false-positives with .expect() calls43 clippy::missing_panics_doc,44 // false positive for IStr type. There is an configuration option for45 // such cases, but it doesn't work:46 // https://github.com/rust-lang/rust-clippy/issues/980147 clippy::mutable_key_type,48)]4950// For jrsonnet-macros51extern crate self as jrsonnet_evaluator;5253mod arr;54#[cfg(feature = "async-import")]55pub mod async_import;56mod ctx;57mod dynamic;58pub mod error;59mod evaluate;60pub mod function;61pub mod gc;62mod import;63mod integrations;64pub mod manifest;65mod map;66mod obj;67pub mod stack;68pub mod stdlib;69mod tla;70pub mod trace;71pub mod typed;72pub mod val;7374use std::{75 any::Any,76 cell::{Ref, RefCell, RefMut},77 fmt::{self, Debug},78 path::Path,79};8081pub use ctx::*;82pub use dynamic::*;83pub use error::{Error, ErrorKind::*, Result, ResultExt};84pub use evaluate::*;85use function::CallLocation;86use gc::{GcHashMap, TraceBox};87use hashbrown::hash_map::RawEntryMut;88pub use import::*;89use jrsonnet_gcmodule::{Cc, Trace};90pub use jrsonnet_interner::{IBytes, IStr};91#[doc(hidden)]92pub use jrsonnet_macros;93pub use jrsonnet_parser as parser;94use jrsonnet_parser::*;95pub use obj::*;96use stack::check_depth;97pub use tla::apply_tla;98pub use val::{Thunk, Val};99100/// Thunk without bound `super`/`this`101/// object inheritance may be overriden multiple times, and will be fixed only on field read102pub trait Unbound: Trace {103 /// Type of value after object context is bound104 type Bound;105 /// Create value bound to specified object context106 fn bind(&self, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<Self::Bound>;107}108109/// Object fields may, or may not depend on `this`/`super`, this enum allows cheaper reuse of object-independent fields for native code110/// Standard jsonnet fields are always unbound111#[derive(Clone, Trace)]112pub enum MaybeUnbound {113 /// Value needs to be bound to `this`/`super`114 Unbound(Cc<TraceBox<dyn Unbound<Bound = Val>>>),115 /// Value is object-independent116 Bound(Thunk<Val>),117}118119impl Debug for MaybeUnbound {120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {121 write!(f, "MaybeUnbound")122 }123}124impl MaybeUnbound {125 /// Attach object context to value, if required126 pub fn evaluate(&self, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<Val> {127 match self {128 Self::Unbound(v) => v.bind(sup, this),129 Self::Bound(v) => Ok(v.evaluate()?),130 }131 }132}133134/// During import, this trait will be called to create initial context for file.135/// It may initialize global variables, stdlib for example.136pub trait ContextInitializer: Trace {137 /// For which size the builder should be preallocated138 fn reserve_vars(&self) -> usize {139 0140 }141 /// Initialize default file context.142 /// Has default implementation, which calls `populate`.143 /// Prefer to always implement `populate` instead.144 fn initialize(&self, state: State, for_file: Source) -> Context {145 let mut builder = ContextBuilder::with_capacity(state, self.reserve_vars());146 self.populate(for_file, &mut builder);147 builder.build()148 }149 /// For composability: extend builder. May panic if this initialization is not supported,150 /// and the context may only be created via `initialize`.151 fn populate(&self, for_file: Source, builder: &mut ContextBuilder);152 /// Allows upcasting from abstract to concrete context initializer.153 /// jrsonnet by itself doesn't use this method, it is allowed for it to panic.154 fn as_any(&self) -> &dyn Any;155}156157/// Context initializer which adds nothing.158impl ContextInitializer for () {159 fn populate(&self, _for_file: Source, _builder: &mut ContextBuilder) {}160 fn as_any(&self) -> &dyn Any {161 self162 }163}164165macro_rules! impl_context_initializer {166 ($($gen:ident)*) => {167 #[allow(non_snake_case)]168 impl<$($gen: ContextInitializer + Trace,)*> ContextInitializer for ($($gen,)*) {169 fn reserve_vars(&self) -> usize {170 let mut out = 0;171 let ($($gen,)*) = self;172 $(out += $gen.reserve_vars();)*173 out174 }175 fn populate(&self, for_file: Source, builder: &mut ContextBuilder) {176 let ($($gen,)*) = self;177 $($gen.populate(for_file.clone(), builder);)*178 }179 fn as_any(&self) -> &dyn Any {180 self181 }182 }183 };184 ($($cur:ident)* @ $c:ident $($rest:ident)*) => {185 impl_context_initializer!($($cur)*);186 impl_context_initializer!($($cur)* $c @ $($rest)*);187 };188 ($($cur:ident)* @) => {189 impl_context_initializer!($($cur)*);190 }191}192impl_context_initializer! {193 A @ B C D E F G194}195196/// Dynamically reconfigurable evaluation settings197#[derive(Trace)]198pub struct EvaluationSettings {199 /// Context initializer, which will be used for imports and everything200 /// [`NoopContextInitializer`] is used by default, most likely you want to have `jrsonnet-stdlib`201 pub context_initializer: TraceBox<dyn ContextInitializer>,202 /// Used to resolve file locations/contents203 pub import_resolver: TraceBox<dyn ImportResolver>,204}205impl Default for EvaluationSettings {206 fn default() -> Self {207 Self {208 context_initializer: tb!(()),209 import_resolver: tb!(DummyImportResolver),210 }211 }212}213214#[derive(Trace)]215struct FileData {216 string: Option<IStr>,217 bytes: Option<IBytes>,218 parsed: Option<LocExpr>,219 evaluated: Option<Val>,220221 evaluating: bool,222}223impl FileData {224 fn new_string(data: IStr) -> Self {225 Self {226 string: Some(data),227 bytes: None,228 parsed: None,229 evaluated: None,230 evaluating: false,231 }232 }233 fn new_bytes(data: IBytes) -> Self {234 Self {235 string: None,236 bytes: Some(data),237 parsed: None,238 evaluated: None,239 evaluating: false,240 }241 }242 pub(crate) fn get_string(&mut self) -> Option<IStr> {243 if self.string.is_none() {244 self.string = Some(245 self.bytes246 .as_ref()247 .expect("either string or bytes should be set")248 .clone()249 .cast_str()?,250 );251 }252 Some(self.string.clone().expect("just set"))253 }254}255256#[derive(Default, Trace)]257pub struct EvaluationStateInternals {258 /// Internal state259 file_cache: RefCell<GcHashMap<SourcePath, FileData>>,260 /// Settings, safe to change at runtime261 settings: RefCell<EvaluationSettings>,262}263264/// Maintains stack trace and import resolution265#[derive(Default, Clone, Trace)]266pub struct State(Cc<EvaluationStateInternals>);267268impl State {269 /// Should only be called with path retrieved from [`resolve_path`], may panic otherwise270 pub fn import_resolved_str(&self, path: SourcePath) -> Result<IStr> {271 let mut file_cache = self.file_cache();272 let mut file = file_cache.raw_entry_mut().from_key(&path);273274 let file = match file {275 RawEntryMut::Occupied(ref mut d) => d.get_mut(),276 RawEntryMut::Vacant(v) => {277 let data = self.settings().import_resolver.load_file_contents(&path)?;278 v.insert(279 path.clone(),280 FileData::new_string(281 std::str::from_utf8(&data)282 .map_err(|_| ImportBadFileUtf8(path.clone()))?283 .into(),284 ),285 )286 .1287 }288 };289 Ok(file290 .get_string()291 .ok_or_else(|| ImportBadFileUtf8(path.clone()))?)292 }293 /// Should only be called with path retrieved from [`resolve_path`], may panic otherwise294 pub fn import_resolved_bin(&self, path: SourcePath) -> Result<IBytes> {295 let mut file_cache = self.file_cache();296 let mut file = file_cache.raw_entry_mut().from_key(&path);297298 let file = match file {299 RawEntryMut::Occupied(ref mut d) => d.get_mut(),300 RawEntryMut::Vacant(v) => {301 let data = self.settings().import_resolver.load_file_contents(&path)?;302 v.insert(path.clone(), FileData::new_bytes(data.as_slice().into()))303 .1304 }305 };306 if let Some(str) = &file.bytes {307 return Ok(str.clone());308 }309 if file.bytes.is_none() {310 file.bytes = Some(311 file.string312 .as_ref()313 .expect("either string or bytes should be set")314 .clone()315 .cast_bytes(),316 );317 }318 Ok(file.bytes.as_ref().expect("just set").clone())319 }320 /// Should only be called with path retrieved from [`resolve_path`], may panic otherwise321 pub fn import_resolved(&self, path: SourcePath) -> Result<Val> {322 let mut file_cache = self.file_cache();323 let mut file = file_cache.raw_entry_mut().from_key(&path);324325 let file = match file {326 RawEntryMut::Occupied(ref mut d) => d.get_mut(),327 RawEntryMut::Vacant(v) => {328 let data = self.settings().import_resolver.load_file_contents(&path)?;329 v.insert(330 path.clone(),331 FileData::new_string(332 std::str::from_utf8(&data)333 .map_err(|_| ImportBadFileUtf8(path.clone()))?334 .into(),335 ),336 )337 .1338 }339 };340 if let Some(val) = &file.evaluated {341 return Ok(val.clone());342 }343 let code = file344 .get_string()345 .ok_or_else(|| ImportBadFileUtf8(path.clone()))?;346 let file_name = Source::new(path.clone(), code.clone());347 if file.parsed.is_none() {348 file.parsed = Some(349 jrsonnet_parser::parse(350 &code,351 &ParserSettings {352 source: file_name.clone(),353 },354 )355 .map_err(|e| ImportSyntaxError {356 path: file_name.clone(),357 error: Box::new(e),358 })?,359 );360 }361 let parsed = file.parsed.as_ref().expect("just set").clone();362 if file.evaluating {363 bail!(InfiniteRecursionDetected)364 }365 file.evaluating = true;366 // Dropping file cache guard here, as evaluation may use this map too367 drop(file_cache);368 let res = evaluate(self.create_default_context(file_name), &parsed);369370 let mut file_cache = self.file_cache();371 let mut file = file_cache.raw_entry_mut().from_key(&path);372373 let RawEntryMut::Occupied(file) = &mut file else {374 unreachable!("this file was just here!")375 };376 let file = file.get_mut();377 file.evaluating = false;378 match res {379 Ok(v) => {380 file.evaluated = Some(v.clone());381 Ok(v)382 }383 Err(e) => Err(e),384 }385 }386387 /// Has same semantics as `import 'path'` called from `from` file388 pub fn import_from(&self, from: &SourcePath, path: &str) -> Result<Val> {389 let resolved = self.resolve_from(from, path)?;390 self.import_resolved(resolved)391 }392 pub fn import(&self, path: impl AsRef<Path>) -> Result<Val> {393 let resolved = self.resolve(path)?;394 self.import_resolved(resolved)395 }396397 /// Creates context with all passed global variables398 pub fn create_default_context(&self, source: Source) -> Context {399 let context_initializer = &self.settings().context_initializer;400 context_initializer.initialize(self.clone(), source)401 }402403 /// Creates context with all passed global variables, calling custom modifier404 pub fn create_default_context_with(405 &self,406 source: Source,407 context_initializer: impl ContextInitializer,408 ) -> Context {409 let default_initializer = &self.settings().context_initializer;410 let mut builder = ContextBuilder::with_capacity(411 self.clone(),412 default_initializer.reserve_vars() + context_initializer.reserve_vars(),413 );414 default_initializer.populate(source.clone(), &mut builder);415 context_initializer.populate(source, &mut builder);416417 builder.build()418 }419420 /// Executes code creating a new stack frame421 pub fn push<T>(422 e: CallLocation<'_>,423 frame_desc: impl FnOnce() -> String,424 f: impl FnOnce() -> Result<T>,425 ) -> Result<T> {426 let _guard = check_depth()?;427428 f().with_description_src(e, frame_desc)429 }430431 /// Executes code creating a new stack frame432 pub fn push_val(433 &self,434 e: &ExprLocation,435 frame_desc: impl FnOnce() -> String,436 f: impl FnOnce() -> Result<Val>,437 ) -> Result<Val> {438 let _guard = check_depth()?;439440 f().with_description_src(e, frame_desc)441 }442 /// Executes code creating a new stack frame443 pub fn push_description<T>(444 frame_desc: impl FnOnce() -> String,445 f: impl FnOnce() -> Result<T>,446 ) -> Result<T> {447 let _guard = check_depth()?;448449 f().with_description(frame_desc)450 }451}452453/// Internals454impl State {455 fn file_cache(&self) -> RefMut<'_, GcHashMap<SourcePath, FileData>> {456 self.0.file_cache.borrow_mut()457 }458 pub fn settings(&self) -> Ref<'_, EvaluationSettings> {459 self.0.settings.borrow()460 }461 pub fn settings_mut(&self) -> RefMut<'_, EvaluationSettings> {462 self.0.settings.borrow_mut()463 }464 pub fn add_global(&self, name: IStr, value: Thunk<Val>) {465 #[derive(Trace)]466 struct GlobalsCtx {467 globals: RefCell<GcHashMap<IStr, Thunk<Val>>>,468 inner: TraceBox<dyn ContextInitializer>,469 }470 impl ContextInitializer for GlobalsCtx {471 fn reserve_vars(&self) -> usize {472 self.inner.reserve_vars() + self.globals.borrow().len()473 }474 fn populate(&self, for_file: Source, builder: &mut ContextBuilder) {475 self.inner.populate(for_file, builder);476 for (name, val) in self.globals.borrow().iter() {477 builder.bind(name.clone(), val.clone());478 }479 }480481 fn as_any(&self) -> &dyn Any {482 self483 }484 }485 let mut settings = self.settings_mut();486 let initializer = &mut settings.context_initializer;487 if let Some(global) = initializer.as_any().downcast_ref::<GlobalsCtx>() {488 global.globals.borrow_mut().insert(name, value);489 } else {490 let inner = std::mem::replace(&mut settings.context_initializer, tb!(()));491 settings.context_initializer = tb!(GlobalsCtx {492 globals: {493 let mut out = GcHashMap::with_capacity(1);494 out.insert(name, value);495 RefCell::new(out)496 },497 inner498 });499 }500 }501}502503#[derive(Trace)]504pub struct InitialUnderscore(pub Thunk<Val>);505impl ContextInitializer for InitialUnderscore {506 fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) {507 builder.bind("_", self.0.clone());508 }509510 fn as_any(&self) -> &dyn Any {511 self512 }513}514515/// Raw methods evaluate passed values but don't perform TLA execution516impl State {517 /// Parses and evaluates the given snippet518 pub fn evaluate_snippet(&self, name: impl Into<IStr>, code: impl Into<IStr>) -> Result<Val> {519 let code = code.into();520 let source = Source::new_virtual(name.into(), code.clone());521 let parsed = jrsonnet_parser::parse(522 &code,523 &ParserSettings {524 source: source.clone(),525 },526 )527 .map_err(|e| ImportSyntaxError {528 path: source.clone(),529 error: Box::new(e),530 })?;531 evaluate(self.create_default_context(source), &parsed)532 }533 /// Parses and evaluates the given snippet with custom context modifier534 pub fn evaluate_snippet_with(535 &self,536 name: impl Into<IStr>,537 code: impl Into<IStr>,538 context_initializer: impl ContextInitializer,539 ) -> Result<Val> {540 let code = code.into();541 let source = Source::new_virtual(name.into(), code.clone());542 let parsed = jrsonnet_parser::parse(543 &code,544 &ParserSettings {545 source: source.clone(),546 },547 )548 .map_err(|e| ImportSyntaxError {549 path: source.clone(),550 error: Box::new(e),551 })?;552 evaluate(553 self.create_default_context_with(source, context_initializer),554 &parsed,555 )556 }557}558559/// Settings utilities560impl State {561 // Only panics in case of [`ImportResolver`] contract violation562 #[allow(clippy::missing_panics_doc)]563 pub fn resolve_from(&self, from: &SourcePath, path: &str) -> Result<SourcePath> {564 self.import_resolver().resolve_from(from, path.as_ref())565 }566567 // Only panics in case of [`ImportResolver`] contract violation568 #[allow(clippy::missing_panics_doc)]569 pub fn resolve(&self, path: impl AsRef<Path>) -> Result<SourcePath> {570 self.import_resolver().resolve(path.as_ref())571 }572 pub fn import_resolver(&self) -> Ref<'_, dyn ImportResolver> {573 Ref::map(self.settings(), |s| &*s.import_resolver)574 }575 pub fn set_import_resolver(&self, resolver: impl ImportResolver) {576 self.settings_mut().import_resolver = tb!(resolver);577 }578 pub fn context_initializer(&self) -> Ref<'_, dyn ContextInitializer> {579 Ref::map(self.settings(), |s| &*s.context_initializer)580 }581 pub fn set_context_initializer(&self, initializer: impl ContextInitializer) {582 self.settings_mut().context_initializer = tb!(initializer);583 }584}1//! jsonnet interpreter implementation2#![cfg_attr(feature = "nightly", feature(thread_local, type_alias_impl_trait))]3#![deny(unsafe_op_in_unsafe_fn)]4#![warn(5 clippy::all,6 clippy::nursery,7 clippy::pedantic,8 // missing_docs,9 elided_lifetimes_in_paths,10 explicit_outlives_requirements,11 noop_method_call,12 single_use_lifetimes,13 variant_size_differences,14 rustdoc::all15)]16#![allow(17 macro_expanded_macro_exports_accessed_by_absolute_paths,18 clippy::ptr_arg,19 // Too verbose20 clippy::must_use_candidate,21 // A lot of functions pass around errors thrown by code22 clippy::missing_errors_doc,23 // A lot of pointers have interior Rc24 clippy::needless_pass_by_value,25 // Its fine26 clippy::wildcard_imports,27 clippy::enum_glob_use,28 clippy::module_name_repetitions,29 // TODO: fix individual issues, however this works as intended almost everywhere30 clippy::cast_precision_loss,31 clippy::cast_possible_wrap,32 clippy::cast_possible_truncation,33 clippy::cast_sign_loss,34 // False positives35 // https://github.com/rust-lang/rust-clippy/issues/690236 clippy::use_self,37 // https://github.com/rust-lang/rust-clippy/issues/853938 clippy::iter_with_drain,39 clippy::type_repetition_in_bounds,40 // ci is being run with nightly, but library should work on stable41 clippy::missing_const_for_fn,42 // too many false-positives with .expect() calls43 clippy::missing_panics_doc,44 // false positive for IStr type. There is an configuration option for45 // such cases, but it doesn't work:46 // https://github.com/rust-lang/rust-clippy/issues/980147 clippy::mutable_key_type,48 // false positives49 clippy::redundant_pub_crate,50)]5152// For jrsonnet-macros53extern crate self as jrsonnet_evaluator;5455mod arr;56#[cfg(feature = "async-import")]57pub mod async_import;58mod ctx;59mod dynamic;60pub mod error;61mod evaluate;62pub mod function;63pub mod gc;64mod import;65mod integrations;66pub mod manifest;67mod map;68mod obj;69pub mod stack;70pub mod stdlib;71mod tla;72pub mod trace;73pub mod typed;74pub mod val;7576use std::{77 any::Any,78 cell::{Ref, RefCell, RefMut},79 fmt::{self, Debug},80 path::Path,81};8283pub use ctx::*;84pub use dynamic::*;85pub use error::{Error, ErrorKind::*, Result, ResultExt};86pub use evaluate::*;87use function::CallLocation;88use gc::{GcHashMap, TraceBox};89use hashbrown::hash_map::RawEntryMut;90pub use import::*;91use jrsonnet_gcmodule::{Cc, Trace};92pub use jrsonnet_interner::{IBytes, IStr};93#[doc(hidden)]94pub use jrsonnet_macros;95pub use jrsonnet_parser as parser;96use jrsonnet_parser::*;97pub use obj::*;98use stack::check_depth;99pub use tla::apply_tla;100pub use val::{Thunk, Val};101102/// Thunk without bound `super`/`this`103/// object inheritance may be overriden multiple times, and will be fixed only on field read104pub trait Unbound: Trace {105 /// Type of value after object context is bound106 type Bound;107 /// Create value bound to specified object context108 fn bind(&self, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<Self::Bound>;109}110111/// Object fields may, or may not depend on `this`/`super`, this enum allows cheaper reuse of object-independent fields for native code112/// Standard jsonnet fields are always unbound113#[derive(Clone, Trace)]114pub enum MaybeUnbound {115 /// Value needs to be bound to `this`/`super`116 Unbound(Cc<TraceBox<dyn Unbound<Bound = Val>>>),117 /// Value is object-independent118 Bound(Thunk<Val>),119}120121impl Debug for MaybeUnbound {122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {123 write!(f, "MaybeUnbound")124 }125}126impl MaybeUnbound {127 /// Attach object context to value, if required128 pub fn evaluate(&self, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<Val> {129 match self {130 Self::Unbound(v) => v.bind(sup, this),131 Self::Bound(v) => Ok(v.evaluate()?),132 }133 }134}135136/// During import, this trait will be called to create initial context for file.137/// It may initialize global variables, stdlib for example.138pub trait ContextInitializer: Trace {139 /// For which size the builder should be preallocated140 fn reserve_vars(&self) -> usize {141 0142 }143 /// Initialize default file context.144 /// Has default implementation, which calls `populate`.145 /// Prefer to always implement `populate` instead.146 fn initialize(&self, state: State, for_file: Source) -> Context {147 let mut builder = ContextBuilder::with_capacity(state, self.reserve_vars());148 self.populate(for_file, &mut builder);149 builder.build()150 }151 /// For composability: extend builder. May panic if this initialization is not supported,152 /// and the context may only be created via `initialize`.153 fn populate(&self, for_file: Source, builder: &mut ContextBuilder);154 /// Allows upcasting from abstract to concrete context initializer.155 /// jrsonnet by itself doesn't use this method, it is allowed for it to panic.156 fn as_any(&self) -> &dyn Any;157}158159/// Context initializer which adds nothing.160impl ContextInitializer for () {161 fn populate(&self, _for_file: Source, _builder: &mut ContextBuilder) {}162 fn as_any(&self) -> &dyn Any {163 self164 }165}166167macro_rules! impl_context_initializer {168 ($($gen:ident)*) => {169 #[allow(non_snake_case)]170 impl<$($gen: ContextInitializer + Trace,)*> ContextInitializer for ($($gen,)*) {171 fn reserve_vars(&self) -> usize {172 let mut out = 0;173 let ($($gen,)*) = self;174 $(out += $gen.reserve_vars();)*175 out176 }177 fn populate(&self, for_file: Source, builder: &mut ContextBuilder) {178 let ($($gen,)*) = self;179 $($gen.populate(for_file.clone(), builder);)*180 }181 fn as_any(&self) -> &dyn Any {182 self183 }184 }185 };186 ($($cur:ident)* @ $c:ident $($rest:ident)*) => {187 impl_context_initializer!($($cur)*);188 impl_context_initializer!($($cur)* $c @ $($rest)*);189 };190 ($($cur:ident)* @) => {191 impl_context_initializer!($($cur)*);192 }193}194impl_context_initializer! {195 A @ B C D E F G196}197198/// Dynamically reconfigurable evaluation settings199#[derive(Trace)]200pub struct EvaluationSettings {201 /// Context initializer, which will be used for imports and everything202 /// [`NoopContextInitializer`] is used by default, most likely you want to have `jrsonnet-stdlib`203 pub context_initializer: TraceBox<dyn ContextInitializer>,204 /// Used to resolve file locations/contents205 pub import_resolver: TraceBox<dyn ImportResolver>,206}207impl Default for EvaluationSettings {208 fn default() -> Self {209 Self {210 context_initializer: tb!(()),211 import_resolver: tb!(DummyImportResolver),212 }213 }214}215216#[derive(Trace)]217struct FileData {218 string: Option<IStr>,219 bytes: Option<IBytes>,220 parsed: Option<LocExpr>,221 evaluated: Option<Val>,222223 evaluating: bool,224}225impl FileData {226 fn new_string(data: IStr) -> Self {227 Self {228 string: Some(data),229 bytes: None,230 parsed: None,231 evaluated: None,232 evaluating: false,233 }234 }235 fn new_bytes(data: IBytes) -> Self {236 Self {237 string: None,238 bytes: Some(data),239 parsed: None,240 evaluated: None,241 evaluating: false,242 }243 }244 pub(crate) fn get_string(&mut self) -> Option<IStr> {245 if self.string.is_none() {246 self.string = Some(247 self.bytes248 .as_ref()249 .expect("either string or bytes should be set")250 .clone()251 .cast_str()?,252 );253 }254 Some(self.string.clone().expect("just set"))255 }256}257258#[derive(Default, Trace)]259pub struct EvaluationStateInternals {260 /// Internal state261 file_cache: RefCell<GcHashMap<SourcePath, FileData>>,262 /// Settings, safe to change at runtime263 settings: RefCell<EvaluationSettings>,264}265266/// Maintains stack trace and import resolution267#[derive(Default, Clone, Trace)]268pub struct State(Cc<EvaluationStateInternals>);269270impl State {271 /// Should only be called with path retrieved from [`resolve_path`], may panic otherwise272 pub fn import_resolved_str(&self, path: SourcePath) -> Result<IStr> {273 let mut file_cache = self.file_cache();274 let mut file = file_cache.raw_entry_mut().from_key(&path);275276 let file = match file {277 RawEntryMut::Occupied(ref mut d) => d.get_mut(),278 RawEntryMut::Vacant(v) => {279 let data = self.settings().import_resolver.load_file_contents(&path)?;280 v.insert(281 path.clone(),282 FileData::new_string(283 std::str::from_utf8(&data)284 .map_err(|_| ImportBadFileUtf8(path.clone()))?285 .into(),286 ),287 )288 .1289 }290 };291 Ok(file292 .get_string()293 .ok_or_else(|| ImportBadFileUtf8(path.clone()))?)294 }295 /// Should only be called with path retrieved from [`resolve_path`], may panic otherwise296 pub fn import_resolved_bin(&self, path: SourcePath) -> Result<IBytes> {297 let mut file_cache = self.file_cache();298 let mut file = file_cache.raw_entry_mut().from_key(&path);299300 let file = match file {301 RawEntryMut::Occupied(ref mut d) => d.get_mut(),302 RawEntryMut::Vacant(v) => {303 let data = self.settings().import_resolver.load_file_contents(&path)?;304 v.insert(path.clone(), FileData::new_bytes(data.as_slice().into()))305 .1306 }307 };308 if let Some(str) = &file.bytes {309 return Ok(str.clone());310 }311 if file.bytes.is_none() {312 file.bytes = Some(313 file.string314 .as_ref()315 .expect("either string or bytes should be set")316 .clone()317 .cast_bytes(),318 );319 }320 Ok(file.bytes.as_ref().expect("just set").clone())321 }322 /// Should only be called with path retrieved from [`resolve_path`], may panic otherwise323 pub fn import_resolved(&self, path: SourcePath) -> Result<Val> {324 let mut file_cache = self.file_cache();325 let mut file = file_cache.raw_entry_mut().from_key(&path);326327 let file = match file {328 RawEntryMut::Occupied(ref mut d) => d.get_mut(),329 RawEntryMut::Vacant(v) => {330 let data = self.settings().import_resolver.load_file_contents(&path)?;331 v.insert(332 path.clone(),333 FileData::new_string(334 std::str::from_utf8(&data)335 .map_err(|_| ImportBadFileUtf8(path.clone()))?336 .into(),337 ),338 )339 .1340 }341 };342 if let Some(val) = &file.evaluated {343 return Ok(val.clone());344 }345 let code = file346 .get_string()347 .ok_or_else(|| ImportBadFileUtf8(path.clone()))?;348 let file_name = Source::new(path.clone(), code.clone());349 if file.parsed.is_none() {350 file.parsed = Some(351 jrsonnet_parser::parse(352 &code,353 &ParserSettings {354 source: file_name.clone(),355 },356 )357 .map_err(|e| ImportSyntaxError {358 path: file_name.clone(),359 error: Box::new(e),360 })?,361 );362 }363 let parsed = file.parsed.as_ref().expect("just set").clone();364 if file.evaluating {365 bail!(InfiniteRecursionDetected)366 }367 file.evaluating = true;368 // Dropping file cache guard here, as evaluation may use this map too369 drop(file_cache);370 let res = evaluate(self.create_default_context(file_name), &parsed);371372 let mut file_cache = self.file_cache();373 let mut file = file_cache.raw_entry_mut().from_key(&path);374375 let RawEntryMut::Occupied(file) = &mut file else {376 unreachable!("this file was just here!")377 };378 let file = file.get_mut();379 file.evaluating = false;380 match res {381 Ok(v) => {382 file.evaluated = Some(v.clone());383 Ok(v)384 }385 Err(e) => Err(e),386 }387 }388389 /// Has same semantics as `import 'path'` called from `from` file390 pub fn import_from(&self, from: &SourcePath, path: &str) -> Result<Val> {391 let resolved = self.resolve_from(from, path)?;392 self.import_resolved(resolved)393 }394 pub fn import(&self, path: impl AsRef<Path>) -> Result<Val> {395 let resolved = self.resolve(path)?;396 self.import_resolved(resolved)397 }398399 /// Creates context with all passed global variables400 pub fn create_default_context(&self, source: Source) -> Context {401 let context_initializer = &self.settings().context_initializer;402 context_initializer.initialize(self.clone(), source)403 }404405 /// Creates context with all passed global variables, calling custom modifier406 pub fn create_default_context_with(407 &self,408 source: Source,409 context_initializer: impl ContextInitializer,410 ) -> Context {411 let default_initializer = &self.settings().context_initializer;412 let mut builder = ContextBuilder::with_capacity(413 self.clone(),414 default_initializer.reserve_vars() + context_initializer.reserve_vars(),415 );416 default_initializer.populate(source.clone(), &mut builder);417 context_initializer.populate(source, &mut builder);418419 builder.build()420 }421422 /// Executes code creating a new stack frame423 pub fn push<T>(424 e: CallLocation<'_>,425 frame_desc: impl FnOnce() -> String,426 f: impl FnOnce() -> Result<T>,427 ) -> Result<T> {428 let _guard = check_depth()?;429430 f().with_description_src(e, frame_desc)431 }432433 /// Executes code creating a new stack frame434 pub fn push_val(435 &self,436 e: &ExprLocation,437 frame_desc: impl FnOnce() -> String,438 f: impl FnOnce() -> Result<Val>,439 ) -> Result<Val> {440 let _guard = check_depth()?;441442 f().with_description_src(e, frame_desc)443 }444 /// Executes code creating a new stack frame445 pub fn push_description<T>(446 frame_desc: impl FnOnce() -> String,447 f: impl FnOnce() -> Result<T>,448 ) -> Result<T> {449 let _guard = check_depth()?;450451 f().with_description(frame_desc)452 }453}454455/// Internals456impl State {457 fn file_cache(&self) -> RefMut<'_, GcHashMap<SourcePath, FileData>> {458 self.0.file_cache.borrow_mut()459 }460 pub fn settings(&self) -> Ref<'_, EvaluationSettings> {461 self.0.settings.borrow()462 }463 pub fn settings_mut(&self) -> RefMut<'_, EvaluationSettings> {464 self.0.settings.borrow_mut()465 }466 pub fn add_global(&self, name: IStr, value: Thunk<Val>) {467 #[derive(Trace)]468 struct GlobalsCtx {469 globals: RefCell<GcHashMap<IStr, Thunk<Val>>>,470 inner: TraceBox<dyn ContextInitializer>,471 }472 impl ContextInitializer for GlobalsCtx {473 fn reserve_vars(&self) -> usize {474 self.inner.reserve_vars() + self.globals.borrow().len()475 }476 fn populate(&self, for_file: Source, builder: &mut ContextBuilder) {477 self.inner.populate(for_file, builder);478 for (name, val) in self.globals.borrow().iter() {479 builder.bind(name.clone(), val.clone());480 }481 }482483 fn as_any(&self) -> &dyn Any {484 self485 }486 }487 let mut settings = self.settings_mut();488 let initializer = &mut settings.context_initializer;489 if let Some(global) = initializer.as_any().downcast_ref::<GlobalsCtx>() {490 global.globals.borrow_mut().insert(name, value);491 } else {492 let inner = std::mem::replace(&mut settings.context_initializer, tb!(()));493 settings.context_initializer = tb!(GlobalsCtx {494 globals: {495 let mut out = GcHashMap::with_capacity(1);496 out.insert(name, value);497 RefCell::new(out)498 },499 inner500 });501 }502 }503}504505#[derive(Trace)]506pub struct InitialUnderscore(pub Thunk<Val>);507impl ContextInitializer for InitialUnderscore {508 fn populate(&self, _for_file: Source, builder: &mut ContextBuilder) {509 builder.bind("_", self.0.clone());510 }511512 fn as_any(&self) -> &dyn Any {513 self514 }515}516517/// Raw methods evaluate passed values but don't perform TLA execution518impl State {519 /// Parses and evaluates the given snippet520 pub fn evaluate_snippet(&self, name: impl Into<IStr>, code: impl Into<IStr>) -> Result<Val> {521 let code = code.into();522 let source = Source::new_virtual(name.into(), code.clone());523 let parsed = jrsonnet_parser::parse(524 &code,525 &ParserSettings {526 source: source.clone(),527 },528 )529 .map_err(|e| ImportSyntaxError {530 path: source.clone(),531 error: Box::new(e),532 })?;533 evaluate(self.create_default_context(source), &parsed)534 }535 /// Parses and evaluates the given snippet with custom context modifier536 pub fn evaluate_snippet_with(537 &self,538 name: impl Into<IStr>,539 code: impl Into<IStr>,540 context_initializer: impl ContextInitializer,541 ) -> Result<Val> {542 let code = code.into();543 let source = Source::new_virtual(name.into(), code.clone());544 let parsed = jrsonnet_parser::parse(545 &code,546 &ParserSettings {547 source: source.clone(),548 },549 )550 .map_err(|e| ImportSyntaxError {551 path: source.clone(),552 error: Box::new(e),553 })?;554 evaluate(555 self.create_default_context_with(source, context_initializer),556 &parsed,557 )558 }559}560561/// Settings utilities562impl State {563 // Only panics in case of [`ImportResolver`] contract violation564 #[allow(clippy::missing_panics_doc)]565 pub fn resolve_from(&self, from: &SourcePath, path: &str) -> Result<SourcePath> {566 self.import_resolver().resolve_from(from, path.as_ref())567 }568569 // Only panics in case of [`ImportResolver`] contract violation570 #[allow(clippy::missing_panics_doc)]571 pub fn resolve(&self, path: impl AsRef<Path>) -> Result<SourcePath> {572 self.import_resolver().resolve(path.as_ref())573 }574 pub fn import_resolver(&self) -> Ref<'_, dyn ImportResolver> {575 Ref::map(self.settings(), |s| &*s.import_resolver)576 }577 pub fn set_import_resolver(&self, resolver: impl ImportResolver) {578 self.settings_mut().import_resolver = tb!(resolver);579 }580 pub fn context_initializer(&self) -> Ref<'_, dyn ContextInitializer> {581 Ref::map(self.settings(), |s| &*s.context_initializer)582 }583 pub fn set_context_initializer(&self, initializer: impl ContextInitializer) {584 self.settings_mut().context_initializer = tb!(initializer);585 }586}crates/jrsonnet-evaluator/src/manifest.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/manifest.rs
+++ b/crates/jrsonnet-evaluator/src/manifest.rs
@@ -175,6 +175,8 @@
manifest_json_ex_buf(val, &mut out, &mut String::new(), options)?;
Ok(out)
}
+
+#[allow(clippy::too_many_lines)]
fn manifest_json_ex_buf(
val: &Val,
buf: &mut String,
crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/obj.rs
+++ b/crates/jrsonnet-evaluator/src/obj.rs
@@ -171,7 +171,7 @@
// .field("assertions_ran", &self.assertions_ran)
.field("this_entries", &self.this_entries)
// .field("value_cache", &self.value_cache)
- .finish()
+ .finish_non_exhaustive()
}
}
@@ -347,7 +347,7 @@
out.with_super(self);
let mut member = out.field(key);
if value.flags.add() {
- member = member.add()
+ member = member.add();
}
if let Some(loc) = value.location {
member = member.with_location(loc);
@@ -395,7 +395,7 @@
pub fn get(&self, key: IStr) -> Result<Option<Val>> {
self.run_assertions()?;
- self.get_for(key, self.0.this().unwrap_or(self.clone()))
+ self.get_for(key, self.0.this().unwrap_or_else(|| self.clone()))
}
pub fn get_for(&self, key: IStr, this: ObjValue) -> Result<Option<Val>> {
@@ -474,7 +474,7 @@
type Output = Val;
fn get(self: Box<Self>) -> Result<Self::Output> {
- Ok(self.obj.get_or_bail(self.key)?)
+ self.obj.get_or_bail(self.key)
}
}
@@ -495,7 +495,7 @@
SuperDepth::default(),
&mut |depth, index, name, visibility| {
let new_sort_key = FieldSortKey::new(depth, index);
- let entry = out.entry(name.clone());
+ let entry = out.entry(name);
let (visible, _) = entry.or_insert((true, new_sort_key));
match visibility {
Visibility::Normal => {}
@@ -634,7 +634,7 @@
SuperDepth::default(),
&mut |depth, index, name, visibility| {
let new_sort_key = FieldSortKey::new(depth, index);
- let entry = out.entry(name.clone());
+ let entry = out.entry(name);
let (visible, _) = entry.or_insert((true, new_sort_key));
match visibility {
Visibility::Normal => {}
crates/jrsonnet-evaluator/src/stdlib/format.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/stdlib/format.rs
+++ b/crates/jrsonnet-evaluator/src/stdlib/format.rs
@@ -248,7 +248,7 @@
let (cflags, str) = try_parse_cflags(str)?;
let (width, str) = try_parse_field_width(str)?;
let (precision, str) = try_parse_precision(str)?;
- let (_, str) = try_parse_length_modifier(str)?;
+ let ((), str) = try_parse_length_modifier(str)?;
let (convtype, str) = parse_conversion_type(str)?;
Ok((
crates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/typed/conversions.rs
+++ b/crates/jrsonnet-evaluator/src/typed/conversions.rs
@@ -449,25 +449,21 @@
}
fn from_untyped(value: Val) -> Result<Self> {
- match &value {
- Val::Arr(a) => {
- if let Some(bytes) = a.as_any().downcast_ref::<BytesArray>() {
- return Ok(bytes.0.as_slice().into());
- };
- <Self as Typed>::TYPE.check(&value)?;
- // Any::downcast_ref::<ByteArray>(&a);
- let mut out = Vec::with_capacity(a.len());
- for e in a.iter() {
- let r = e?;
- out.push(u8::from_untyped(r)?);
- }
- Ok(out.as_slice().into())
- }
- _ => {
- <Self as Typed>::TYPE.check(&value)?;
- unreachable!()
- }
+ let Val::Arr(a) = &value else {
+ <Self as Typed>::TYPE.check(&value)?;
+ unreachable!()
+ };
+ if let Some(bytes) = a.as_any().downcast_ref::<BytesArray>() {
+ return Ok(bytes.0.as_slice().into());
+ };
+ <Self as Typed>::TYPE.check(&value)?;
+ // Any::downcast_ref::<ByteArray>(&a);
+ let mut out = Vec::with_capacity(a.len());
+ for e in a.iter() {
+ let r = e?;
+ out.push(u8::from_untyped(r)?);
}
+ Ok(out.as_slice().into())
}
}
crates/jrsonnet-evaluator/src/typed/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/typed/mod.rs
+++ b/crates/jrsonnet-evaluator/src/typed/mod.rs
@@ -90,7 +90,7 @@
item: impl Fn() -> Result<()>,
) -> Result<()> {
State::push_description(error_reason, || match item() {
- Ok(_) => Ok(()),
+ Ok(()) => Ok(()),
Err(mut e) => {
if let ErrorKind::TypeError(e) = &mut e.error_mut() {
(e.1).0.push(path());
crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -351,6 +351,8 @@
}
}
impl PartialEq for StrValue {
+ // False positive, into_flat returns not StrValue, but IStr, thus no infinite recursion here.
+ #[allow(clippy::unconditional_recursion)]
fn eq(&self, other: &Self) -> bool {
let a = self.clone().into_flat();
let b = other.clone().into_flat();
crates/jrsonnet-interner/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-interner/src/lib.rs
+++ b/crates/jrsonnet-interner/src/lib.rs
@@ -6,7 +6,7 @@
#![warn(clippy::pedantic, clippy::nursery)]
#![allow(clippy::missing_const_for_fn)]
use std::{
- borrow::{Borrow, Cow},
+ borrow::Cow,
cell::RefCell,
fmt::{self, Display},
hash::{BuildHasherDefault, Hash, Hasher},
@@ -14,7 +14,7 @@
str,
};
-use hashbrown::HashMap;
+use hashbrown::{hash_map::RawEntryMut, HashMap};
use jrsonnet_gcmodule::Trace;
use rustc_hash::FxHasher;
@@ -57,17 +57,6 @@
}
}
-impl Borrow<str> for IStr {
- fn borrow(&self) -> &str {
- self.as_str()
- }
-}
-impl Borrow<[u8]> for IStr {
- fn borrow(&self) -> &[u8] {
- self.as_bytes()
- }
-}
-
impl PartialEq for IStr {
fn eq(&self, other: &Self) -> bool {
// all IStr should be inlined into same pool
@@ -142,12 +131,6 @@
type Target = [u8];
fn deref(&self) -> &Self::Target {
- self.0.as_slice()
- }
-}
-
-impl Borrow<[u8]> for IBytes {
- fn borrow(&self) -> &[u8] {
self.0.as_slice()
}
}
@@ -285,9 +268,9 @@
let mut pool = pool.borrow_mut();
let entry = pool.raw_entry_mut().from_key(bytes);
match entry {
- hashbrown::hash_map::RawEntryMut::Occupied(i) => IBytes(i.get_key_value().0.clone()),
- hashbrown::hash_map::RawEntryMut::Vacant(e) => {
- let (k, _) = e.insert(Inner::new_bytes(bytes), ());
+ RawEntryMut::Occupied(i) => IBytes(i.get_key_value().0.clone()),
+ RawEntryMut::Vacant(e) => {
+ let (k, ()) = e.insert(Inner::new_bytes(bytes), ());
IBytes(k.clone())
}
}
crates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-macros/src/lib.rs
+++ b/crates/jrsonnet-macros/src/lib.rs
@@ -374,6 +374,7 @@
fn params(&self) -> &[BuiltinParam] {
PARAMS
}
+ #[allow(unused_variable)]
fn call(&self, ctx: Context, location: CallLocation, args: &dyn ArgsLike) -> Result<Val> {
let parsed = parse_builtin_call(ctx.clone(), &PARAMS, args, false)?;
crates/jrsonnet-stdlib/src/encoding.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/encoding.rs
+++ b/crates/jrsonnet-stdlib/src/encoding.rs
@@ -39,5 +39,5 @@
let bytes = STANDARD
.decode(str.as_bytes())
.map_err(|e| runtime_error!("invalid base64: {e}"))?;
- Ok(String::from_utf8(bytes).map_err(|_| runtime_error!("bad utf8"))?)
+ String::from_utf8(bytes).map_err(|_| runtime_error!("bad utf8"))
}
crates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth--- a/crates/jrsonnet-stdlib/src/misc.rs
+++ b/crates/jrsonnet-stdlib/src/misc.rs
@@ -47,7 +47,7 @@
.ext_natives
.get(&x)
.cloned()
- .map_or(Val::Null, |v| Val::Func(v))
+ .map_or(Val::Null, Val::Func)
}
#[builtin(fields(
flake.lockdiffbeforeafterboth--- a/flake.lock
+++ b/flake.lock
@@ -5,11 +5,11 @@
"systems": "systems"
},
"locked": {
- "lastModified": 1694529238,
- "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
+ "lastModified": 1705309234,
+ "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
"owner": "numtide",
"repo": "flake-utils",
- "rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
+ "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
"type": "github"
},
"original": {
@@ -20,11 +20,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1701376520,
- "narHash": "sha256-U3iGiOZqgu7wvVzgfoQzGGFMqNsDj/q/6zPIjCy7ajg=",
+ "lastModified": 1705391267,
+ "narHash": "sha256-gGVm9QudiRtYTX8PN9cTTy7uuJcL4I2lRMoPx496kXk=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "c74cc3c3db2ed5e68895953d75c397797d499133",
+ "rev": "41a9a7f170c740acb24f3390323877d11c69d5ee",
"type": "github"
},
"original": {
@@ -50,11 +50,11 @@
]
},
"locked": {
- "lastModified": 1701310566,
- "narHash": "sha256-CL9J3xUR2Ejni4LysrEGX0IdO+Y4BXCiH/By0lmF3eQ=",
+ "lastModified": 1705371439,
+ "narHash": "sha256-P1kulUXpYWkcrjiX3sV4j8ACJZh9XXSaaD+jDLBDLKo=",
"owner": "oxalica",
"repo": "rust-overlay",
- "rev": "6d3c6e185198b8bf7ad639f22404a75aa9a09bff",
+ "rev": "b21f3c0d5bf0f0179f5f0140e8e0cd099618bd04",
"type": "github"
},
"original": {
flake.nixdiffbeforeafterboth--- a/flake.nix
+++ b/flake.nix
@@ -25,14 +25,14 @@
lib = pkgs.lib;
rust =
(pkgs.rustChannelOf {
- date = "2023-10-28";
+ date = "2024-01-10";
channel = "nightly";
})
.default
.override {
extensions = ["rust-src" "miri" "rust-analyzer" "clippy"];
};
- in rec {
+ in {
packages = rec {
go-jsonnet = pkgs.callPackage ./nix/go-jsonnet.nix {};
sjsonnet = pkgs.callPackage ./nix/sjsonnet.nix {};