difftreelog
fix disallow field duplicates
in: master
5 files changed
crates/jrsonnet-evaluator/src/error.rsdiffbeforeafterboth636364 #[error("field name should be string, got {0}")]64 #[error("field name should be string, got {0}")]65 FieldMustBeStringGot(ValType),65 FieldMustBeStringGot(ValType),66 #[error("duplicate field name: {0}")]67 DuplicateFieldName(IStr),666867 #[error("attempted to index array with string {0}")]69 #[error("attempted to index array with string {0}")]68 AttemptedIndexAnArrayWithString(IStr),70 AttemptedIndexAnArrayWithString(IStr),crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth298 context_creator: context_creator.clone(),298 context_creator: context_creator.clone(),299 value: value.clone(),299 value: value.clone(),300 name,300 name,301 })));301 })))?;302 }302 }303 Member::Field(FieldMember {303 Member::Field(FieldMember {304 name,304 name,341 value: value.clone(),341 value: value.clone(),342 params: params.clone(),342 params: params.clone(),343 name,343 name,344 })));344 })))?;345 }345 }346 Member::BindStmt(_) => {}346 Member::BindStmt(_) => {}347 Member::AssertStmt(stmt) => {347 Member::AssertStmt(stmt) => {424 .bindable(TraceBox(Box::new(ObjCompBinding {424 .bindable(TraceBox(Box::new(ObjCompBinding {425 context: ctx,425 context: ctx,426 value: obj.value.clone(),426 value: obj.value.clone(),427 })));427 })))?;428 }428 }429 v => throw!(FieldMustBeStringGot(v.value_type())),429 v => throw!(FieldMustBeStringGot(v.value_type())),430 }430 }crates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth68 Value::Object(o) => {68 Value::Object(o) => {69 let mut builder = ObjValueBuilder::with_capacity(o.len());69 let mut builder = ObjValueBuilder::with_capacity(o.len());70 for (k, v) in o {70 for (k, v) in o {71 builder.member((k as &str).into()).value(v.try_into()?);71 builder.member((k as &str).into()).value(v.try_into()?)?;72 }72 }73 Self::Obj(builder.build())73 Self::Obj(builder.build())74 }74 }crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth1use crate::function::CallLocation;1use crate::gc::{GcHashMap, GcHashSet, TraceBox};2use crate::gc::{GcHashMap, GcHashSet, TraceBox};2use crate::operator::evaluate_add_op;3use crate::operator::evaluate_add_op;4use crate::push_frame;3use crate::{cc_ptr_eq, weak_ptr_eq, weak_raw, Bindable, LazyBinding, LazyVal, Result, Val};5use crate::{6 cc_ptr_eq, error::Error::*, throw, weak_ptr_eq, weak_raw, Bindable, LazyBinding, LazyVal,7 Result, Val,8};4use gcmodule::{Cc, Trace, Weak};9use gcmodule::{Cc, Trace, Weak};5use jrsonnet_interner::IStr;10use jrsonnet_interner::IStr;373 self.location = Some(location);378 self.location = Some(location);374 self379 self375 }380 }376 pub fn value(self, value: Val) -> &'v mut ObjValueBuilder {381 pub fn value(self, value: Val) -> Result<()> {377 self.binding(LazyBinding::Bound(LazyVal::new_resolved(value)))382 self.binding(LazyBinding::Bound(LazyVal::new_resolved(value)))378 }383 }379 pub fn bindable(self, bindable: TraceBox<dyn Bindable>) -> &'v mut ObjValueBuilder {384 pub fn bindable(self, bindable: TraceBox<dyn Bindable>) -> Result<()> {380 self.binding(LazyBinding::Bindable(Cc::new(bindable)))385 self.binding(LazyBinding::Bindable(Cc::new(bindable)))381 }386 }382 pub fn binding(self, binding: LazyBinding) -> &'v mut ObjValueBuilder {387 pub fn binding(self, binding: LazyBinding) -> Result<()> {383 self.value.map.insert(388 let old = self.value.map.insert(384 self.name,389 self.name.clone(),385 ObjMember {390 ObjMember {386 add: self.add,391 add: self.add,387 visibility: self.visibility,392 visibility: self.visibility,388 invoke: binding,393 invoke: binding,389 location: self.location,394 location: self.location.clone(),390 },395 },391 );396 );397 if old.is_some() {398 push_frame(399 CallLocation(self.location.as_ref()),392 self.value400 || format!("field <{}> initializtion", self.name.clone()),401 || throw!(DuplicateFieldName(self.name.clone())),402 )?403 }404 Ok(())393 }405 }394}406}395407crates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth459 if self.is_option() {459 if self.is_option() {460 quote! {460 quote! {461 if let Some(value) = self.#ident {461 if let Some(value) = self.#ident {462 out.member(#name.into()).value(value.try_into()?);462 out.member(#name.into()).value(value.try_into()?)?;463 }463 }464 }464 }465 } else {465 } else {466 quote! {466 quote! {467 out.member(#name.into()).value(self.#ident.try_into()?);467 out.member(#name.into()).value(self.#ident.try_into()?)?;468 }468 }469 }469 }470 } else if self.is_option() {470 } else if self.is_option() {