Box ShellError in Value::Error (#8375)

# Description

Our `ShellError` at the moment has a `std::mem::size_of<ShellError>` of
136 bytes (on AMD64). As a result `Value` directly storing the struct
also required 136 bytes (thanks to alignment requirements).

This change stores the `Value::Error` `ShellError` on the heap.

Pro:
- Value now needs just 80 bytes
- Should be 1 cacheline less (still at least 2 cachelines)

Con:
- More small heap allocations when dealing with `Value::Error`
  - More heap fragmentation
  - Potential for additional required memcopies

# Further code changes

Includes a small refactor of `try` due to a type mismatch in its large
match.

# User-Facing Changes

None for regular users.

Plugin authors may have to update their matches on `Value` if they use
`nu-protocol`

Needs benchmarking to see if there is a benefit in real world workloads.
**Update** small improvements in runtime for workloads with high volume
of values. Significant reduction in maximum resident set size, when many
values are held in memory.

# Tests + Formatting
This commit is contained in:
Stefan Holderbach 2023-03-12 09:57:27 +01:00 committed by GitHub
parent c26d91fb61
commit a52386e837
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
153 changed files with 648 additions and 520 deletions

View File

@ -145,7 +145,7 @@ pub(crate) fn print_table_or_error(
if let PipelineData::Value(Value::Error { error }, ..) = &pipeline_data { if let PipelineData::Value(Value::Error { error }, ..) = &pipeline_data {
let working_set = StateWorkingSet::new(engine_state); let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, error); report_error(&working_set, &**error);
std::process::exit(1); std::process::exit(1);
} }
@ -193,7 +193,7 @@ fn print_or_exit(pipeline_data: PipelineData, engine_state: &mut EngineState, co
if let Value::Error { error } = item { if let Value::Error { error } = item {
let working_set = StateWorkingSet::new(engine_state); let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &error); report_error(&working_set, &*error);
std::process::exit(1); std::process::exit(1);
} }

View File

@ -53,7 +53,9 @@ impl Command for NuHighlight {
span: head, span: head,
} }
} }
Err(err) => Value::Error { error: err }, Err(err) => Value::Error {
error: Box::new(err),
},
}, },
ctrlc, ctrlc,
) )

View File

