difftreelog
style use let-else
in: master
7 files changed
crates/jrsonnet-evaluator/src/evaluate/destructure.rsdiffbeforeafterboth1use jrsonnet_gcmodule::Trace;2use jrsonnet_interner::IStr;3use jrsonnet_parser::{BindSpec, Destruct, LocExpr, ParamsDesc};45use crate::{6 error::{Error::*, Result},7 evaluate, evaluate_method, evaluate_named,8 gc::GcHashMap,9 tb, throw,10 val::ThunkValue,11 Context, Pending, Thunk, Val,12};1314#[allow(clippy::too_many_lines)]15#[allow(unused_variables)]16pub fn destruct(17 d: &Destruct,18 parent: Thunk<Val>,19 fctx: Pending<Context>,20 new_bindings: &mut GcHashMap<IStr, Thunk<Val>>,21) -> Result<()> {22 match d {23 Destruct::Full(v) => {24 let old = new_bindings.insert(v.clone(), parent);25 if old.is_some() {26 throw!(DuplicateLocalVar(v.clone()))27 }28 }29 #[cfg(feature = "exp-destruct")]30 Destruct::Skip => {}31 #[cfg(feature = "exp-destruct")]32 Destruct::Array { start, rest, end } => {33 use jrsonnet_parser::DestructRest;3435 use crate::val::ArrValue;3637 #[derive(Trace)]38 struct DataThunk {39 parent: Thunk<Val>,40 min_len: usize,41 has_rest: bool,42 }43 impl ThunkValue for DataThunk {44 type Output = ArrValue;4546 fn get(self: Box<Self>) -> Result<Self::Output> {47 let v = self.parent.evaluate()?;48 let arr = match v {49 Val::Arr(a) => a,50 _ => throw!("expected array"),51 };52 if !self.has_rest {53 if arr.len() != self.min_len {54 throw!("expected {} elements, got {}", self.min_len, arr.len())55 }56 } else if arr.len() < self.min_len {57 throw!(58 "expected at least {} elements, but array was only {}",59 self.min_len,60 arr.len()61 )62 }63 Ok(arr)64 }65 }6667 let full = Thunk::new(tb!(DataThunk {68 min_len: start.len() + end.len(),69 has_rest: rest.is_some(),70 parent,71 }));7273 {74 #[derive(Trace)]75 struct BaseThunk {76 full: Thunk<ArrValue>,77 index: usize,78 }79 impl ThunkValue for BaseThunk {80 type Output = Val;8182 fn get(self: Box<Self>) -> Result<Self::Output> {83 let full = self.full.evaluate()?;84 Ok(full.get(self.index)?.expect("length is checked"))85 }86 }87 for (i, d) in start.iter().enumerate() {88 destruct(89 d,90 Thunk::new(tb!(BaseThunk {91 full: full.clone(),92 index: i,93 })),94 fctx.clone(),95 new_bindings,96 )?;97 }98 }99100 match rest {101 Some(DestructRest::Keep(v)) => {102 #[derive(Trace)]103 struct RestThunk {104 full: Thunk<ArrValue>,105 start: usize,106 end: usize,107 }108 impl ThunkValue for RestThunk {109 type Output = Val;110111 fn get(self: Box<Self>) -> Result<Self::Output> {112 let full = self.full.evaluate()?;113 let to = full.len() - self.end;114 Ok(Val::Arr(full.slice(Some(self.start), Some(to), None)))115 }116 }117118 destruct(119 &Destruct::Full(v.clone()),120 Thunk::new(tb!(RestThunk {121 full: full.clone(),122 start: start.len(),123 end: end.len(),124 })),125 fctx.clone(),126 new_bindings,127 )?;128 }129 Some(DestructRest::Drop) => {}130 None => {}131 }132133 {134 #[derive(Trace)]135 struct EndThunk {136 full: Thunk<ArrValue>,137 index: usize,138 end: usize,139 }140 impl ThunkValue for EndThunk {141 type Output = Val;142143 fn get(self: Box<Self>) -> Result<Self::Output> {144 let full = self.full.evaluate()?;145 Ok(full146 .get(full.len() - self.end + self.index)?147 .expect("length is checked"))148 }149 }150 for (i, d) in end.iter().enumerate() {151 destruct(152 d,153 Thunk::new(tb!(EndThunk {154 full: full.clone(),155 index: i,156 end: end.len(),157 })),158 fctx.clone(),159 new_bindings,160 )?;161 }162 }163 }164 #[cfg(feature = "exp-destruct")]165 Destruct::Object { fields, rest } => {166 use crate::obj::ObjValue;167168 #[derive(Trace)]169 struct DataThunk {170 parent: Thunk<Val>,171 field_names: Vec<IStr>,172 has_rest: bool,173 }174 impl ThunkValue for DataThunk {175 type Output = ObjValue;176177 fn get(self: Box<Self>) -> Result<Self::Output> {178 let v = self.parent.evaluate()?;179 let obj = match v {180 Val::Obj(o) => o,181 _ => throw!("expected object"),182 };183 for field in &self.field_names {184 if !obj.has_field_ex(field.clone(), true) {185 throw!("missing field: {}", field);186 }187 }188 if !self.has_rest {189 let len = obj.len();190 if len != self.field_names.len() {191 throw!("too many fields, and rest not found");192 }193 }194 Ok(obj)195 }196 }197 let field_names: Vec<_> = fields198 .iter()199 .filter(|f| f.2.is_none())200 .map(|f| f.0.clone())201 .collect();202 let full = Thunk::new(tb!(DataThunk {203 parent,204 field_names: field_names.clone(),205 has_rest: rest.is_some()206 }));207208 for (field, d, default) in fields {209 #[derive(Trace)]210 struct FieldThunk {211 full: Thunk<ObjValue>,212 field: IStr,213 default: Option<(Pending<Context>, LocExpr)>,214 }215 impl ThunkValue for FieldThunk {216 type Output = Val;217218 fn get(self: Box<Self>) -> Result<Self::Output> {219 let full = self.full.evaluate()?;220 if let Some(field) = full.get(self.field)? {221 Ok(field)222 } else {223 let (fctx, expr) = self.default.as_ref().expect("shape is checked");224 Ok(evaluate(fctx.clone().unwrap(), &expr)?)225 }226 }227 }228 let value = Thunk::new(tb!(FieldThunk {229 full: full.clone(),230 field: field.clone(),231 default: default.clone().map(|e| (fctx.clone(), e)),232 }));233 if let Some(d) = d {234 destruct(d, value, fctx.clone(), new_bindings)?;235 } else {236 destruct(237 &Destruct::Full(field.clone()),238 value,239 fctx.clone(),240 new_bindings,241 )?;242 }243 }244 }245 }246 Ok(())247}248249pub fn evaluate_dest(250 d: &BindSpec,251 fctx: Pending<Context>,252 new_bindings: &mut GcHashMap<IStr, Thunk<Val>>,253) -> Result<()> {254 match d {255 BindSpec::Field { into, value } => {256 #[derive(Trace)]257 struct EvaluateThunkValue {258 name: Option<IStr>,259 fctx: Pending<Context>,260 expr: LocExpr,261 }262 impl ThunkValue for EvaluateThunkValue {263 type Output = Val;264 fn get(self: Box<Self>) -> Result<Self::Output> {265 self.name.map_or_else(266 || evaluate(self.fctx.unwrap(), &self.expr),267 |name| evaluate_named(self.fctx.unwrap(), &self.expr, name),268 )269 }270 }271 let data = Thunk::new(tb!(EvaluateThunkValue {272 name: into.name(),273 fctx: fctx.clone(),274 expr: value.clone(),275 }));276 destruct(into, data, fctx, new_bindings)?;277 }278 BindSpec::Function {279 name,280 params,281 value,282 } => {283 #[derive(Trace)]284 struct MethodThunk {285 fctx: Pending<Context>,286 name: IStr,287 params: ParamsDesc,288 value: LocExpr,289 }290 impl ThunkValue for MethodThunk {291 type Output = Val;292293 fn get(self: Box<Self>) -> Result<Self::Output> {294 Ok(evaluate_method(295 self.fctx.unwrap(),296 self.name,297 self.params,298 self.value,299 ))300 }301 }302303 let old = new_bindings.insert(304 name.clone(),305 Thunk::new(tb!(MethodThunk {306 fctx,307 name: name.clone(),308 params: params.clone(),309 value: value.clone()310 })),311 );312 if old.is_some() {313 throw!(DuplicateLocalVar(name.clone()))314 }315 }316 }317 Ok(())318}crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -162,9 +162,7 @@
}
let name = evaluate_field_name(ctx.clone(), name)?;
- let name = if let Some(name) = name {
- name
- } else {
+ let Some(name) = name else {
continue;
};
crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/lib.rs
+++ b/crates/jrsonnet-evaluator/src/lib.rs
@@ -344,10 +344,10 @@
let mut file_cache = self.file_cache();
let mut file = file_cache.raw_entry_mut().from_key(&path);
- let file = match file {
- RawEntryMut::Occupied(ref mut d) => d.get_mut(),
- RawEntryMut::Vacant(_) => unreachable!("this file was just here!"),
+ let RawEntryMut::Occupied(file) = &mut file else {
+ unreachable!("this file was just here!")
};
+ let file = file.get_mut();
file.evaluating = false;
match res {
Ok(v) => {
crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -54,12 +54,8 @@
ThunkInner::Pending => return Err(InfiniteRecursionDetected.into()),
ThunkInner::Waiting(..) => (),
};
- let value = if let ThunkInner::Waiting(value) =
- std::mem::replace(&mut *self.0.borrow_mut(), ThunkInner::Pending)
- {
- value
- } else {
- unreachable!()
+ let ThunkInner::Waiting(value) = std::mem::replace(&mut *self.0.borrow_mut(), ThunkInner::Pending) else {
+ unreachable!();
};
let new_value = match value.0.get() {
Ok(v) => v,
@@ -668,9 +664,8 @@
/// Expects value to be object, outputs (key, manifested value) pairs
pub fn manifest_multi(&self, ty: &ManifestFormat) -> Result<Vec<(IStr, IStr)>> {
- let obj = match self {
- Self::Obj(obj) => obj,
- _ => throw!(MultiManifestOutputIsNotAObject),
+ let Self::Obj(obj) = self else {
+ throw!(MultiManifestOutputIsNotAObject);
};
let keys = obj.fields(
#[cfg(feature = "exp-preserve-order")]
@@ -689,9 +684,8 @@
/// Expects value to be array, outputs manifested values
pub fn manifest_stream(&self, ty: &ManifestFormat) -> Result<Vec<IStr>> {
- let arr = match self {
- Self::Arr(a) => a,
- _ => throw!(StreamManifestOutputIsNotAArray),
+ let Self::Arr(arr) = self else {
+ throw!(StreamManifestOutputIsNotAArray);
};
let mut out = Vec::with_capacity(arr.len());
for i in arr.iter() {
@@ -703,9 +697,8 @@
pub fn manifest(&self, ty: &ManifestFormat) -> Result<IStr> {
Ok(match ty {
ManifestFormat::YamlStream(format) => {
- let arr = match self {
- Self::Arr(a) => a,
- _ => throw!(StreamManifestOutputIsNotAArray),
+ let Self::Arr(arr) = self else {
+ throw!(StreamManifestOutputIsNotAArray)
};
let mut out = String::new();
crates/jrsonnet-macros/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-macros/src/lib.rs
+++ b/crates/jrsonnet-macros/src/lib.rs
@@ -50,25 +50,22 @@
}
fn extract_type_from_option(ty: &Type) -> Result<Option<&Type>> {
- Ok(if let Some(args) = type_is_path(ty, "Option") {
- // It should have only on angle-bracketed param ("<String>"):
- let generic_arg = match args {
- PathArguments::AngleBracketed(params) => params.args.iter().next().unwrap(),
- _ => return Err(Error::new(args.span(), "missing option generic")),
- };
- // This argument must be a type:
- match generic_arg {
- GenericArgument::Type(ty) => Some(ty),
- _ => {
- return Err(Error::new(
- generic_arg.span(),
- "option generic should be a type",
- ))
- }
- }
- } else {
- None
- })
+ let Some(args) = type_is_path(ty, "Option") else {
+ return Ok(None)
+ };
+ // It should have only on angle-bracketed param ("<String>"):
+ let PathArguments::AngleBracketed(params) = args else {
+ return Err(Error::new(args.span(), "missing option generic"));
+ };
+ let generic_arg = params.args.iter().next().unwrap();
+ // This argument must be a type:
+ let GenericArgument::Type(ty) = generic_arg else {
+ return Err(Error::new(
+ generic_arg.span(),
+ "option generic should be a type",
+ ))
+ };
+ Ok(Some(ty))
}
struct Field {
@@ -137,9 +134,8 @@
impl ArgInfo {
fn parse(name: &str, arg: &FnArg) -> Result<Self> {
- let arg = match arg {
- FnArg::Receiver(_) => unreachable!(),
- FnArg::Typed(a) => a,
+ let FnArg::Typed(arg) = arg else {
+ unreachable!()
};
let ident = match &arg.pat as &Pat {
Pat::Ident(i) => Some(i.ident.clone()),
@@ -206,33 +202,28 @@
}
fn builtin_inner(attr: BuiltinAttrs, fun: ItemFn) -> syn::Result<TokenStream> {
- let result = match fun.sig.output {
- ReturnType::Default => {
- return Err(Error::new(
- fun.sig.span(),
- "builtin should return something",
- ))
- }
- ReturnType::Type(_, ref ty) => ty.clone(),
+ let ReturnType::Type(_, result) = &fun.sig.output else {
+ return Err(Error::new(
+ fun.sig.span(),
+ "builtin should return something",
+ ))
};
- let result_inner = if let Some(args) = type_is_path(&result, "Result") {
- let generic_arg = match args {
- PathArguments::AngleBracketed(params) => params.args.iter().next().unwrap(),
- _ => return Err(Error::new(args.span(), "missing result generic")),
- };
- // This argument must be a type:
- match generic_arg {
- GenericArgument::Type(ty) => ty,
- _ => {
- return Err(Error::new(
- generic_arg.span(),
- "option generic should be a type",
- ))
- }
- }
- } else {
+
+ let Some(args) = type_is_path(result, "Result") else {
return Err(Error::new(result.span(), "return value should be result"));
+
+ };
+ let PathArguments::AngleBracketed(params) = args else {
+ return Err(Error::new(args.span(), "missing result generic"));
};
+ let generic_arg = params.args.iter().next().unwrap();
+ // This argument must be a type:
+ let GenericArgument::Type(result_inner) = generic_arg else {
+ return Err(Error::new(
+ generic_arg.span(),
+ "option generic should be a type",
+ ))
+ };
let name = fun.sig.ident.to_string();
let args = fun
@@ -471,9 +462,7 @@
impl TypedField {
fn parse(field: &syn::Field) -> Result<Self> {
let attr = parse_attr::<TypedAttr, _>(&field.attrs, "typed")?.unwrap_or_default();
- let ident = if let Some(ident) = field.ident.clone() {
- ident
- } else {
+ let Some(ident) = field.ident.clone() else {
return Err(Error::new(
field.span(),
"this field should appear in output object, but it has no visible name",
@@ -603,9 +592,8 @@
}
fn derive_typed_inner(input: DeriveInput) -> Result<TokenStream> {
- let data = match &input.data {
- syn::Data::Struct(s) => s,
- _ => return Err(Error::new(input.span(), "only structs supported")),
+ let syn::Data::Struct(data) = &input.data else {
+ return Err(Error::new(input.span(), "only structs supported"));
};
let ident = &input.ident;
crates/jrsonnet-parser/src/source.rsdiffbeforeafterboth--- a/crates/jrsonnet-parser/src/source.rs
+++ b/crates/jrsonnet-parser/src/source.rs
@@ -32,10 +32,8 @@
self.hash(&mut hasher)
}
fn dyn_eq(&self, other: &dyn $T) -> bool {
- let other = if let Some(v) = other.as_any().downcast_ref::<Self>() {
- v
- } else {
- return false;
+ let Some(other) = other.as_any().downcast_ref::<Self>() else {
+ return false
};
let this = <Self as $T>::as_any(self)
.downcast_ref::<Self>()
tests/tests/sanity.rsdiffbeforeafterboth--- a/tests/tests/sanity.rs
+++ b/tests/tests/sanity.rs
@@ -22,17 +22,15 @@
s.with_stdlib();
{
- let e = match s.evaluate_snippet("snip".to_owned(), "assert 1 == 2: 'fail'; null") {
- Ok(_) => throw!("assertion should fail"),
- Err(e) => e,
+ let Err(e) = s.evaluate_snippet("snip".to_owned(), "assert 1 == 2: 'fail'; null") else {
+ throw!("assertion should fail");
};
let e = s.stringify_err(&e);
ensure!(e.starts_with("assert failed: fail\n"));
}
{
- let e = match s.evaluate_snippet("snip".to_owned(), "std.assertEqual(1, 2)") {
- Ok(_) => throw!("assertion should fail"),
- Err(e) => e,
+ let Err(e) = s.evaluate_snippet("snip".to_owned(), "std.assertEqual(1, 2)") else {
+ throw!("assertion should fail")
};
let e = s.stringify_err(&e);
ensure!(e.starts_with("runtime error: Assertion failed. 1 != 2"))