git.delta.rocks / jrsonnet / refs/commits / 2d0d919b58c4

difftreelog

style fix warnings with nightly clippy

Yaroslav Bolyukin2022-05-26parent: #e1e1d4b.patch.diff
in: master

9 files changed

modifiedcrates/jrsonnet-cli/src/trace.rsdiffbeforeafterboth
--- a/crates/jrsonnet-cli/src/trace.rs
+++ b/crates/jrsonnet-cli/src/trace.rs
@@ -9,7 +9,7 @@
 
 use crate::ConfigureState;
 
-#[derive(PartialEq)]
+#[derive(PartialEq, Eq)]
 pub enum TraceFormatName {
 	Compact,
 	Explaining,
modifiedcrates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/integrations/serde.rs
+++ b/crates/jrsonnet-evaluator/src/integrations/serde.rs
@@ -13,20 +13,20 @@
 
 	fn into_untyped(value: Self, s: State) -> Result<Val> {
 		Ok(match value {
-			Value::Null => Val::Null,
-			Value::Bool(v) => Val::Bool(v),
-			Value::Number(n) => Val::Num(n.as_f64().ok_or_else(|| {
+			Self::Null => Val::Null,
+			Self::Bool(v) => Val::Bool(v),
+			Self::Number(n) => Val::Num(n.as_f64().ok_or_else(|| {
 				RuntimeError(format!("json number can't be represented as jsonnet: {}", n).into())
 			})?),
-			Value::String(s) => Val::Str((&s as &str).into()),
-			Value::Array(a) => {
+			Self::String(s) => Val::Str((&s as &str).into()),
+			Self::Array(a) => {
 				let mut out: Vec<Val> = Vec::with_capacity(a.len());
 				for v in a {
 					out.push(Self::into_untyped(v, s.clone())?);
 				}
 				Val::Arr(out.into())
 			}
-			Value::Object(o) => {
+			Self::Object(o) => {
 				let mut builder = ObjValueBuilder::with_capacity(o.len());
 				for (k, v) in o {
 					builder
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
before · crates/jrsonnet-evaluator/src/lib.rs
1#![warn(clippy::all, clippy::nursery, clippy::pedantic)]2#![allow(3	macro_expanded_macro_exports_accessed_by_absolute_paths,4	clippy::ptr_arg,5	// Too verbose6	clippy::must_use_candidate,7	// A lot of functions pass around errors thrown by code8	clippy::missing_errors_doc,9	// A lot of pointers have interior Rc10	clippy::needless_pass_by_value,11	// Its fine12	clippy::wildcard_imports,13	clippy::enum_glob_use,14	clippy::module_name_repetitions,15	// TODO: fix individual issues, however this works as intended almost everywhere16	clippy::cast_precision_loss,17	clippy::cast_possible_wrap,18	clippy::cast_possible_truncation,19	clippy::cast_sign_loss,20)]2122// For jrsonnet-macros23extern crate self as jrsonnet_evaluator;2425mod ctx;26mod dynamic;27pub mod error;28mod evaluate;29pub mod function;30pub mod gc;31mod import;32mod integrations;33mod map;34mod obj;35mod stdlib;36pub mod trace;37pub mod typed;38pub mod val;3940use std::{41	borrow::Cow,42	cell::{Ref, RefCell, RefMut},43	collections::HashMap,44	fmt::{self, Debug},45	path::{Path, PathBuf},46	rc::Rc,47};4849pub use ctx::*;50pub use dynamic::*;51use error::{Error::*, LocError, Result, StackTraceElement};52pub use evaluate::*;53use function::{builtin::Builtin, CallLocation, TlaArg};54use gc::{GcHashMap, TraceBox};55use gcmodule::{Cc, Trace, Weak};56use hashbrown::hash_map::RawEntryMut;57pub use import::*;58use jrsonnet_interner::IBytes;59pub use jrsonnet_interner::IStr;60pub use jrsonnet_parser as parser;61use jrsonnet_parser::*;62pub use obj::*;63use trace::{location_to_offset, offset_to_location, CodeLocation, CompactFormat, TraceFormat};64pub use val::{ManifestFormat, Thunk, Val};6566pub trait Unbound: Trace {67	type Bound;68	fn bind(&self, s: State, sup: Option<ObjValue>, this: Option<ObjValue>) -> Result<Self::Bound>;69}7071#[derive(Clone, Trace)]72pub enum LazyBinding {73	Bindable(Cc<TraceBox<dyn Unbound<Bound = Thunk<Val>>>>),74	Bound(Thunk<Val>),75}7677impl Debug for LazyBinding {78	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {79		write!(f, "LazyBinding")80	}81}82impl LazyBinding {83	pub fn evaluate(84		&self,85		s: State,86		sup: Option<ObjValue>,87		this: Option<ObjValue>,88	) -> Result<Thunk<Val>> {89		match self {90			Self::Bindable(v) => v.bind(s, sup, this),91			Self::Bound(v) => Ok(v.clone()),92		}93	}94}9596pub struct EvaluationSettings {97	/// Limits recursion by limiting the number of stack frames98	pub max_stack: usize,99	/// Limits amount of stack trace items preserved100	pub max_trace: usize,101	/// Used for s`td.extVar`102	pub ext_vars: HashMap<IStr, TlaArg>,103	/// Used for ext.native104	pub ext_natives: HashMap<IStr, Cc<TraceBox<dyn Builtin>>>,105	/// TLA vars106	pub tla_vars: HashMap<IStr, TlaArg>,107	/// Global variables are inserted in default context108	pub globals: HashMap<IStr, Val>,109	/// Used to resolve file locations/contents110	pub import_resolver: Box<dyn ImportResolver>,111	/// Used in manifestification functions112	pub manifest_format: ManifestFormat,113	/// Used for bindings114	pub trace_format: Box<dyn TraceFormat>,115}116impl Default for EvaluationSettings {117	fn default() -> Self {118		Self {119			max_stack: 200,120			max_trace: 20,121			globals: HashMap::default(),122			ext_vars: HashMap::default(),123			ext_natives: HashMap::default(),124			tla_vars: HashMap::default(),125			import_resolver: Box::new(DummyImportResolver),126			manifest_format: ManifestFormat::Json {127				padding: 4,128				#[cfg(feature = "exp-preserve-order")]129				preserve_order: false,130			},131			trace_format: Box::new(CompactFormat {132				padding: 4,133				resolver: trace::PathResolver::Absolute,134			}),135		}136	}137}138139#[derive(Default)]140struct EvaluationData {141	/// Used for stack overflow detection, stacktrace is populated on unwind142	stack_depth: usize,143	/// Updated every time stack entry is popt144	stack_generation: usize,145146	breakpoints: Breakpoints,147148	/// Contains file source codes and evaluation results for imports and pretty-printed stacktraces149	files: GcHashMap<PathBuf, FileData>,150	/// Contains tla arguments and others, which aren't needed to be obtained by name151	volatile_files: GcHashMap<String, String>,152}153struct FileData {154	string: Option<IStr>,155	bytes: Option<IBytes>,156	parsed: Option<LocExpr>,157	evaluated: Option<Val>,158159	evaluating: bool,160}161impl FileData {162	fn new_string(data: IStr) -> Self {163		Self {164			string: Some(data),165			bytes: None,166			parsed: None,167			evaluated: None,168			evaluating: false,169		}170	}171	fn new_bytes(data: IBytes) -> Self {172		Self {173			string: None,174			bytes: Some(data),175			parsed: None,176			evaluated: None,177			evaluating: false,178		}179	}180}181182#[allow(clippy::type_complexity)]183pub struct Breakpoint {184	loc: ExprLocation,185	collected: RefCell<HashMap<usize, (usize, Vec<Result<Val>>)>>,186}187#[derive(Default)]188struct Breakpoints(Vec<Rc<Breakpoint>>);189impl Breakpoints {190	fn insert(191		&self,192		stack_depth: usize,193		stack_generation: usize,194		loc: &ExprLocation,195		result: Result<Val>,196	) -> Result<Val> {197		if self.0.is_empty() {198			return result;199		}200		for item in &self.0 {201			if item.loc.belongs_to(loc) {202				let mut collected = item.collected.borrow_mut();203				let (depth, vals) = collected.entry(stack_generation).or_default();204				if stack_depth > *depth {205					vals.clear();206				}207				vals.push(result.clone());208			}209		}210		result211	}212}213214#[derive(Default)]215pub struct EvaluationStateInternals {216	/// Internal state217	data: RefCell<EvaluationData>,218	/// Settings, safe to change at runtime219	settings: RefCell<EvaluationSettings>,220}221222/// Maintains stack trace and import resolution223#[derive(Default, Clone)]224pub struct State(Rc<EvaluationStateInternals>);225226impl State {227	pub fn import_str(&self, path: PathBuf) -> Result<IStr> {228		let mut data = self.data_mut();229		let mut file = data.files.raw_entry_mut().from_key(&path);230231		let file = match file {232			RawEntryMut::Occupied(ref mut d) => d.get_mut(),233			RawEntryMut::Vacant(v) => {234				let data = self.settings().import_resolver.load_file_contents(&path)?;235				v.insert(236					path.clone(),237					FileData::new_string(238						std::str::from_utf8(&data)239							.map_err(|_| ImportBadFileUtf8(path.clone()))?240							.into(),241					),242				)243				.1244			}245		};246		if let Some(str) = &file.string {247			return Ok(str.clone());248		}249		if file.string.is_none() {250			file.string = Some(251				file.bytes252					.as_ref()253					.expect("either string or bytes should be set")254					.clone()255					.cast_str()256					.ok_or_else(|| ImportBadFileUtf8(path.clone()))?,257			);258		}259		Ok(file.string.as_ref().expect("just set").clone())260	}261	pub fn import_bin(&self, path: PathBuf) -> Result<IBytes> {262		let mut data = self.data_mut();263		let mut file = data.files.raw_entry_mut().from_key(&path);264265		let file = match file {266			RawEntryMut::Occupied(ref mut d) => d.get_mut(),267			RawEntryMut::Vacant(v) => {268				let data = self.settings().import_resolver.load_file_contents(&path)?;269				v.insert(path.clone(), FileData::new_bytes(data.as_slice().into()))270					.1271			}272		};273		if let Some(str) = &file.bytes {274			return Ok(str.clone());275		}276		if file.bytes.is_none() {277			file.bytes = Some(278				file.string279					.as_ref()280					.expect("either string or bytes should be set")281					.clone()282					.cast_bytes(),283			);284		}285		Ok(file.bytes.as_ref().expect("just set").clone())286	}287	pub fn import(&self, path: PathBuf) -> Result<Val> {288		let mut data = self.data_mut();289		let mut file = data.files.raw_entry_mut().from_key(&path);290291		let file = match file {292			RawEntryMut::Occupied(ref mut d) => d.get_mut(),293			RawEntryMut::Vacant(v) => {294				let data = self.settings().import_resolver.load_file_contents(&path)?;295				v.insert(296					path.clone(),297					FileData::new_string(298						std::str::from_utf8(&data)299							.map_err(|_| ImportBadFileUtf8(path.clone()))?300							.into(),301					),302				)303				.1304			}305		};306		if let Some(val) = &file.evaluated {307			return Ok(val.clone());308		}309		if file.string.is_none() {310			file.string = Some(311				std::str::from_utf8(312					file.bytes313						.as_ref()314						.expect("either string or bytes should be set"),315				)316				.map_err(|_| ImportBadFileUtf8(path.clone()))?317				.into(),318			);319		}320		let code = file.string.as_ref().expect("just set");321		let file_name = Source::new(path.clone()).expect("resolver should return correct name");322		if file.parsed.is_none() {323			file.parsed = Some(324				jrsonnet_parser::parse(325					code,326					&ParserSettings {327						file_name: file_name.clone(),328					},329				)330				.map_err(|e| ImportSyntaxError {331					path: file_name,332					source_code: code.clone(),333					error: Box::new(e),334				})?,335			);336		}337		let parsed = file.parsed.as_ref().expect("just set").clone();338		if file.evaluating {339			throw!(InfiniteRecursionDetected)340		}341		file.evaluating = true;342		// Dropping file here, as it borrows data, which may be used in evaluation343		drop(data);344		let res = evaluate(self.clone(), self.create_default_context(), &parsed);345346		let mut data = self.data_mut();347		let mut file = data.files.raw_entry_mut().from_key(&path);348349		let file = match file {350			RawEntryMut::Occupied(ref mut d) => d.get_mut(),351			RawEntryMut::Vacant(_) => unreachable!("this file was just here!"),352		};353		file.evaluating = false;354		match res {355			Ok(v) => {356				file.evaluated = Some(v.clone());357				Ok(v)358			}359			Err(e) => Err(e),360		}361	}362363	pub fn get_source(&self, name: Source) -> Option<String> {364		let data = self.data();365		match name.repr() {366			Ok(real) => data367				.files368				.get(real)369				.and_then(|f| f.string.as_ref())370				.map(ToString::to_string),371			Err(e) => data.volatile_files.get(e).map(ToOwned::to_owned),372		}373	}374	pub fn map_source_locations(&self, file: Source, locs: &[u32]) -> Vec<CodeLocation> {375		offset_to_location(&self.get_source(file).unwrap_or_else(|| "".into()), locs)376	}377	pub fn map_from_source_location(378		&self,379		file: Source,380		line: usize,381		column: usize,382	) -> Option<usize> {383		location_to_offset(384			&self.get_source(file).expect("file not found"),385			line,386			column,387		)388	}389	/// Adds standard library global variable (std) to this evaluator390	pub fn with_stdlib(&self) -> &Self {391		let val = evaluate(392			self.clone(),393			self.create_default_context(),394			&stdlib::get_parsed_stdlib(),395		)396		.expect("std should not fail");397		self.settings_mut().globals.insert("std".into(), val);398		self399	}400401	/// Creates context with all passed global variables402	pub fn create_default_context(&self) -> Context {403		let globals = &self.settings().globals;404		let mut new_bindings = GcHashMap::with_capacity(globals.len());405		for (name, value) in globals.iter() {406			new_bindings.insert(name.clone(), Thunk::evaluated(value.clone()));407		}408		Context::new().extend(new_bindings, None, None, None)409	}410411	/// Executes code creating a new stack frame412	pub fn push<T>(413		&self,414		e: CallLocation,415		frame_desc: impl FnOnce() -> String,416		f: impl FnOnce() -> Result<T>,417	) -> Result<T> {418		{419			let mut data = self.data_mut();420			let stack_depth = &mut data.stack_depth;421			if *stack_depth > self.max_stack() {422				// Error creation uses data, so i drop guard here423				drop(data);424				throw!(StackOverflow);425			}426			*stack_depth += 1;427		}428		let result = f();429		{430			let mut data = self.data_mut();431			data.stack_depth -= 1;432			data.stack_generation += 1;433		}434		if let Err(mut err) = result {435			err.trace_mut().0.push(StackTraceElement {436				location: e.0.cloned(),437				desc: frame_desc(),438			});439			return Err(err);440		}441		result442	}443444	/// Executes code creating a new stack frame445	pub fn push_val(446		&self,447		e: &ExprLocation,448		frame_desc: impl FnOnce() -> String,449		f: impl FnOnce() -> Result<Val>,450	) -> Result<Val> {451		{452			let mut data = self.data_mut();453			let stack_depth = &mut data.stack_depth;454			if *stack_depth > self.max_stack() {455				// Error creation uses data, so i drop guard here456				drop(data);457				throw!(StackOverflow);458			}459			*stack_depth += 1;460		}461		let mut result = f();462		{463			let mut data = self.data_mut();464			data.stack_depth -= 1;465			data.stack_generation += 1;466			result = data467				.breakpoints468				.insert(data.stack_depth, data.stack_generation, e, result);469		}470		if let Err(mut err) = result {471			err.trace_mut().0.push(StackTraceElement {472				location: Some(e.clone()),473				desc: frame_desc(),474			});475			return Err(err);476		}477		result478	}479	/// Executes code creating a new stack frame480	pub fn push_description<T>(481		&self,482		frame_desc: impl FnOnce() -> String,483		f: impl FnOnce() -> Result<T>,484	) -> Result<T> {485		{486			let mut data = self.data_mut();487			let stack_depth = &mut data.stack_depth;488			if *stack_depth > self.max_stack() {489				// Error creation uses data, so i drop guard here490				drop(data);491				throw!(StackOverflow);492			}493			*stack_depth += 1;494		}495		let result = f();496		{497			let mut data = self.data_mut();498			data.stack_depth -= 1;499			data.stack_generation += 1;500		}501		if let Err(mut err) = result {502			err.trace_mut().0.push(StackTraceElement {503				location: None,504				desc: frame_desc(),505			});506			return Err(err);507		}508		result509	}510511	/// # Panics512	/// In case of formatting failure513	pub fn stringify_err(&self, e: &LocError) -> String {514		let mut out = String::new();515		self.settings()516			.trace_format517			.write_trace(&mut out, self, e)518			.unwrap();519		out520	}521522	pub fn manifest(&self, val: Val) -> Result<IStr> {523		self.push_description(524			|| "manifestification".to_string(),525			|| val.manifest(self.clone(), &self.manifest_format()),526		)527	}528	pub fn manifest_multi(&self, val: Val) -> Result<Vec<(IStr, IStr)>> {529		val.manifest_multi(self.clone(), &self.manifest_format())530	}531	pub fn manifest_stream(&self, val: Val) -> Result<Vec<IStr>> {532		val.manifest_stream(self.clone(), &self.manifest_format())533	}534535	/// If passed value is function then call with set TLA536	pub fn with_tla(&self, val: Val) -> Result<Val> {537		Ok(match val {538			Val::Func(func) => self.push_description(539				|| "during TLA call".to_owned(),540				|| {541					func.evaluate(542						self.clone(),543						self.create_default_context(),544						CallLocation::native(),545						&self.settings().tla_vars,546						true,547					)548				},549			)?,550			v => v,551		})552	}553}554555/// Internals556impl State {557	fn data(&self) -> Ref<EvaluationData> {558		self.0.data.borrow()559	}560	fn data_mut(&self) -> RefMut<EvaluationData> {561		self.0.data.borrow_mut()562	}563	pub fn settings(&self) -> Ref<EvaluationSettings> {564		self.0.settings.borrow()565	}566	pub fn settings_mut(&self) -> RefMut<EvaluationSettings> {567		self.0.settings.borrow_mut()568	}569}570571/// Raw methods evaluate passed values but don't perform TLA execution572impl State {573	/// Parses and evaluates the given snippet574	pub fn evaluate_snippet(&self, name: String, code: String) -> Result<Val> {575		let source = Source::new_virtual(Cow::Owned(name.clone()));576		let parsed = jrsonnet_parser::parse(577			&code,578			&ParserSettings {579				file_name: source.clone(),580			},581		)582		.map_err(|e| ImportSyntaxError {583			path: source,584			source_code: code.clone().into(),585			error: Box::new(e),586		})?;587		self.data_mut().volatile_files.insert(name, code);588		evaluate(self.clone(), self.create_default_context(), &parsed)589	}590}591592/// Settings utilities593impl State {594	pub fn add_ext_var(&self, name: IStr, value: Val) {595		self.settings_mut()596			.ext_vars597			.insert(name, TlaArg::Val(value));598	}599	pub fn add_ext_str(&self, name: IStr, value: IStr) {600		self.settings_mut()601			.ext_vars602			.insert(name, TlaArg::String(value));603	}604	pub fn add_ext_code(&self, name: &str, code: String) -> Result<()> {605		let source_name = format!("<extvar:{}>", name);606		let source = Source::new_virtual(Cow::Owned(source_name.clone()));607		let parsed = jrsonnet_parser::parse(608			&code,609			&ParserSettings {610				file_name: source.clone(),611			},612		)613		.map_err(|e| ImportSyntaxError {614			path: source,615			source_code: code.clone().into(),616			error: Box::new(e),617		})?;618		self.data_mut().volatile_files.insert(source_name, code);619		self.settings_mut()620			.ext_vars621			.insert(name.into(), TlaArg::Code(parsed));622		Ok(())623	}624625	pub fn add_tla(&self, name: IStr, value: Val) {626		self.settings_mut()627			.tla_vars628			.insert(name, TlaArg::Val(value));629	}630	pub fn add_tla_str(&self, name: IStr, value: IStr) {631		self.settings_mut()632			.tla_vars633			.insert(name, TlaArg::String(value));634	}635	pub fn add_tla_code(&self, name: IStr, code: &str) -> Result<()> {636		let source_name = format!("<top-level-arg:{}>", name);637		let source = Source::new_virtual(Cow::Owned(source_name.clone()));638		let parsed = jrsonnet_parser::parse(639			code,640			&ParserSettings {641				file_name: source.clone(),642			},643		)644		.map_err(|e| ImportSyntaxError {645			path: source,646			source_code: code.into(),647			error: Box::new(e),648		})?;649		self.data_mut()650			.volatile_files651			.insert(source_name, code.to_owned());652		self.settings_mut()653			.tla_vars654			.insert(name, TlaArg::Code(parsed));655		Ok(())656	}657658	pub fn resolve_file(&self, from: &Path, path: &str) -> Result<PathBuf> {659		self.settings()660			.import_resolver661			.resolve_file(from, path.as_ref())662	}663664	pub fn import_resolver(&self) -> Ref<dyn ImportResolver> {665		Ref::map(self.settings(), |s| &*s.import_resolver)666	}667	pub fn set_import_resolver(&self, resolver: Box<dyn ImportResolver>) {668		self.settings_mut().import_resolver = resolver;669	}670671	pub fn add_native(&self, name: IStr, cb: Cc<TraceBox<dyn Builtin>>) {672		self.settings_mut().ext_natives.insert(name, cb);673	}674675	pub fn manifest_format(&self) -> ManifestFormat {676		self.settings().manifest_format.clone()677	}678	pub fn set_manifest_format(&self, format: ManifestFormat) {679		self.settings_mut().manifest_format = format;680	}681682	pub fn trace_format(&self) -> Ref<dyn TraceFormat> {683		Ref::map(self.settings(), |s| &*s.trace_format)684	}685	pub fn set_trace_format(&self, format: Box<dyn TraceFormat>) {686		self.settings_mut().trace_format = format;687	}688689	pub fn max_trace(&self) -> usize {690		self.settings().max_trace691	}692	pub fn set_max_trace(&self, trace: usize) {693		self.settings_mut().max_trace = trace;694	}695696	pub fn max_stack(&self) -> usize {697		self.settings().max_stack698	}699	pub fn set_max_stack(&self, trace: usize) {700		self.settings_mut().max_stack = trace;701	}702}703704pub fn cc_ptr_eq<T>(a: &Cc<T>, b: &Cc<T>) -> bool {705	let a = a as &T;706	let b = b as &T;707	std::ptr::eq(a, b)708}709710fn weak_raw<T>(a: Weak<T>) -> *const () {711	unsafe { std::mem::transmute(a) }712}713fn weak_ptr_eq<T>(a: Weak<T>, b: Weak<T>) -> bool {714	std::ptr::eq(weak_raw(a), weak_raw(b))715}716717#[test]718fn weak_unsafe() {719	let a = Cc::new(1);720	let b = Cc::new(2);721722	let aw1 = a.clone().downgrade();723	let aw2 = a.clone().downgrade();724	let aw3 = a.clone().downgrade();725726	let bw = b.clone().downgrade();727728	assert!(weak_ptr_eq(aw1, aw2));729	assert!(!weak_ptr_eq(aw3, bw));730}
modifiedcrates/jrsonnet-evaluator/src/stdlib/format.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/stdlib/format.rs
+++ b/crates/jrsonnet-evaluator/src/stdlib/format.rs
@@ -120,7 +120,7 @@
 	Ok((out, &str[i..]))
 }
 
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Eq)]
 pub enum Width {
 	Star,
 	Fixed(usize),
@@ -174,7 +174,7 @@
 	Ok(((), &str[idx..]))
 }
 
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Eq)]
 pub enum ConvTypeV {
 	Decimal,
 	Octal,
modifiedcrates/jrsonnet-evaluator/src/stdlib/manifest.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/stdlib/manifest.rs
+++ b/crates/jrsonnet-evaluator/src/stdlib/manifest.rs
@@ -3,7 +3,7 @@
 	throw, State, Val,
 };
 
-#[derive(PartialEq, Clone, Copy)]
+#[derive(PartialEq, Eq, Clone, Copy)]
 pub enum ManifestType {
 	// Applied in manifestification
 	Manifest,
modifiedcrates/jrsonnet-evaluator/src/trace/location.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/trace/location.rs
+++ b/crates/jrsonnet-evaluator/src/trace/location.rs
@@ -1,5 +1,5 @@
 #[allow(clippy::module_name_repetitions)]
-#[derive(Clone, PartialEq, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug)]
 pub struct CodeLocation {
 	pub offset: usize,
 
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -476,43 +476,43 @@
 impl Val {
 	pub const fn as_bool(&self) -> Option<bool> {
 		match self {
-			Val::Bool(v) => Some(*v),
+			Self::Bool(v) => Some(*v),
 			_ => None,
 		}
 	}
 	pub const fn as_null(&self) -> Option<()> {
 		match self {
-			Val::Null => Some(()),
+			Self::Null => Some(()),
 			_ => None,
 		}
 	}
 	pub fn as_str(&self) -> Option<IStr> {
 		match self {
-			Val::Str(s) => Some(s.clone()),
+			Self::Str(s) => Some(s.clone()),
 			_ => None,
 		}
 	}
 	pub const fn as_num(&self) -> Option<f64> {
 		match self {
-			Val::Num(n) => Some(*n),
+			Self::Num(n) => Some(*n),
 			_ => None,
 		}
 	}
 	pub fn as_arr(&self) -> Option<ArrValue> {
 		match self {
-			Val::Arr(a) => Some(a.clone()),
+			Self::Arr(a) => Some(a.clone()),
 			_ => None,
 		}
 	}
 	pub fn as_obj(&self) -> Option<ObjValue> {
 		match self {
-			Val::Obj(o) => Some(o.clone()),
+			Self::Obj(o) => Some(o.clone()),
 			_ => None,
 		}
 	}
 	pub fn as_func(&self) -> Option<FuncVal> {
 		match self {
-			Val::Func(f) => Some(f.clone()),
+			Self::Func(f) => Some(f.clone()),
 			_ => None,
 		}
 	}
modifiedcrates/jrsonnet-interner/src/inner.rsdiffbeforeafterboth
--- a/crates/jrsonnet-interner/src/inner.rs
+++ b/crates/jrsonnet-interner/src/inner.rs
@@ -157,7 +157,7 @@
 	pub fn ptr_eq(a: &Self, b: &Self) -> bool {
 		a.0 == b.0
 	}
-	pub fn as_ptr(this: &Self) -> *const u8 {
+	pub const fn as_ptr(this: &Self) -> *const u8 {
 		// SAFETY: data is initialized
 		unsafe { this.0.as_ptr().add(mem::size_of::<InnerHeader>()) }
 	}
modifiedcrates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth
--- a/crates/jrsonnet-parser/src/expr.rs
+++ b/crates/jrsonnet-parser/src/expr.rs
@@ -21,7 +21,7 @@
 }
 
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[derive(Debug, Clone, Copy, PartialEq, Trace)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]
 pub enum Visibility {
 	/// :
 	Normal,
@@ -60,7 +60,7 @@
 }
 
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[derive(Debug, Clone, Copy, PartialEq, Trace)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]
 pub enum UnaryOpType {
 	Plus,
 	Minus,
@@ -85,7 +85,7 @@
 }
 
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[derive(Debug, Clone, Copy, PartialEq, Trace)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Trace)]
 pub enum BinaryOpType {
 	Mul,
 	Div,
@@ -179,7 +179,7 @@
 }
 
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[derive(Debug, Clone, PartialEq, Trace)]
+#[derive(Debug, Clone, PartialEq, Eq, Trace)]
 pub enum DestructRest {
 	/// ...rest
 	Keep(IStr),
@@ -188,7 +188,7 @@
 }
 
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[derive(Debug, Clone, PartialEq, Trace)]
+#[derive(Debug, Clone, PartialEq, Eq, Trace)]
 pub enum Destruct {
 	Full(IStr),
 	#[cfg(feature = "exp-destruct")]
@@ -263,7 +263,7 @@
 }
 
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[derive(Debug, PartialEq, Clone, Copy, Trace)]
+#[derive(Debug, PartialEq, Eq, Clone, Copy, Trace)]
 pub enum LiteralType {
 	This,
 	Super,
@@ -357,7 +357,7 @@
 
 /// file, begin offset, end offset
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-#[derive(Clone, PartialEq, Trace)]
+#[derive(Clone, PartialEq, Eq, Trace)]
 #[skip_trace]
 #[repr(C)]
 pub struct ExprLocation(pub Source, pub u32, pub u32);