@ -1124,7 +1124,7 @@ fn run_hook_block(
eval_block_with_early_return(engine_state, &mut callee_stack, block, input, false, false)?; eval_block_with_early_return(engine_state, &mut callee_stack, block, input, false, false)?;
if let PipelineData::Value(Value::Error { error }, _) = pipeline_data { if let PipelineData::Value(Value::Error { error }, _) = pipeline_data {
return Err(error); return Err(*error);
} }
// If all went fine, preserve the environment of the called block // If all went fine, preserve the environment of the called block

View File

@ -57,66 +57,29 @@ impl Command for Try {
let result = eval_block(engine_state, stack, try_block, input, false, false); let result = eval_block(engine_state, stack, try_block, input, false, false);
match result { match result {
Err(error) | Ok(PipelineData::Value(Value::Error { error }, ..)) => { Err(error) => {
if let nu_protocol::ShellError::Break(_) = error { let error = intercept_block_control(error)?;
return Err(error); let err_value = Value::Error {
} else if let nu_protocol::ShellError::Continue(_) = error { error: Box::new(error),
return Err(error); };
} else if let nu_protocol::ShellError::Return(_, _) = error { handle_catch(err_value, catch_block, engine_state, stack)
return Err(error); }
} Ok(PipelineData::Value(Value::Error { error }, ..)) => {
if let Some(catch_block) = catch_block { let error = intercept_block_control(*error)?;
let catch_block = engine_state.get_block(catch_block.block_id); let err_value = Value::Error {
let err_value = Value::Error { error }; error: Box::new(error),
// Put the error value in the positional closure var };
if let Some(var) = catch_block.signature.get_positional(0) { handle_catch(err_value, catch_block, engine_state, stack)
if let Some(var_id) = &var.var_id {
stack.add_var(*var_id, err_value.clone());
}
}
eval_block(
engine_state,
stack,
catch_block,
// Make the error accessible with $in, too
err_value.into_pipeline_data(),
false,
false,
)
} else {
Ok(PipelineData::empty())
}
} }
// external command may fail to run // external command may fail to run
Ok(pipeline) => { Ok(pipeline) => {
let (pipeline, external_failed) = pipeline.is_external_failed(); let (pipeline, external_failed) = pipeline.is_external_failed();
if external_failed { if external_failed {
if let Some(catch_block) = catch_block { // Because external command errors aren't "real" errors,
let catch_block = engine_state.get_block(catch_block.block_id); // (unless do -c is in effect)
// they can't be passed in as Nushell values.
if let Some(var) = catch_block.signature.get_positional(0) { let err_value = Value::nothing(call.head);
if let Some(var_id) = &var.var_id { handle_catch(err_value, catch_block, engine_state, stack)
// Because external command errors aren't "real" errors,
// (unless do -c is in effect)
// they can't be passed in as Nushell values.
let err_value = Value::nothing(call.head);
stack.add_var(*var_id, err_value);
}
}
eval_block(
engine_state,
stack,
catch_block,
// The same null as in the above block is set as the $in value.
Value::nothing(call.head).into_pipeline_data(),
false,
false,
)
} else {
Ok(PipelineData::empty())
}
} else { } else {
Ok(pipeline) Ok(pipeline)
} }
@ -140,6 +103,48 @@ impl Command for Try {
} }
} }
fn handle_catch(
err_value: Value,
catch_block: Option<Closure>,
engine_state: &EngineState,
stack: &mut Stack,
) -> Result<PipelineData, ShellError> {
if let Some(catch_block) = catch_block {
let catch_block = engine_state.get_block(catch_block.block_id);
// Put the error value in the positional closure var
if let Some(var) = catch_block.signature.get_positional(0) {
if let Some(var_id) = &var.var_id {
stack.add_var(*var_id, err_value.clone());
}
}
eval_block(
engine_state,
stack,
catch_block,
// Make the error accessible with $in, too
err_value.into_pipeline_data(),
false,
false,
)
} else {
Ok(PipelineData::empty())
}
}
/// The flow control commands `break`/`continue`/`return` emit their own [`ShellError`] variants
/// We need to ignore those in `try` and bubble them through
///
/// `Err` when flow control to bubble up with `?`
fn intercept_block_control(error: ShellError) -> Result<ShellError, ShellError> {
match error {
nu_protocol::ShellError::Break(_) => Err(error),
nu_protocol::ShellError::Continue(_) => Err(error),
nu_protocol::ShellError::Return(_, _) => Err(error),
_ => Ok(error),
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;

View File

@ -81,12 +81,12 @@ fn operate(value: Value, target: i64, head: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(), exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -150,12 +150,12 @@ fn operate(value: Value, head: Span, signed: bool, number_size: NumberBytes) ->
// Propagate errors inside the value // Propagate errors inside the value
Value::Error { .. } => other, Value::Error { .. } => other,
_ => Value::Error { _ => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(), exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
}, },
} }

View File

@ -81,12 +81,12 @@ fn operate(value: Value, target: i64, head: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(), exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -103,7 +103,7 @@ where
match rotate_result { match rotate_result {
Ok(val) => Value::Int { val, span }, Ok(val) => Value::Int { val, span },
Err(_) => Value::Error { Err(_) => Value::Error {
error: ShellError::GenericError( error: Box::new(ShellError::GenericError(
"Rotate left result beyond the range of 64 bit signed number".to_string(), "Rotate left result beyond the range of 64 bit signed number".to_string(),
format!( format!(
"{val} of the specified number of bytes rotate left {bits} bits exceed limit" "{val} of the specified number of bytes rotate left {bits} bits exceed limit"
@ -111,7 +111,7 @@ where
Some(span), Some(span),
None, None,
Vec::new(), Vec::new(),
), )),
}, },
} }
} }
@ -137,12 +137,12 @@ fn operate(value: Value, bits: usize, head: Span, signed: bool, number_size: Num
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(), exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -107,7 +107,7 @@ where
match rotate_result { match rotate_result {
Ok(val) => Value::Int { val, span }, Ok(val) => Value::Int { val, span },
Err(_) => Value::Error { Err(_) => Value::Error {
error: ShellError::GenericError( error: Box::new(ShellError::GenericError(
"Rotate right result beyond the range of 64 bit signed number".to_string(), "Rotate right result beyond the range of 64 bit signed number".to_string(),
format!( format!(
"{val} of the specified number of bytes rotate right {bits} bits exceed limit" "{val} of the specified number of bytes rotate right {bits} bits exceed limit"
@ -115,7 +115,7 @@ where
Some(span), Some(span),
None, None,
Vec::new(), Vec::new(),
), )),
}, },
} }
} }
@ -141,12 +141,12 @@ fn operate(value: Value, bits: usize, head: Span, signed: bool, number_size: Num
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(), exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -115,7 +115,7 @@ where
match shift_result { match shift_result {
Ok(val) => Value::Int { val, span }, Ok(val) => Value::Int { val, span },
Err(_) => Value::Error { Err(_) => Value::Error {
error: ShellError::GenericError( error: Box::new(ShellError::GenericError(
"Shift left result beyond the range of 64 bit signed number".to_string(), "Shift left result beyond the range of 64 bit signed number".to_string(),
format!( format!(
"{val} of the specified number of bytes shift left {bits} bits exceed limit" "{val} of the specified number of bytes shift left {bits} bits exceed limit"
@ -123,18 +123,18 @@ where
Some(span), Some(span),
None, None,
Vec::new(), Vec::new(),
), )),
}, },
} }
} }
None => Value::Error { None => Value::Error {
error: ShellError::GenericError( error: Box::new(ShellError::GenericError(
"Shift left failed".to_string(), "Shift left failed".to_string(),
format!("{val} shift left {bits} bits failed, you may shift too many bits"), format!("{val} shift left {bits} bits failed, you may shift too many bits"),
Some(span), Some(span),
None, None,
Vec::new(), Vec::new(),
), )),
}, },
} }
} }
@ -160,12 +160,12 @@ fn operate(value: Value, bits: usize, head: Span, signed: bool, number_size: Num
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(), exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -105,7 +105,7 @@ where
match shift_result { match shift_result {
Ok(val) => Value::Int { val, span }, Ok(val) => Value::Int { val, span },
Err(_) => Value::Error { Err(_) => Value::Error {
error: ShellError::GenericError( error: Box::new(ShellError::GenericError(
"Shift right result beyond the range of 64 bit signed number".to_string(), "Shift right result beyond the range of 64 bit signed number".to_string(),
format!( format!(
"{val} of the specified number of bytes shift right {bits} bits exceed limit" "{val} of the specified number of bytes shift right {bits} bits exceed limit"
@ -113,18 +113,18 @@ where
Some(span), Some(span),
None, None,
Vec::new(), Vec::new(),
), )),
}, },
} }
} }
None => Value::Error { None => Value::Error {
error: ShellError::GenericError( error: Box::new(ShellError::GenericError(
"Shift right failed".to_string(), "Shift right failed".to_string(),
format!("{val} shift right {bits} bits failed, you may shift too many bits"), format!("{val} shift right {bits} bits failed, you may shift too many bits"),
Some(span), Some(span),
None, None,
Vec::new(), Vec::new(),
), )),
}, },
} }
} }
@ -150,12 +150,12 @@ fn operate(value: Value, bits: usize, head: Span, signed: bool, number_size: Num
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(), exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -80,12 +80,12 @@ fn operate(value: Value, target: i64, head: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(), exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -125,12 +125,12 @@ fn add(val: &Value, args: &Arguments, span: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => val.clone(), Value::Error { .. } => val.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(), exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -41,7 +41,7 @@ fn parse_range(range: Value, head: Span) -> Result<(isize, isize, Span), ShellEr
Value::Int { val, .. } => val.to_string(), Value::Int { val, .. } => val.to_string(),
Value::String { val, .. } => val, Value::String { val, .. } => val,
// Explicitly propagate errors instead of dropping them. // Explicitly propagate errors instead of dropping them.
Value::Error { error } => return Err(error), Value::Error { error } => return Err(*error),
other => { other => {
return Err(ShellError::UnsupportedInput( return Err(ShellError::UnsupportedInput(
"Only string or list<int> ranges are supported".into(), "Only string or list<int> ranges are supported".into(),
@ -56,7 +56,7 @@ fn parse_range(range: Value, head: Span) -> Result<(isize, isize, Span), ShellEr
Value::Int { val, .. } => val.to_string(), Value::Int { val, .. } => val.to_string(),
Value::String { val, .. } => val, Value::String { val, .. } => val,
// Explicitly propagate errors instead of dropping them. // Explicitly propagate errors instead of dropping them.
Value::Error { error } => return Err(error), Value::Error { error } => return Err(*error),
other => { other => {
return Err(ShellError::UnsupportedInput( return Err(ShellError::UnsupportedInput(
"Only string or list<int> ranges are supported".into(), "Only string or list<int> ranges are supported".into(),
@ -84,7 +84,7 @@ fn parse_range(range: Value, head: Span) -> Result<(isize, isize, Span), ShellEr
} }
} }
// Explicitly propagate errors instead of dropping them. // Explicitly propagate errors instead of dropping them.
Value::Error { error } => return Err(error), Value::Error { error } => return Err(*error),
other => { other => {
return Err(ShellError::UnsupportedInput( return Err(ShellError::UnsupportedInput(
"could not perform subbytes".to_string(), "could not perform subbytes".to_string(),
@ -249,12 +249,12 @@ fn at(val: &Value, args: &Arguments, span: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => val.clone(), Value::Error { .. } => val.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(), exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }
@ -277,10 +277,10 @@ fn at_impl(input: &[u8], arg: &Arguments, span: Span) -> Value {
match start.cmp(&end) { match start.cmp(&end) {
Ordering::Equal => Value::Binary { val: vec![], span }, Ordering::Equal => Value::Binary { val: vec![], span },
Ordering::Greater => Value::Error { Ordering::Greater => Value::Error {
error: ShellError::TypeMismatch { error: Box::new(ShellError::TypeMismatch {
err_message: "End must be greater than or equal to Start".to_string(), err_message: "End must be greater than or equal to Start".to_string(),
span: arg.arg_span, span: arg.arg_span,
}, }),
}, },
Ordering::Less => Value::Binary { Ordering::Less => Value::Binary {
val: { val: {

View File

@ -53,7 +53,7 @@ impl Command for BytesBuild {
match val { match val {
Value::Binary { mut val, .. } => output.append(&mut val), Value::Binary { mut val, .. } => output.append(&mut val),
// Explicitly propagate errors instead of dropping them. // Explicitly propagate errors instead of dropping them.
Value::Error { error } => return Err(error), Value::Error { error } => return Err(*error),
other => { other => {
return Err(ShellError::TypeMismatch { return Err(ShellError::TypeMismatch {
err_message: "only binary data arguments are supported".to_string(), err_message: "only binary data arguments are supported".to_string(),

View File

@ -55,7 +55,7 @@ impl Command for BytesCollect {
} }
} }
// Explicitly propagate errors instead of dropping them. // Explicitly propagate errors instead of dropping them.
Value::Error { error } => return Err(error), Value::Error { error } => return Err(*error),
other => { other => {
return Err(ShellError::OnlySupportsThisInputType { return Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(), exp_input_type: "binary".into(),

View File

@ -93,12 +93,12 @@ fn ends_with(val: &Value, args: &Arguments, span: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => val.clone(), Value::Error { .. } => val.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(), exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -135,12 +135,12 @@ fn index_of(val: &Value, args: &Arguments, span: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => val.clone(), Value::Error { .. } => val.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(), exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -74,12 +74,12 @@ fn length(val: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => val.clone(), Value::Error { .. } => val.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(), exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -142,12 +142,12 @@ fn remove(val: &Value, args: &Arguments, span: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => val.clone(), Value::Error { .. } => val.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(), exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -133,12 +133,12 @@ fn replace(val: &Value, args: &Arguments, span: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => val.clone(), Value::Error { .. } => val.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(), exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -84,12 +84,12 @@ fn reverse(val: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => val.clone(), Value::Error { .. } => val.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(), exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -80,12 +80,12 @@ impl Command for BytesStartsWith {
// Unsupported data // Unsupported data
Ok(other) => { Ok(other) => {
return Ok(Value::Error { return Ok(Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string and binary".into(), exp_input_type: "string and binary".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
} }
.into_pipeline_data()); .into_pipeline_data());
} }
@ -149,12 +149,12 @@ fn starts_with(val: &Value, args: &Arguments, span: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => val.clone(), Value::Error { .. } => val.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(), exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -79,7 +79,7 @@ impl HashableValue {
Value::Binary { val, span } => Ok(HashableValue::Binary { val, span }), Value::Binary { val, span } => Ok(HashableValue::Binary { val, span }),
// Explicitly propagate errors instead of dropping them. // Explicitly propagate errors instead of dropping them.
Value::Error { error } => Err(error), Value::Error { error } => Err(*error),
_ => Err(ShellError::UnsupportedInput( _ => Err(ShellError::UnsupportedInput(
"input value is not hashable".into(), "input value is not hashable".into(),
format!("input type: {:?}", value.get_type()), format!("input type: {:?}", value.get_type()),
@ -236,7 +236,7 @@ mod test {
}, },
Value::Nothing { span }, Value::Nothing { span },
Value::Error { Value::Error {
error: ShellError::DidYouMean("what?".to_string(), span), error: Box::new(ShellError::DidYouMean("what?".to_string(), span)),
}, },
Value::CellPath { Value::CellPath {
val: CellPath { val: CellPath {

View File

@ -160,7 +160,7 @@ fn run_histogram(
for v in values { for v in values {
match v { match v {
// Propagate existing errors. // Propagate existing errors.
Value::Error { error } => return Err(error), Value::Error { error } => return Err(*error),
_ => { _ => {
let t = v.get_type(); let t = v.get_type();
let span = v.expect_span(); let span = v.expect_span();
@ -198,7 +198,7 @@ fn run_histogram(
} }
} }
// Propagate existing errors. // Propagate existing errors.
Value::Error { error } => return Err(error), Value::Error { error } => return Err(*error),
_ => continue, _ => continue,
} }
} }

View File

@ -193,12 +193,12 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => input.clone(), Value::Error { .. } => input.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "int, filesize, float, string".into(), exp_input_type: "int, filesize, float, string".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -87,12 +87,12 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => input.clone(), Value::Error { .. } => input.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer or filesize".into(), exp_input_type: "integer or filesize".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -188,13 +188,13 @@ pub fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => input.clone(), Value::Error { .. } => input.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer, float, filesize, string, date, duration, binary or bool" exp_input_type: "integer, float, filesize, string, date, duration, binary or bool"
.into(), .into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -161,17 +161,19 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
}, },
Value::String { val, .. } => match string_to_boolean(val, span) { Value::String { val, .. } => match string_to_boolean(val, span) {
Ok(val) => Value::Bool { val, span }, Ok(val) => Value::Bool { val, span },
Err(error) => Value::Error { error }, Err(error) => Value::Error {
error: Box::new(error),
},
}, },
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => input.clone(), Value::Error { .. } => input.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "bool, integer, float or string".into(), exp_input_type: "bool, integer, float or string".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -209,12 +209,12 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
Value::Error { .. } => return input.clone(), Value::Error { .. } => return input.clone(),
other => { other => {
return Value::Error { return Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string and integer".into(), exp_input_type: "string and integer".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}; };
} }
}; };
@ -245,21 +245,21 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
Zone::East(i) => match FixedOffset::east_opt((*i as i32) * HOUR) { Zone::East(i) => match FixedOffset::east_opt((*i as i32) * HOUR) {
Some(eastoffset) => match_datetime!(eastoffset.timestamp_nanos(ts)), Some(eastoffset) => match_datetime!(eastoffset.timestamp_nanos(ts)),
None => Value::Error { None => Value::Error {
error: ShellError::DatetimeParseError(input.debug_value(), *span), error: Box::new(ShellError::DatetimeParseError(input.debug_value(), *span)),
}, },
}, },
Zone::West(i) => match FixedOffset::west_opt((*i as i32) * HOUR) { Zone::West(i) => match FixedOffset::west_opt((*i as i32) * HOUR) {
Some(westoffset) => match_datetime!(westoffset.timestamp_nanos(ts)), Some(westoffset) => match_datetime!(westoffset.timestamp_nanos(ts)),
None => Value::Error { None => Value::Error {
error: ShellError::DatetimeParseError(input.debug_value(), *span), error: Box::new(ShellError::DatetimeParseError(input.debug_value(), *span)),
}, },
}, },
Zone::Error => Value::Error { Zone::Error => Value::Error {
// This is an argument error, not an input error // This is an argument error, not an input error
error: ShellError::TypeMismatch { error: Box::new(ShellError::TypeMismatch {
err_message: "Invalid timezone or offset".to_string(), err_message: "Invalid timezone or offset".to_string(),
span: *span, span: *span,
}, }),
}, },
}, },
}; };
@ -273,7 +273,7 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
Ok(d) => Value::Date { val: d, span: head }, Ok(d) => Value::Date { val: d, span: head },
Err(reason) => { Err(reason) => {
Value::Error { Value::Error {
error: ShellError::CantConvert { to_type: format!("could not parse as datetime using format '{}'", dt.0), from_type: reason.to_string(), span: head, help: Some("you can use `into datetime` without a format string to enable flexible parsing".to_string()) }, error: Box::new(ShellError::CantConvert { to_type: format!("could not parse as datetime using format '{}'", dt.0), from_type: reason.to_string(), span: head, help: Some("you can use `into datetime` without a format string to enable flexible parsing".to_string()) }),
} }
} }
}, },
@ -292,12 +292,12 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => input.clone(), Value::Error { .. } => input.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string".into(), exp_input_type: "string".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }
@ -374,7 +374,7 @@ mod tests {
#[test] #[test]
fn takes_timestamp_offset_as_int() { fn takes_timestamp_offset_as_int() {
let date_int = Value::test_int(1614434140_000000000); let date_int = Value::test_int(1_614_434_140_000_000_000);
let timezone_option = Some(Spanned { let timezone_option = Some(Spanned {
item: Zone::East(8), item: Zone::East(8),
span: Span::test_data(), span: Span::test_data(),

View File

@ -88,12 +88,12 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, head: Span) -> Value {
match other.parse::<f64>() { match other.parse::<f64>() {
Ok(x) => Value::float(x, head), Ok(x) => Value::float(x, head),
Err(reason) => Value::Error { Err(reason) => Value::Error {
error: ShellError::CantConvert { error: Box::new(ShellError::CantConvert {
to_type: "float".to_string(), to_type: "float".to_string(),
from_type: reason.to_string(), from_type: reason.to_string(),
span: *span, span: *span,
help: None, help: None,
}, }),
}, },
} }
} }
@ -108,12 +108,12 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, head: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => input.clone(), Value::Error { .. } => input.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string, integer or bool".into(), exp_input_type: "string, integer or bool".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -174,7 +174,9 @@ fn into_duration(
Box::new(move |old| action(old, &d, float_precision, head)), Box::new(move |old| action(old, &d, float_precision, head)),
); );
if let Err(error) = r { if let Err(error) = r {
return Value::Error { error }; return Value::Error {
error: Box::new(error),
};
} }
} }
@ -430,7 +432,7 @@ fn action(
} }
} }
} }
Err(e) => Value::Error { error: e }, Err(e) => Value::Error { error: Box::new(e) },
} }
} else { } else {
input.clone() input.clone()
@ -464,34 +466,36 @@ fn action(
} }
} }
} }
Err(e) => Value::Error { error: e }, Err(e) => Value::Error { error: Box::new(e) },
} }
} else { } else {
Value::Error { Value::Error {
error: ShellError::CantConvert { error: Box::new(ShellError::CantConvert {
to_type: "string".into(), to_type: "string".into(),
from_type: "duration".into(), from_type: "duration".into(),
span, span,
help: None, help: None,
}, }),
} }
} }
} else { } else {
match string_to_duration(val, span, *value_span) { match string_to_duration(val, span, *value_span) {
Ok(val) => Value::Duration { val, span }, Ok(val) => Value::Duration { val, span },
Err(error) => Value::Error { error }, Err(error) => Value::Error {
error: Box::new(error),
},
} }
} }
} }
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => input.clone(), Value::Error { .. } => input.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string or duration".into(), exp_input_type: "string or duration".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -110,19 +110,21 @@ pub fn action(input: &Value, _args: &CellPathOnlyArgs, span: Span) -> Value {
val, val,
span: value_span, span: value_span,
}, },
Err(error) => Value::Error { error }, Err(error) => Value::Error {
error: Box::new(error),
},
}, },
Value::Nothing { .. } => Value::Filesize { Value::Nothing { .. } => Value::Filesize {
val: 0, val: 0,
span: value_span, span: value_span,
}, },
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string and integer".into(), exp_input_type: "string and integer".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: value_span, src_span: value_span,
}, }),
}, },
} }
} else { } else {

View File

@ -189,12 +189,12 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
Ok(v) => v, Ok(v) => v,
_ => { _ => {
return Value::Error { return Value::Error {
error: ShellError::CantConvert { error: Box::new(ShellError::CantConvert {
to_type: "float".to_string(), to_type: "float".to_string(),
from_type: "integer".to_string(), from_type: "integer".to_string(),
span, span,
help: None, help: None,
}, }),
} }
} }
} }
@ -206,7 +206,9 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
if radix == 10 { if radix == 10 {
match int_from_string(val, span) { match int_from_string(val, span) {
Ok(val) => Value::Int { val, span }, Ok(val) => Value::Int { val, span },
Err(error) => Value::Error { error }, Err(error) => Value::Error {
error: Box::new(error),
},
} }
} else { } else {
convert_int(input, span, radix) convert_int(input, span, radix)
@ -232,10 +234,10 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
.unwrap() .unwrap()
{ {
Value::Error { Value::Error {
error: ShellError::IncorrectValue { error: Box::new(ShellError::IncorrectValue {
msg: "DateTime out of range for timestamp: 1677-09-21T00:12:43Z to 2262-04-11T23:47:16".to_string(), msg: "DateTime out of range for timestamp: 1677-09-21T00:12:43Z to 2262-04-11T23:47:16".to_string(),
span span
}, }),
} }
} else { } else {
Value::Int { Value::Int {
@ -269,13 +271,13 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => input.clone(), Value::Error { .. } => input.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer, float, filesize, date, string, binary, duration or bool" exp_input_type: "integer, float, filesize, date, string, binary, duration or bool"
.into(), .into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }
@ -292,7 +294,7 @@ fn convert_int(input: &Value, head: Span, radix: u32) -> Value {
{ {
match int_from_string(val, head) { match int_from_string(val, head) {
Ok(x) => return Value::int(x, head), Ok(x) => return Value::int(x, head),
Err(e) => return Value::Error { error: e }, Err(e) => return Value::Error { error: Box::new(e) },
} }
} else if val.starts_with("00") { } else if val.starts_with("00") {
// It's a padded string // It's a padded string
@ -300,12 +302,12 @@ fn convert_int(input: &Value, head: Span, radix: u32) -> Value {
Ok(n) => return Value::int(n, head), Ok(n) => return Value::int(n, head),
Err(e) => { Err(e) => {
return Value::Error { return Value::Error {
error: ShellError::CantConvert { error: Box::new(ShellError::CantConvert {
to_type: "string".to_string(), to_type: "string".to_string(),
from_type: "int".to_string(), from_type: "int".to_string(),
span: head, span: head,
help: Some(e.to_string()), help: Some(e.to_string()),
}, }),
} }
} }
} }
@ -316,24 +318,24 @@ fn convert_int(input: &Value, head: Span, radix: u32) -> Value {
Value::Error { .. } => return input.clone(), Value::Error { .. } => return input.clone(),
other => { other => {
return Value::Error { return Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string and integer".into(), exp_input_type: "string and integer".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}; };
} }
}; };
match i64::from_str_radix(i.trim(), radix) { match i64::from_str_radix(i.trim(), radix) {
Ok(n) => Value::int(n, head), Ok(n) => Value::int(n, head),
Err(_reason) => Value::Error { Err(_reason) => Value::Error {
error: ShellError::CantConvert { error: Box::new(ShellError::CantConvert {
to_type: "string".to_string(), to_type: "string".to_string(),
from_type: "int".to_string(), from_type: "int".to_string(),
span: head, span: head,
help: None, help: None,
}, }),
}, },
} }
} }
@ -483,9 +485,9 @@ mod test {
} }
#[rstest] #[rstest]
#[case("2262-04-11T23:47:16+00:00", 0x7fffffff_ffffffff)] #[case("2262-04-11T23:47:16+00:00", 0x7fff_ffff_ffff_ffff)]
#[case("1970-01-01T00:00:00+00:00", 0)] #[case("1970-01-01T00:00:00+00:00", 0)]
#[case("1677-09-21T00:12:44+00:00", -0x7fffffff_ffffffff)] #[case("1677-09-21T00:12:44+00:00", -0x7fff_ffff_ffff_ffff)]
fn datetime_to_int_values_that_work( fn datetime_to_int_values_that_work(
#[case] dt_in: DateTime<FixedOffset>, #[case] dt_in: DateTime<FixedOffset>,
#[case] int_expected: i64, #[case] int_expected: i64,
@ -522,14 +524,15 @@ mod test {
}, },
Span::test_data(), Span::test_data(),
); );
if let Value::Error { if let Value::Error { error } = actual {
error: ShellError::IncorrectValue { msg: e, .. }, if let ShellError::IncorrectValue { msg: e, .. } = *error {
} = actual assert!(
{ e.contains(err_expected),
assert!( "{e:?} doesn't contain {err_expected}"
e.contains(err_expected), );
"{e:?} doesn't contain {err_expected}" } else {
); panic!("Unexpected error variant {error:?}")
}
} else { } else {
panic!("Unexpected actual value {actual:?}") panic!("Unexpected actual value {actual:?}")
} }

View File

@ -185,12 +185,12 @@ fn into_record(
Value::Record { cols, vals, span } => Value::Record { cols, vals, span }, Value::Record { cols, vals, span } => Value::Record { cols, vals, span },
Value::Error { .. } => input, Value::Error { .. } => input,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string".into(), exp_input_type: "string".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: call.head, dst_span: call.head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
}; };
Ok(res.into_pipeline_data()) Ok(res.into_pipeline_data())

View File

@ -247,28 +247,28 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
span: _, span: _,
} => Value::Error { } => Value::Error {
// Watch out for CantConvert's argument order // Watch out for CantConvert's argument order
error: ShellError::CantConvert { error: Box::new(ShellError::CantConvert {
to_type: "string".into(), to_type: "string".into(),
from_type: "record".into(), from_type: "record".into(),
span, span,
help: Some("try using the `to nuon` command".into()), help: Some("try using the `to nuon` command".into()),
}, }),
}, },
Value::Binary { .. } => Value::Error { Value::Binary { .. } => Value::Error {
error: ShellError::CantConvert { error: Box::new(ShellError::CantConvert {
to_type: "string".into(), to_type: "string".into(),
from_type: "binary".into(), from_type: "binary".into(),
span, span,
help: Some("try using the `decode` command".into()), help: Some("try using the `decode` command".into()),
}, }),
}, },
x => Value::Error { x => Value::Error {
error: ShellError::CantConvert { error: Box::new(ShellError::CantConvert {
to_type: String::from("string"), to_type: String::from("string"),
from_type: x.get_type().to_string(), from_type: x.get_type().to_string(),
span, span,
help: None, help: None,
}, }),
}, },
} }
} }

View File

@ -217,7 +217,7 @@ fn action(
Ok(Value::Nothing { span: *span }) Ok(Value::Nothing { span: *span })
} }
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { error } => Err(error.clone()), Value::Error { error } => Err(*error.clone()),
other => Err(ShellError::OnlySupportsThisInputType { other => Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "list".into(), exp_input_type: "list".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),

View File

@ -463,7 +463,7 @@ pub fn convert_sqlite_value_to_nu_value(value: ValueRef, span: Span) -> Value {
Ok(v) => v, Ok(v) => v,
Err(_) => { Err(_) => {
return Value::Error { return Value::Error {
error: ShellError::NonUtf8(span), error: Box::new(ShellError::NonUtf8(span)),
} }
} }
}; };

View File

@ -461,13 +461,13 @@ pub fn create_column(
Some(val) => val, Some(val) => val,
None => { None => {
return Value::Error { return Value::Error {
error: ShellError::UnsupportedInput( error: Box::new(ShellError::UnsupportedInput(
"The given local datetime representation is invalid." "The given local datetime representation is invalid."
.to_string(), .to_string(),
format!("timestamp is {a:?}"), format!("timestamp is {a:?}"),
span, span,
Span::unknown(), Span::unknown(),
), )),
} }
} }
}; };
@ -476,13 +476,13 @@ pub fn create_column(
Some(val) => val, Some(val) => val,
None => { None => {
return Value::Error { return Value::Error {
error: ShellError::UnsupportedInput( error: Box::new(ShellError::UnsupportedInput(
"The given local datetime representation is invalid." "The given local datetime representation is invalid."
.to_string(), .to_string(),
format!("timestamp is {a:?}"), format!("timestamp is {a:?}"),
span, span,
Span::unknown(), Span::unknown(),
), )),
} }
} }
}; };
@ -526,13 +526,13 @@ pub fn create_column(
Some(val) => val, Some(val) => val,
None => { None => {
return Value::Error { return Value::Error {
error: ShellError::UnsupportedInput( error: Box::new(ShellError::UnsupportedInput(
"The given local datetime representation is invalid." "The given local datetime representation is invalid."
.to_string(), .to_string(),
format!("timestamp is {a:?}"), format!("timestamp is {a:?}"),
span, span,
Span::unknown(), Span::unknown(),
), )),
} }
} }
}; };
@ -541,13 +541,13 @@ pub fn create_column(
Some(val) => val, Some(val) => val,
None => { None => {
return Value::Error { return Value::Error {
error: ShellError::UnsupportedInput( error: Box::new(ShellError::UnsupportedInput(
"The given local datetime representation is invalid." "The given local datetime representation is invalid."
.to_string(), .to_string(),
format!("timestamp is {a:?}"), format!("timestamp is {a:?}"),
span, span,
Span::unknown(), Span::unknown(),
), )),
} }
} }
}; };

View File

@ -132,10 +132,10 @@ where
span, span,
}, },
Err(_) => Value::Error { Err(_) => Value::Error {
error: ShellError::TypeMismatch { error: Box::new(ShellError::TypeMismatch {
err_message: "invalid format".to_string(), err_message: "invalid format".to_string(),
span, span,
}, }),
}, },
} }
} }
@ -152,7 +152,10 @@ fn format_helper(value: Value, formatter: &str, formatter_span: Span, head_span:
} }
} }
_ => Value::Error { _ => Value::Error {
error: ShellError::DatetimeParseError(value.debug_value(), head_span), error: Box::new(ShellError::DatetimeParseError(
value.debug_value(),
head_span,
)),
}, },
} }
} }
@ -177,7 +180,7 @@ fn format_helper_rfc2822(value: Value, span: Span) -> Value {
} }
} }
_ => Value::Error { _ => Value::Error {
error: ShellError::DatetimeParseError(value.debug_value(), span), error: Box::new(ShellError::DatetimeParseError(value.debug_value(), span)),
}, },
} }
} }

View File

@ -90,7 +90,7 @@ fn helper(value: Value, head: Span) -> Value {
span: head, span: head,
}, },
_ => Value::Error { _ => Value::Error {
error: ShellError::DatetimeParseError(value.debug_value(), head), error: Box::new(ShellError::DatetimeParseError(value.debug_value(), head)),
}, },
} }
} }

View File

@ -156,7 +156,7 @@ fn helper(val: Value, head: Span) -> Value {
} }
Value::Date { val, span: _ } => parse_date_into_table(Ok(val), head), Value::Date { val, span: _ } => parse_date_into_table(Ok(val), head),
_ => Value::Error { _ => Value::Error {
error: DatetimeParseError(val.debug_value(), head), error: Box::new(DatetimeParseError(val.debug_value(), head)),
}, },
} }
} }

View File

@ -161,7 +161,7 @@ fn helper(val: Value, head: Span) -> Value {
} }
Value::Date { val, span: _ } => parse_date_into_table(Ok(val), head), Value::Date { val, span: _ } => parse_date_into_table(Ok(val), head),
_ => Value::Error { _ => Value::Error {
error: DatetimeParseError(val.debug_value(), head), error: Box::new(DatetimeParseError(val.debug_value(), head)),
}, },
} }
} }

View File

@ -128,7 +128,7 @@ fn helper(value: Value, head: Span, timezone: &Spanned<String>) -> Value {
_to_timezone(dt.with_timezone(dt.offset()), timezone, head) _to_timezone(dt.with_timezone(dt.offset()), timezone, head)
} }
_ => Value::Error { _ => Value::Error {
error: ShellError::DatetimeParseError(value.debug_value(), head), error: Box::new(ShellError::DatetimeParseError(value.debug_value(), head)),
}, },
} }
} }
@ -137,10 +137,10 @@ fn _to_timezone(dt: DateTime<FixedOffset>, timezone: &Spanned<String>, span: Spa
match datetime_in_timezone(&dt, timezone.item.as_str()) { match datetime_in_timezone(&dt, timezone.item.as_str()) {
Ok(dt) => Value::Date { val: dt, span }, Ok(dt) => Value::Date { val: dt, span },
Err(_) => Value::Error { Err(_) => Value::Error {
error: ShellError::TypeMismatch { error: Box::new(ShellError::TypeMismatch {
err_message: String::from("invalid time zone"), err_message: String::from("invalid time zone"),
span: timezone.span, span: timezone.span,
}, }),
}, },
} }
} }

View File

@ -15,12 +15,12 @@ pub(crate) fn parse_date_from_string(
LocalResult::Single(d) => Ok(d), LocalResult::Single(d) => Ok(d),
LocalResult::Ambiguous(d, _) => Ok(d), LocalResult::Ambiguous(d, _) => Ok(d),
LocalResult::None => Err(Value::Error { LocalResult::None => Err(Value::Error {
error: ShellError::DatetimeParseError(input.to_string(), span), error: Box::new(ShellError::DatetimeParseError(input.to_string(), span)),
}), }),
} }
} }
Err(_) => Err(Value::Error { Err(_) => Err(Value::Error {
error: ShellError::DatetimeParseError(input.to_string(), span), error: Box::new(ShellError::DatetimeParseError(input.to_string(), span)),
}), }),
} }
} }

View File

@ -279,7 +279,9 @@ fn get_expression_as_value(
) -> Value { ) -> Value {
match eval_expression(engine_state, stack, inner_expr) { match eval_expression(engine_state, stack, inner_expr) {
Ok(v) => v, Ok(v) => v,
Err(error) => Value::Error { error }, Err(error) => Value::Error {
error: Box::new(error),
},
} }
} }

View File

@ -379,13 +379,13 @@ fn interactive_copy(
); );
if let Err(e) = interaction { if let Err(e) = interaction {
Value::Error { Value::Error {
error: ShellError::GenericError( error: Box::new(ShellError::GenericError(
e.to_string(), e.to_string(),
e.to_string(), e.to_string(),
Some(span), Some(span),
None, None,
Vec::new(), Vec::new(),
), )),
} }
} else if !confirmed { } else if !confirmed {
let msg = format!("{:} not copied to {:}", src.display(), dst.display()); let msg = format!("{:} not copied to {:}", src.display(), dst.display());
@ -518,13 +518,13 @@ fn copy_symlink(
Ok(p) => p, Ok(p) => p,
Err(err) => { Err(err) => {
return Value::Error { return Value::Error {
error: ShellError::GenericError( error: Box::new(ShellError::GenericError(
err.to_string(), err.to_string(),
err.to_string(), err.to_string(),
Some(span), Some(span),
None, None,
vec![], vec![],
), )),
} }
} }
}; };
@ -551,7 +551,13 @@ fn copy_symlink(
Value::String { val: msg, span } Value::String { val: msg, span }
} }
Err(e) => Value::Error { Err(e) => Value::Error {
error: ShellError::GenericError(e.to_string(), e.to_string(), Some(span), None, vec![]), error: Box::new(ShellError::GenericError(
e.to_string(),
e.to_string(),
Some(span),
None,
vec![],
)),
}, },
} }
} }
@ -593,5 +599,7 @@ fn convert_io_error(error: std::io::Error, src: PathBuf, dst: PathBuf, span: Spa
_ => ShellError::IOErrorSpanned(message_src, span), _ => ShellError::IOErrorSpanned(message_src, span),
}; };
Value::Error { error: shell_error } Value::Error {
error: Box::new(shell_error),
}
} }

View File

@ -255,10 +255,14 @@ impl Command for Ls {
); );
match entry { match entry {
Ok(value) => Some(value), Ok(value) => Some(value),
Err(err) => Some(Value::Error { error: err }), Err(err) => Some(Value::Error {
error: Box::new(err),
}),
} }
} }
Err(err) => Some(Value::Error { error: err }), Err(err) => Some(Value::Error {
error: Box::new(err),
}),
} }
} }
_ => Some(Value::Nothing { span: call_span }), _ => Some(Value::Nothing { span: call_span }),

View File

@ -193,7 +193,9 @@ impl Command for Mv {
interactive, interactive,
); );
if let Err(error) = result { if let Err(error) = result {
Some(Value::Error { error }) Some(Value::Error {
error: Box::new(error),
})
} else if verbose { } else if verbose {
let val = match result { let val = match result {
Ok(true) => format!( Ok(true) => format!(

View File

@ -405,13 +405,13 @@ fn rm(
if let Err(e) = result { if let Err(e) = result {
let msg = format!("Could not delete because: {e:}"); let msg = format!("Could not delete because: {e:}");
Value::Error { Value::Error {
error: ShellError::GenericError( error: Box::new(ShellError::GenericError(
msg, msg,
e.to_string(), e.to_string(),
Some(span), Some(span),
None, None,
Vec::new(), Vec::new(),
), )),
} }
} else if verbose { } else if verbose {
let msg = if interactive && !confirmed { let msg = if interactive && !confirmed {
@ -427,25 +427,25 @@ fn rm(
} else { } else {
let msg = format!("Cannot remove {:}. try --recursive", f.to_string_lossy()); let msg = format!("Cannot remove {:}. try --recursive", f.to_string_lossy());
Value::Error { Value::Error {
error: ShellError::GenericError( error: Box::new(ShellError::GenericError(
msg, msg,
"cannot remove non-empty directory".into(), "cannot remove non-empty directory".into(),
Some(span), Some(span),
None, None,
Vec::new(), Vec::new(),
), )),
} }
} }
} else { } else {
let msg = format!("no such file or directory: {:}", f.to_string_lossy()); let msg = format!("no such file or directory: {:}", f.to_string_lossy());
Value::Error { Value::Error {
error: ShellError::GenericError( error: Box::new(ShellError::GenericError(
msg, msg,
"no such file or directory".into(), "no such file or directory".into(),
Some(span), Some(span),
None, None,
Vec::new(), Vec::new(),
), )),
} }
} }
}) })

View File

@ -250,7 +250,7 @@ fn value_to_bytes(value: Value) -> Result<Vec<u8>, ShellError> {
Ok(val.into_bytes()) Ok(val.into_bytes())
} }
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { error } => Err(error), Value::Error { error } => Err(*error),
other => Ok(other.as_string()?.into_bytes()), other => Ok(other.as_string()?.into_bytes()),
} }
} }
@ -376,7 +376,7 @@ fn stream_to_file(
Value::String { val, .. } => val.into_bytes(), Value::String { val, .. } => val.into_bytes(),
Value::Binary { val, .. } => val, Value::Binary { val, .. } => val,
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { error } => return Err(error), Value::Error { error } => return Err(*error),
other => { other => {
return Err(ShellError::OnlySupportsThisInputType { return Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "string or binary".into(), exp_input_type: "string or binary".into(),

View File

@ -137,7 +137,7 @@ fn getcol(
.into_pipeline_data(ctrlc) .into_pipeline_data(ctrlc)
.set_metadata(metadata)), .set_metadata(metadata)),
// Propagate errors // Propagate errors
PipelineData::Value(Value::Error { error }, ..) => Err(error), PipelineData::Value(Value::Error { error }, ..) => Err(*error),
PipelineData::Value(other, ..) => Err(ShellError::OnlySupportsThisInputType { PipelineData::Value(other, ..) => Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "record or table".into(), exp_input_type: "record or table".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),

View File

@ -167,7 +167,9 @@ with 'transpose' first."#
Err(ShellError::Break(_)) => None, Err(ShellError::Break(_)) => None,
Err(error) => { Err(error) => {
let error = chain_error_with_input(error, input_span); let error = chain_error_with_input(error, input_span);
Some(Value::Error { error }) Some(Value::Error {
error: Box::new(error),
})
} }
} }
}) })
@ -187,7 +189,11 @@ with 'transpose' first."#
let x = match x { let x = match x {
Ok(x) => x, Ok(x) => x,
Err(ShellError::Break(_)) => return None, Err(ShellError::Break(_)) => return None,
Err(err) => return Some(Value::Error { error: err }), Err(err) => {
return Some(Value::Error {
error: Box::new(err),
})
}
}; };
if let Some(var) = block.signature.get_positional(0) { if let Some(var) = block.signature.get_positional(0) {
@ -208,7 +214,7 @@ with 'transpose' first."#
Ok(v) => Some(v.into_value(span)), Ok(v) => Some(v.into_value(span)),
Err(ShellError::Break(_)) => None, Err(ShellError::Break(_)) => None,
Err(error) => { Err(error) => {
let error = chain_error_with_input(error, input_span); let error = Box::new(chain_error_with_input(error, input_span));
Some(Value::Error { error }) Some(Value::Error { error })
} }
} }

View File

@ -101,7 +101,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
} }
} }
Err(error) => Some(Value::Error { Err(error) => Some(Value::Error {
error: chain_error_with_input(error, x.span()), error: Box::new(chain_error_with_input(error, x.span())),
}), }),
} }
}) })
@ -118,7 +118,11 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
let x = match x { let x = match x {
Ok(x) => x, Ok(x) => x,
Err(err) => return Some(Value::Error { error: err }), Err(err) => {
return Some(Value::Error {
error: Box::new(err),
})
}
}; };
if let Some(var) = block.signature.get_positional(0) { if let Some(var) = block.signature.get_positional(0) {
@ -144,7 +148,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
} }
} }
Err(error) => Some(Value::Error { Err(error) => Some(Value::Error {
error: chain_error_with_input(error, x.span()), error: Box::new(chain_error_with_input(error, x.span())),
}), }),
} }
}) })
@ -177,7 +181,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
} }
} }
Err(error) => Some(Value::Error { Err(error) => Some(Value::Error {
error: chain_error_with_input(error, x.span()), error: Box::new(chain_error_with_input(error, x.span())),
}), }),
} }
.into_pipeline_data(ctrlc)) .into_pipeline_data(ctrlc))

View File

@ -522,7 +522,7 @@ fn find_with_rest_and_highlight(
} }
} }
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { error } => return Err(error), Value::Error { error } => return Err(*error),
other => { other => {
return Err(ShellError::UnsupportedInput( return Err(ShellError::UnsupportedInput(
"unsupported type from raw stream".into(), "unsupported type from raw stream".into(),

View File

@ -141,7 +141,7 @@ fn first_helper(
} }
} }
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { error } => Err(error), Value::Error { error } => Err(*error),
other => Err(ShellError::OnlySupportsThisInputType { other => Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "list, binary or range".into(), exp_input_type: "list, binary or range".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),

View File

@ -154,7 +154,7 @@ enum TableInside<'a> {
fn flat_value(columns: &[CellPath], item: &Value, _name_tag: Span, all: bool) -> Vec<Value> { fn flat_value(columns: &[CellPath], item: &Value, _name_tag: Span, all: bool) -> Vec<Value> {
let tag = match item.span() { let tag = match item.span() {
Ok(x) => x, Ok(x) => x,
Err(e) => return vec![Value::Error { error: e }], Err(e) => return vec![Value::Error { error: Box::new(e) }],
}; };
let res = { let res = {
@ -172,19 +172,19 @@ fn flat_value(columns: &[CellPath], item: &Value, _name_tag: Span, all: bool) ->
Value::Error { .. } => return vec![item.clone()], Value::Error { .. } => return vec![item.clone()],
other => { other => {
return vec![Value::Error { return vec![Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "record".into(), exp_input_type: "record".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: _name_tag, dst_span: _name_tag,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}]; }];
} }
}; };
let s = match item.span() { let s = match item.span() {
Ok(x) => x, Ok(x) => x,
Err(e) => return vec![Value::Error { error: e }], Err(e) => return vec![Value::Error { error: Box::new(e) }],
}; };
let records_iterator = { let records_iterator = {
@ -229,12 +229,12 @@ fn flat_value(columns: &[CellPath], item: &Value, _name_tag: Span, all: bool) ->
if all && vals.iter().all(|f| f.as_record().is_ok()) => if all && vals.iter().all(|f| f.as_record().is_ok()) =>
{ {
if need_flatten && inner_table.is_some() { if need_flatten && inner_table.is_some() {
return vec![Value::Error{ error: ShellError::UnsupportedInput( return vec![Value::Error{ error: Box::new(ShellError::UnsupportedInput(
"can only flatten one inner list at a time. tried flattening more than one column with inner lists... but is flattened already".to_string(), "can only flatten one inner list at a time. tried flattening more than one column with inner lists... but is flattened already".to_string(),
"value originates from here".into(), "value originates from here".into(),
s, s,
*span *span
)} ))}
]; ];
} }
// it's a table (a list of record, we can flatten inner record) // it's a table (a list of record, we can flatten inner record)
@ -267,12 +267,12 @@ fn flat_value(columns: &[CellPath], item: &Value, _name_tag: Span, all: bool) ->
} }
Value::List { vals: values, span } => { Value::List { vals: values, span } => {
if need_flatten && inner_table.is_some() { if need_flatten && inner_table.is_some() {
return vec![Value::Error{ error: ShellError::UnsupportedInput( return vec![Value::Error{ error: Box::new(ShellError::UnsupportedInput(
"can only flatten one inner list at a time. tried flattening more than one column with inner lists... but is flattened already".to_string(), "can only flatten one inner list at a time. tried flattening more than one column with inner lists... but is flattened already".to_string(),
"value originates from here".into(), "value originates from here".into(),
s, s,
*span *span
)} ))}
]; ];
} }

View File

@ -244,7 +244,7 @@ pub fn group(
Grouper::ByColumn(Some(column_name)) => { Grouper::ByColumn(Some(column_name)) => {
let block = Box::new(move |_, row: &Value| { let block = Box::new(move |_, row: &Value| {
if let Value::Error { error } = row { if let Value::Error { error } = row {
return Err(error.clone()); return Err(*error.clone());
}; };
match row.get_data_by_key(&column_name.item) { match row.get_data_by_key(&column_name.item) {
Some(group_key) => Ok(group_key.as_string()?), Some(group_key) => Ok(group_key.as_string()?),

View File

@ -163,12 +163,12 @@ fn insert(
pd.into_value(span), pd.into_value(span),
span, span,
) { ) {
return Value::Error { error: e }; return Value::Error { error: Box::new(e) };
} }
input input
} }
Err(e) => Value::Error { error: e }, Err(e) => Value::Error { error: Box::new(e) },
} }
}, },
ctrlc, ctrlc,
@ -199,7 +199,7 @@ fn insert(
if let Err(e) = if let Err(e) =
input.insert_data_at_cell_path(&cell_path.members, replacement, span) input.insert_data_at_cell_path(&cell_path.members, replacement, span)
{ {
return Value::Error { error: e }; return Value::Error { error: Box::new(e) };
} }
input input

View File

@ -86,7 +86,7 @@ fn length_row(call: &Call, input: PipelineData) -> Result<PipelineData, ShellErr
// Check for and propagate errors // Check for and propagate errors
for value in input.into_iter() { for value in input.into_iter() {
if let Value::Error { error } = value { if let Value::Error { error } = value {
return Err(error); return Err(*error);
} }
count += 1 count += 1
} }

View File

@ -112,7 +112,7 @@ impl Command for Lines {
PipelineData::Value(val, ..) => { PipelineData::Value(val, ..) => {
match val { match val {
// Propagate existing errors // Propagate existing errors
Value::Error { error } => Err(error), Value::Error { error } => Err(*error),
_ => Err(ShellError::OnlySupportsThisInputType { _ => Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "string or raw data".into(), exp_input_type: "string or raw data".into(),
wrong_type: val.get_type().to_string(), wrong_type: val.get_type().to_string(),
@ -129,7 +129,9 @@ impl Command for Lines {
.enumerate() .enumerate()
.map(move |(_idx, x)| match x { .map(move |(_idx, x)| match x {
Ok(x) => x, Ok(x) => x,
Err(err) => Value::Error { error: err }, Err(err) => Value::Error {
error: Box::new(err),
},
}) })
.into_pipeline_data(ctrlc)), .into_pipeline_data(ctrlc)),
} }
@ -232,7 +234,7 @@ impl Iterator for RawStreamLinesAdapter {
self.queue.append(&mut lines); self.queue.append(&mut lines);
} }
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { error } => return Some(Err(error)), Value::Error { error } => return Some(Err(*error)),
other => { other => {
return Some(Err(ShellError::OnlySupportsThisInputType { return Some(Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "string".into(), exp_input_type: "string".into(),

View File

@ -125,11 +125,15 @@ repeating this process with row 1, and so on."#
span: call.head, span: call.head,
} }
} }
Err(error) => Value::Error { error }, Err(error) => Value::Error {
error: Box::new(error),
},
} }
} }
(_, None) => inp, (_, None) => inp,
(Err(error), _) => Value::Error { error }, (Err(error), _) => Value::Error {
error: Box::new(error),
},
}); });
if let Some(md) = metadata { if let Some(md) = metadata {

View File

@ -158,9 +158,13 @@ impl Command for Move {
call.head, call.head,
) { ) {
Ok(val) => val, Ok(val) => val,
Err(error) => Value::Error { error }, Err(error) => Value::Error {
error: Box::new(error),
},
},
Err(error) => Value::Error {
error: Box::new(error),
}, },
Err(error) => Value::Error { error },
}); });
if let Some(md) = metadata { if let Some(md) = metadata {

View File

@ -121,7 +121,7 @@ impl Command for ParEach {
) { ) {
Ok(v) => v, Ok(v) => v,
Err(error) => Value::Error { Err(error) => Value::Error {
error: chain_error_with_input(error, val_span), error: Box::new(chain_error_with_input(error, val_span)),
} }
.into_pipeline_data(), .into_pipeline_data(),
} }
@ -155,7 +155,7 @@ impl Command for ParEach {
) { ) {
Ok(v) => v, Ok(v) => v,
Err(error) => Value::Error { Err(error) => Value::Error {
error: chain_error_with_input(error, val_span), error: Box::new(chain_error_with_input(error, val_span)),
} }
.into_pipeline_data(), .into_pipeline_data(),
} }
@ -188,7 +188,7 @@ impl Command for ParEach {
) { ) {
Ok(v) => v, Ok(v) => v,
Err(error) => Value::Error { Err(error) => Value::Error {
error: chain_error_with_input(error, val_span), error: Box::new(chain_error_with_input(error, val_span)),
} }
.into_pipeline_data(), .into_pipeline_data(),
} }
@ -206,7 +206,12 @@ impl Command for ParEach {
.map(move |x| { .map(move |x| {
let x = match x { let x = match x {
Ok(x) => x, Ok(x) => x,
Err(err) => return Value::Error { error: err }.into_pipeline_data(), Err(err) => {
return Value::Error {
error: Box::new(err),
}
.into_pipeline_data()
}
}; };
let block = engine_state.get_block(block_id); let block = engine_state.get_block(block_id);
@ -228,7 +233,10 @@ impl Command for ParEach {
redirect_stderr, redirect_stderr,
) { ) {
Ok(v) => v, Ok(v) => v,
Err(error) => Value::Error { error }.into_pipeline_data(), Err(error) => Value::Error {
error: Box::new(error),
}
.into_pipeline_data(),
} }
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()

View File

@ -141,7 +141,7 @@ fn rename(
// check if the specified column to be renamed exists // check if the specified column to be renamed exists
if !cols.contains(&c[0]) { if !cols.contains(&c[0]) {
return Value::Error { return Value::Error {
error: ShellError::UnsupportedInput( error: Box::new(ShellError::UnsupportedInput(
format!( format!(
"The column '{}' does not exist in the input", "The column '{}' does not exist in the input",
&c[0] &c[0]
@ -151,7 +151,7 @@ fn rename(
specified_col_span.unwrap_or(head_span), specified_col_span.unwrap_or(head_span),
// Arrow 2 points at the input value. // Arrow 2 points at the input value.
span, span,
), )),
}; };
} }
for (idx, val) in cols.iter_mut().enumerate() { for (idx, val) in cols.iter_mut().enumerate() {
@ -177,12 +177,12 @@ fn rename(
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { .. } => item.clone(), Value::Error { .. } => item.clone(),
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "record".into(), exp_input_type: "record".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head_span, dst_span: head_span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
}, },
engine_state.ctrlc.clone(), engine_state.ctrlc.clone(),

View File

@ -73,7 +73,7 @@ impl Command for Take {
.into_pipeline_data(ctrlc) .into_pipeline_data(ctrlc)
.set_metadata(metadata)), .set_metadata(metadata)),
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { error } => Err(error), Value::Error { error } => Err(*error),
other => Err(ShellError::OnlySupportsThisInputType { other => Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "list, binary or range".into(), exp_input_type: "list, binary or range".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),

View File

@ -132,12 +132,12 @@ fn update(
if let Err(e) = if let Err(e) =
input.update_data_at_cell_path(&cell_path.members, pd.into_value(span)) input.update_data_at_cell_path(&cell_path.members, pd.into_value(span))
{ {
return Value::Error { error: e }; return Value::Error { error: Box::new(e) };
} }
input input
} }
Err(e) => Value::Error { error: e }, Err(e) => Value::Error { error: Box::new(e) },
} }
}, },
ctrlc, ctrlc,
@ -174,7 +174,7 @@ fn update(
let replacement = replacement.clone(); let replacement = replacement.clone();
if let Err(e) = input.update_data_at_cell_path(&cell_path.members, replacement) { if let Err(e) = input.update_data_at_cell_path(&cell_path.members, replacement) {
return Value::Error { error: e }; return Value::Error { error: Box::new(e) };
} }
input input

View File

@ -253,7 +253,7 @@ fn process_cell(
redirect_stderr, redirect_stderr,
) { ) {
Ok(pd) => pd.into_value(span), Ok(pd) => pd.into_value(span),
Err(e) => Value::Error { error: e }, Err(e) => Value::Error { error: Box::new(e) },
} }
} }

View File

@ -154,12 +154,12 @@ fn upsert(
if let Err(e) = if let Err(e) =
input.upsert_data_at_cell_path(&cell_path.members, pd.into_value(span)) input.upsert_data_at_cell_path(&cell_path.members, pd.into_value(span))
{ {
return Value::Error { error: e }; return Value::Error { error: Box::new(e) };
} }
input input
} }
Err(e) => Value::Error { error: e }, Err(e) => Value::Error { error: Box::new(e) },
} }
}, },
ctrlc, ctrlc,
@ -195,7 +195,7 @@ fn upsert(
let replacement = replacement.clone(); let replacement = replacement.clone();
if let Err(e) = input.upsert_data_at_cell_path(&cell_path.members, replacement) { if let Err(e) = input.upsert_data_at_cell_path(&cell_path.members, replacement) {
return Value::Error { error: e }; return Value::Error { error: Box::new(e) };
} }
input input

View File

@ -119,7 +119,7 @@ pub fn get_values<'a>(
} }
} }
} }
Value::Error { error } => return Err(error.clone()), Value::Error { error } => return Err(*error.clone()),
_ => { _ => {
return Err(ShellError::OnlySupportsThisInputType { return Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "record or table".into(), exp_input_type: "record or table".into(),
@ -176,7 +176,7 @@ fn values(
Ok(vals.into_pipeline_data(ctrlc).set_metadata(metadata)) Ok(vals.into_pipeline_data(ctrlc).set_metadata(metadata))
} }
// Propagate errors // Propagate errors
PipelineData::Value(Value::Error { error }, ..) => Err(error), PipelineData::Value(Value::Error { error }, ..) => Err(*error),
PipelineData::Value(other, ..) => Err(ShellError::OnlySupportsThisInputType { PipelineData::Value(other, ..) => Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "record or table".into(), exp_input_type: "record or table".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),

View File

@ -97,7 +97,9 @@ not supported."#
None None
} }
} }
Err(err) => Some(Value::Error { error: err }), Err(err) => Some(Value::Error {
error: Box::new(err),
}),
} }
}) })
.into_pipeline_data(ctrlc) .into_pipeline_data(ctrlc)

View File

@ -77,7 +77,9 @@ impl Command for FromJson {
} else { } else {
match convert_string_to_value(x.to_string(), span) { match convert_string_to_value(x.to_string(), span) {
Ok(v) => Some(v), Ok(v) => Some(v),
Err(error) => Some(Value::Error { error }), Err(error) => Some(Value::Error {
error: Box::new(error),
}),
} }
} }
}) })
@ -119,12 +121,12 @@ fn convert_nujson_to_value(value: &nu_json::Value, span: Span) -> Value {
nu_json::Value::U64(u) => { nu_json::Value::U64(u) => {
if *u > i64::MAX as u64 { if *u > i64::MAX as u64 {
Value::Error { Value::Error {
error: ShellError::CantConvert { error: Box::new(ShellError::CantConvert {
to_type: "i64 sized integer".into(), to_type: "i64 sized integer".into(),
from_type: "value larger than i64".into(), from_type: "value larger than i64".into(),
span, span,
help: None, help: None,
}, }),
} }
} else { } else {
Value::Int { Value::Int {

View File

@ -93,7 +93,7 @@ fn collect_binary(input: PipelineData, span: Span) -> Result<Vec<u8>, ShellError
Some(Value::Binary { val: b, .. }) => { Some(Value::Binary { val: b, .. }) => {
bytes.extend_from_slice(&b); bytes.extend_from_slice(&b);
} }
Some(Value::Error { error }) => return Err(error), Some(Value::Error { error }) => return Err(*error),
Some(x) => { Some(x) => {
return Err(ShellError::UnsupportedInput( return Err(ShellError::UnsupportedInput(
"Expected binary from pipeline".to_string(), "Expected binary from pipeline".to_string(),

View File

@ -16,7 +16,7 @@ fn from_value_to_delimited_string(
} }
Value::List { vals, span } => table_to_delimited(vals, span, separator, config, head), Value::List { vals, span } => table_to_delimited(vals, span, separator, config, head),
// Propagate errors by explicitly matching them before the final case. // Propagate errors by explicitly matching them before the final case.
Value::Error { error } => Err(error.clone()), Value::Error { error } => Err(*error.clone()),
v => Err(make_unsupported_input_error(v, head, v.expect_span())), v => Err(make_unsupported_input_error(v, head, v.expect_span())),
} }
} }
@ -122,7 +122,7 @@ fn to_string_tagged_value(
Value::Date { val, .. } => Ok(val.to_string()), Value::Date { val, .. } => Ok(val.to_string()),
Value::Nothing { .. } => Ok(String::new()), Value::Nothing { .. } => Ok(String::new()),
// Propagate existing errors // Propagate existing errors
Value::Error { error } => Err(error.clone()), Value::Error { error } => Err(*error.clone()),
_ => Err(make_unsupported_input_error(v, head, span)), _ => Err(make_unsupported_input_error(v, head, span)),
} }
} }

View File

@ -70,12 +70,12 @@ impl Command for ToJson {
} }
.into_pipeline_data()), .into_pipeline_data()),
_ => Ok(Value::Error { _ => Ok(Value::Error {
error: ShellError::CantConvert { error: Box::new(ShellError::CantConvert {
to_type: "JSON".into(), to_type: "JSON".into(),
from_type: value.get_type().to_string(), from_type: value.get_type().to_string(),
span, span,
help: None, help: None,
}, }),
} }
.into_pipeline_data()), .into_pipeline_data()),
} }
@ -126,7 +126,7 @@ pub fn value_to_json_value(v: &Value) -> Result<nu_json::Value, ShellError> {
), ),
Value::List { vals, .. } => nu_json::Value::Array(json_list(vals)?), Value::List { vals, .. } => nu_json::Value::Array(json_list(vals)?),
Value::Error { error } => return Err(error.clone()), Value::Error { error } => return Err(*error.clone()),
Value::Closure { .. } | Value::Block { .. } | Value::Range { .. } => nu_json::Value::Null, Value::Closure { .. } | Value::Block { .. } | Value::Range { .. } => nu_json::Value::Null,
Value::Binary { val, .. } => { Value::Binary { val, .. } => {
nu_json::Value::Array(val.iter().map(|x| nu_json::Value::U64(*x as u64)).collect()) nu_json::Value::Array(val.iter().map(|x| nu_json::Value::U64(*x as u64)).collect())

View File

@ -101,7 +101,7 @@ pub fn value_to_string(v: &Value, span: Span) -> Result<String, ShellError> {
// FIXME: make durations use the shortest lossless representation. // FIXME: make durations use the shortest lossless representation.
Value::Duration { val, .. } => Ok(format!("{}ns", *val)), Value::Duration { val, .. } => Ok(format!("{}ns", *val)),
// Propagate existing errors // Propagate existing errors
Value::Error { error } => Err(error.clone()), Value::Error { error } => Err(*error.clone()),
// FIXME: make filesizes use the shortest lossless representation. // FIXME: make filesizes use the shortest lossless representation.
Value::Filesize { val, .. } => Ok(format!("{}b", *val)), Value::Filesize { val, .. } => Ok(format!("{}b", *val)),
Value::Float { val, .. } => { Value::Float { val, .. } => {

View File

@ -77,7 +77,7 @@ fn helper(engine_state: &EngineState, v: &Value) -> Result<toml::Value, ShellErr
toml::Value::String(code) toml::Value::String(code)
} }
Value::Nothing { .. } => toml::Value::String("<Nothing>".to_string()), Value::Nothing { .. } => toml::Value::String("<Nothing>".to_string()),
Value::Error { error } => return Err(error.clone()), Value::Error { error } => return Err(*error.clone()),
Value::Binary { val, .. } => toml::Value::Array( Value::Binary { val, .. } => toml::Value::Array(
val.iter() val.iter()
.map(|x| toml::Value::Integer(*x as i64)) .map(|x| toml::Value::Integer(*x as i64))
@ -118,12 +118,12 @@ fn toml_into_pipeline_data(
} }
.into_pipeline_data()), .into_pipeline_data()),
_ => Ok(Value::Error { _ => Ok(Value::Error {
error: ShellError::CantConvert { error: Box::new(ShellError::CantConvert {
to_type: "TOML".into(), to_type: "TOML".into(),
from_type: value_type.to_string(), from_type: value_type.to_string(),
span, span,
help: None, help: None,
}, }),
} }
.into_pipeline_data()), .into_pipeline_data()),
} }
@ -137,7 +137,7 @@ fn value_to_toml_value(
match v { match v {
Value::Record { .. } => helper(engine_state, v), Value::Record { .. } => helper(engine_state, v),
// Propagate existing errors // Propagate existing errors
Value::Error { error } => Err(error.clone()), Value::Error { error } => Err(*error.clone()),
_ => Err(ShellError::UnsupportedInput( _ => Err(ShellError::UnsupportedInput(
format!("{:?} is not valid top-level TOML", v.get_type()), format!("{:?} is not valid top-level TOML", v.get_type()),
"value originates from here".into(), "value originates from here".into(),

View File

@ -79,7 +79,7 @@ pub fn value_to_yaml_value(v: &Value) -> Result<serde_yaml::Value, ShellError> {
Value::Block { .. } => serde_yaml::Value::Null, Value::Block { .. } => serde_yaml::Value::Null,
Value::Closure { .. } => serde_yaml::Value::Null, Value::Closure { .. } => serde_yaml::Value::Null,
Value::Nothing { .. } => serde_yaml::Value::Null, Value::Nothing { .. } => serde_yaml::Value::Null,
Value::Error { error } => return Err(error.clone()), Value::Error { error } => return Err(*error.clone()),
Value::Binary { val, .. } => serde_yaml::Value::Sequence( Value::Binary { val, .. } => serde_yaml::Value::Sequence(
val.iter() val.iter()
.map(|x| serde_yaml::Value::Number(serde_yaml::Number::from(*x))) .map(|x| serde_yaml::Value::Number(serde_yaml::Number::from(*x)))
@ -111,12 +111,12 @@ fn to_yaml(input: PipelineData, head: Span) -> Result<PipelineData, ShellError>
} }
.into_pipeline_data()), .into_pipeline_data()),
_ => Ok(Value::Error { _ => Ok(Value::Error {
error: ShellError::CantConvert { error: Box::new(ShellError::CantConvert {
to_type: "YAML".into(), to_type: "YAML".into(),
from_type: value.get_type().to_string(), from_type: value.get_type().to_string(),
span: head, span: head,
help: None, help: None,
}, }),
} }
.into_pipeline_data()), .into_pipeline_data()),
} }

View File

@ -111,16 +111,20 @@ where
other => { other => {
let span = match input.span() { let span = match input.span() {
Ok(span) => span, Ok(span) => span,
Err(error) => return Value::Error { error }, Err(error) => {
return Value::Error {
error: Box::new(error),
}
}
}; };
return Value::Error { return Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string or binary".into(), exp_input_type: "string or binary".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: span, dst_span: span,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}; };
} }
}; };

View File

@ -76,7 +76,9 @@ where
}), }),
); );
if let Err(error) = r { if let Err(error) = r {
return Value::Error { error }; return Value::Error {
error: Box::new(error),
};
} }
} }
v v

View File

@ -68,12 +68,12 @@ fn abs_helper(val: Value, head: Span) -> Value {
}, },
Value::Error { .. } => val, Value::Error { .. } => val,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -77,23 +77,23 @@ fn operate(value: Value, head: Span, use_degrees: bool) -> Value {
Value::Float { val, span } Value::Float { val, span }
} else { } else {
Value::Error { Value::Error {
error: ShellError::UnsupportedInput( error: Box::new(ShellError::UnsupportedInput(
"'arccos' undefined for values outside the closed interval [-1, 1].".into(), "'arccos' undefined for values outside the closed interval [-1, 1].".into(),
"value originates from here".into(), "value originates from here".into(),
head, head,
span, span,
), )),
} }
} }
} }
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -67,23 +67,23 @@ fn operate(value: Value, head: Span) -> Value {
Value::Float { val, span } Value::Float { val, span }
} else { } else {
Value::Error { Value::Error {
error: ShellError::UnsupportedInput( error: Box::new(ShellError::UnsupportedInput(
"'arccosh' undefined for values below 1.".into(), "'arccosh' undefined for values below 1.".into(),
"value originates from here".into(), "value originates from here".into(),
head, head,
span, span,
), )),
} }
} }
} }
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -78,23 +78,23 @@ fn operate(value: Value, head: Span, use_degrees: bool) -> Value {
Value::Float { val, span } Value::Float { val, span }
} else { } else {
Value::Error { Value::Error {
error: ShellError::UnsupportedInput( error: Box::new(ShellError::UnsupportedInput(
"'arcsin' undefined for values outside the closed interval [-1, 1].".into(), "'arcsin' undefined for values outside the closed interval [-1, 1].".into(),
"value originates from here".into(), "value originates from here".into(),
head, head,
span, span,
), )),
} }
} }
} }
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -67,12 +67,12 @@ fn operate(value: Value, head: Span) -> Value {
} }
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -78,12 +78,12 @@ fn operate(value: Value, head: Span, use_degrees: bool) -> Value {
} }
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -67,23 +67,23 @@ fn operate(value: Value, head: Span) -> Value {
Value::Float { val, span } Value::Float { val, span }
} else { } else {
Value::Error { Value::Error {
error: ShellError::UnsupportedInput( error: Box::new(ShellError::UnsupportedInput(
"'arctanh' undefined for values outside the open interval (-1, 1).".into(), "'arctanh' undefined for values outside the open interval (-1, 1).".into(),
"value originates from here".into(), "value originates from here".into(),
head, head,
span, span,
), )),
} }
} }
} }
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -64,12 +64,12 @@ fn operate(value: Value, head: Span) -> Value {
}, },
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -88,12 +88,12 @@ fn operate(value: Value, head: Span, use_degrees: bool) -> Value {
} }
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -69,12 +69,12 @@ fn operate(value: Value, head: Span) -> Value {
} }
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -64,12 +64,12 @@ fn operate(value: Value, head: Span) -> Value {
}, },
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -67,23 +67,23 @@ fn operate(value: Value, head: Span) -> Value {
Value::Float { val, span } Value::Float { val, span }
} else { } else {
Value::Error { Value::Error {
error: ShellError::UnsupportedInput( error: Box::new(ShellError::UnsupportedInput(
"'ln' undefined for values outside the open interval (0, Inf).".into(), "'ln' undefined for values outside the open interval (0, Inf).".into(),
"value originates from here".into(), "value originates from here".into(),
head, head,
span, span,
), )),
} }
} }
} }
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -96,13 +96,13 @@ fn operate(value: Value, head: Span, base: f64) -> Value {
if val <= 0.0 { if val <= 0.0 {
return Value::Error { return Value::Error {
error: ShellError::UnsupportedInput( error: Box::new(ShellError::UnsupportedInput(
"'math log' undefined for values outside the open interval (0, Inf)." "'math log' undefined for values outside the open interval (0, Inf)."
.into(), .into(),
"value originates from here".into(), "value originates from here".into(),
head, head,
span, span,
), )),
}; };
} }
// Specialize for better precision/performance // Specialize for better precision/performance
@ -118,12 +118,12 @@ fn operate(value: Value, head: Span, base: f64) -> Value {
} }
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -132,7 +132,7 @@ pub fn mode(values: &[Value], _span: Span, head: &Span) -> Result<Value, ShellEr
Value::Filesize { val, .. } => { Value::Filesize { val, .. } => {
Ok(HashableType::new(val.to_ne_bytes(), NumberTypes::Filesize)) Ok(HashableType::new(val.to_ne_bytes(), NumberTypes::Filesize))
} }
Value::Error { error } => Err(error.clone()), Value::Error { error } => Err(*error.clone()),
other => Err(ShellError::UnsupportedInput( other => Err(ShellError::UnsupportedInput(
"Unable to give a result with this input".to_string(), "Unable to give a result with this input".to_string(),
"value originates from here".into(), "value originates from here".into(),

View File

@ -112,7 +112,7 @@ pub fn sum(data: Vec<Value>, span: Span, head: Span) -> Result<Value, ShellError
| Value::Duration { .. } => { | Value::Duration { .. } => {
acc = acc.add(head, value, head)?; acc = acc.add(head, value, head)?;
} }
Value::Error { error } => return Err(error.clone()), Value::Error { error } => return Err(*error.clone()),
other => { other => {
return Err(ShellError::UnsupportedInput( return Err(ShellError::UnsupportedInput(
"Attempted to compute the sum of a value that cannot be summed".to_string(), "Attempted to compute the sum of a value that cannot be summed".to_string(),
@ -145,7 +145,7 @@ pub fn product(data: Vec<Value>, span: Span, head: Span) -> Result<Value, ShellE
Value::Int { .. } | Value::Float { .. } => { Value::Int { .. } | Value::Float { .. } => {
acc = acc.mul(head, value, head)?; acc = acc.mul(head, value, head)?;
} }
Value::Error { error } => return Err(error.clone()), Value::Error { error } => return Err(*error.clone()),
other => { other => {
return Err(ShellError::UnsupportedInput( return Err(ShellError::UnsupportedInput(
"Attempted to compute the product of a value that cannot be multiplied" "Attempted to compute the product of a value that cannot be multiplied"

View File

@ -95,12 +95,12 @@ fn operate(value: Value, head: Span, precision: Option<i64>) -> Value {
Value::Int { .. } => value, Value::Int { .. } => value,
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -88,12 +88,12 @@ fn operate(value: Value, head: Span, use_degrees: bool) -> Value {
} }
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -69,12 +69,12 @@ fn operate(value: Value, head: Span) -> Value {
} }
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

View File

@ -73,24 +73,24 @@ fn operate(value: Value, head: Span) -> Value {
} }
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }
fn error_negative_sqrt(head: Span, span: Span) -> Value { fn error_negative_sqrt(head: Span, span: Span) -> Value {
Value::Error { Value::Error {
error: ShellError::UnsupportedInput( error: Box::new(ShellError::UnsupportedInput(
String::from("Can't square root a negative number"), String::from("Can't square root a negative number"),
"value originates from here".into(), "value originates from here".into(),
head, head,
span, span,
), )),
} }
} }

View File

@ -86,12 +86,12 @@ fn operate(value: Value, head: Span, use_degrees: bool) -> Value {
} }
Value::Error { .. } => value, Value::Error { .. } => value,
other => Value::Error { other => Value::Error {
error: ShellError::OnlySupportsThisInputType { error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(), exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(), wrong_type: other.get_type().to_string(),
dst_span: head, dst_span: head,
src_span: other.expect_span(), src_span: other.expect_span(),
}, }),
}, },
} }
} }

Some files were not shown because too many files have changed in this diff Show More