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 {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, error);
report_error(&working_set, &**error);
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 {
let working_set = StateWorkingSet::new(engine_state);
report_error(&working_set, &error);
report_error(&working_set, &*error);
std::process::exit(1);
}

View File

@ -53,7 +53,9 @@ impl Command for NuHighlight {
span: head,
}
}
Err(err) => Value::Error { error: err },
Err(err) => Value::Error {
error: Box::new(err),
},
},
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)?;
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

View File

@ -57,66 +57,29 @@ impl Command for Try {
let result = eval_block(engine_state, stack, try_block, input, false, false);
match result {
Err(error) | Ok(PipelineData::Value(Value::Error { error }, ..)) => {
if let nu_protocol::ShellError::Break(_) = error {
return Err(error);
} else if let nu_protocol::ShellError::Continue(_) = error {
return Err(error);
} else if let nu_protocol::ShellError::Return(_, _) = error {
return Err(error);
}
if let Some(catch_block) = catch_block {
let catch_block = engine_state.get_block(catch_block.block_id);
let err_value = Value::Error { error };
// 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())
}
Err(error) => {
let error = intercept_block_control(error)?;
let err_value = Value::Error {
error: Box::new(error),
};
handle_catch(err_value, catch_block, engine_state, stack)
}
Ok(PipelineData::Value(Value::Error { error }, ..)) => {
let error = intercept_block_control(*error)?;
let err_value = Value::Error {
error: Box::new(error),
};
handle_catch(err_value, catch_block, engine_state, stack)
}
// external command may fail to run
Ok(pipeline) => {
let (pipeline, external_failed) = pipeline.is_external_failed();
if external_failed {
if let Some(catch_block) = catch_block {
let catch_block = engine_state.get_block(catch_block.block_id);
if let Some(var) = catch_block.signature.get_positional(0) {
if let Some(var_id) = &var.var_id {
// 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())
}
// 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);
handle_catch(err_value, catch_block, engine_state, stack)
} else {
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)]
mod test {
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.
Value::Error { .. } => value,
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
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
Value::Error { .. } => other,
_ => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
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.
Value::Error { .. } => value,
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.expect_span(),
},
}),
},
}
}

View File

@ -103,7 +103,7 @@ where
match rotate_result {
Ok(val) => Value::Int { val, span },
Err(_) => Value::Error {
error: ShellError::GenericError(
error: Box::new(ShellError::GenericError(
"Rotate left result beyond the range of 64 bit signed number".to_string(),
format!(
"{val} of the specified number of bytes rotate left {bits} bits exceed limit"
@ -111,7 +111,7 @@ where
Some(span),
None,
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.
Value::Error { .. } => value,
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.expect_span(),
},
}),
},
}
}

View File

@ -107,7 +107,7 @@ where
match rotate_result {
Ok(val) => Value::Int { val, span },
Err(_) => Value::Error {
error: ShellError::GenericError(
error: Box::new(ShellError::GenericError(
"Rotate right result beyond the range of 64 bit signed number".to_string(),
format!(
"{val} of the specified number of bytes rotate right {bits} bits exceed limit"
@ -115,7 +115,7 @@ where
Some(span),
None,
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.
Value::Error { .. } => value,
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.expect_span(),
},
}),
},
}
}

View File

@ -115,7 +115,7 @@ where
match shift_result {
Ok(val) => Value::Int { val, span },
Err(_) => Value::Error {
error: ShellError::GenericError(
error: Box::new(ShellError::GenericError(
"Shift left result beyond the range of 64 bit signed number".to_string(),
format!(
"{val} of the specified number of bytes shift left {bits} bits exceed limit"
@ -123,18 +123,18 @@ where
Some(span),
None,
Vec::new(),
),
)),
},
}
}
None => Value::Error {
error: ShellError::GenericError(
error: Box::new(ShellError::GenericError(
"Shift left failed".to_string(),
format!("{val} shift left {bits} bits failed, you may shift too many bits"),
Some(span),
None,
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.
Value::Error { .. } => value,
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.expect_span(),
},
}),
},
}
}

View File

@ -105,7 +105,7 @@ where
match shift_result {
Ok(val) => Value::Int { val, span },
Err(_) => Value::Error {
error: ShellError::GenericError(
error: Box::new(ShellError::GenericError(
"Shift right result beyond the range of 64 bit signed number".to_string(),
format!(
"{val} of the specified number of bytes shift right {bits} bits exceed limit"
@ -113,18 +113,18 @@ where
Some(span),
None,
Vec::new(),
),
)),
},
}
}
None => Value::Error {
error: ShellError::GenericError(
error: Box::new(ShellError::GenericError(
"Shift right failed".to_string(),
format!("{val} shift right {bits} bits failed, you may shift too many bits"),
Some(span),
None,
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.
Value::Error { .. } => value,
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
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.
Value::Error { .. } => value,
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
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.
Value::Error { .. } => val.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(),
dst_span: 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::String { val, .. } => val,
// Explicitly propagate errors instead of dropping them.
Value::Error { error } => return Err(error),
Value::Error { error } => return Err(*error),
other => {
return Err(ShellError::UnsupportedInput(
"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::String { val, .. } => val,
// Explicitly propagate errors instead of dropping them.
Value::Error { error } => return Err(error),
Value::Error { error } => return Err(*error),
other => {
return Err(ShellError::UnsupportedInput(
"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.
Value::Error { error } => return Err(error),
Value::Error { error } => return Err(*error),
other => {
return Err(ShellError::UnsupportedInput(
"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.
Value::Error { .. } => val.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(),
dst_span: span,
src_span: other.expect_span(),
},
}),
},
}
}
@ -277,10 +277,10 @@ fn at_impl(input: &[u8], arg: &Arguments, span: Span) -> Value {
match start.cmp(&end) {
Ordering::Equal => Value::Binary { val: vec![], span },
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(),
span: arg.arg_span,
},
}),
},
Ordering::Less => Value::Binary {
val: {

View File

@ -53,7 +53,7 @@ impl Command for BytesBuild {
match val {
Value::Binary { mut val, .. } => output.append(&mut val),
// Explicitly propagate errors instead of dropping them.
Value::Error { error } => return Err(error),
Value::Error { error } => return Err(*error),
other => {
return Err(ShellError::TypeMismatch {
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.
Value::Error { error } => return Err(error),
Value::Error { error } => return Err(*error),
other => {
return Err(ShellError::OnlySupportsThisInputType {
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.
Value::Error { .. } => val.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(),
dst_span: 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.
Value::Error { .. } => val.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(),
dst_span: 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.
Value::Error { .. } => val.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(),
dst_span: 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.
Value::Error { .. } => val.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(),
dst_span: 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.
Value::Error { .. } => val.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(),
dst_span: 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.
Value::Error { .. } => val.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(),
dst_span: span,
src_span: other.expect_span(),
},
}),
},
}
}

View File

@ -80,12 +80,12 @@ impl Command for BytesStartsWith {
// Unsupported data
Ok(other) => {
return Ok(Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string and binary".into(),
wrong_type: other.get_type().to_string(),
dst_span: span,
src_span: other.expect_span(),
},
}),
}
.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.
Value::Error { .. } => val.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "binary".into(),
wrong_type: other.get_type().to_string(),
dst_span: span,
src_span: other.expect_span(),
},
}),
},
}
}

View File

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

View File

@ -160,7 +160,7 @@ fn run_histogram(
for v in values {
match v {
// Propagate existing errors.
Value::Error { error } => return Err(error),
Value::Error { error } => return Err(*error),
_ => {
let t = v.get_type();
let span = v.expect_span();
@ -198,7 +198,7 @@ fn run_histogram(
}
}
// Propagate existing errors.
Value::Error { error } => return Err(error),
Value::Error { error } => return Err(*error),
_ => 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.
Value::Error { .. } => input.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "int, filesize, float, string".into(),
wrong_type: other.get_type().to_string(),
dst_span: 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.
Value::Error { .. } => input.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer or filesize".into(),
wrong_type: other.get_type().to_string(),
dst_span: 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.
Value::Error { .. } => input.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer, float, filesize, string, date, duration, binary or bool"
.into(),
wrong_type: other.get_type().to_string(),
dst_span: 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) {
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.
Value::Error { .. } => input.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "bool, integer, float or string".into(),
wrong_type: other.get_type().to_string(),
dst_span: 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(),
other => {
return Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string and integer".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
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) {
Some(eastoffset) => match_datetime!(eastoffset.timestamp_nanos(ts)),
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) {
Some(westoffset) => match_datetime!(westoffset.timestamp_nanos(ts)),
None => Value::Error {
error: ShellError::DatetimeParseError(input.debug_value(), *span),
error: Box::new(ShellError::DatetimeParseError(input.debug_value(), *span)),
},
},
Zone::Error => Value::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(),
span: *span,
},
}),
},
},
};
@ -273,7 +273,7 @@ fn action(input: &Value, args: &Arguments, head: Span) -> Value {
Ok(d) => Value::Date { val: d, span: head },
Err(reason) => {
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.
Value::Error { .. } => input.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.expect_span(),
},
}),
},
}
}
@ -374,7 +374,7 @@ mod tests {
#[test]
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 {
item: Zone::East(8),
span: Span::test_data(),

View File

@ -88,12 +88,12 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, head: Span) -> Value {
match other.parse::<f64>() {
Ok(x) => Value::float(x, head),
Err(reason) => Value::Error {
error: ShellError::CantConvert {
error: Box::new(ShellError::CantConvert {
to_type: "float".to_string(),
from_type: reason.to_string(),
span: *span,
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.
Value::Error { .. } => input.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string, integer or bool".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.expect_span(),
},
}),
},
}
}

View File

@ -174,7 +174,9 @@ fn into_duration(
Box::new(move |old| action(old, &d, float_precision, head)),
);
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 {
input.clone()
@ -464,34 +466,36 @@ fn action(
}
}
}
Err(e) => Value::Error { error: e },
Err(e) => Value::Error { error: Box::new(e) },
}
} else {
Value::Error {
error: ShellError::CantConvert {
error: Box::new(ShellError::CantConvert {
to_type: "string".into(),
from_type: "duration".into(),
span,
help: None,
},
}),
}
}
} else {
match string_to_duration(val, span, *value_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.
Value::Error { .. } => input.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string or duration".into(),
wrong_type: other.get_type().to_string(),
dst_span: span,
src_span: other.expect_span(),
},
}),
},
}
}

View File

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

View File

@ -189,12 +189,12 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
Ok(v) => v,
_ => {
return Value::Error {
error: ShellError::CantConvert {
error: Box::new(ShellError::CantConvert {
to_type: "float".to_string(),
from_type: "integer".to_string(),
span,
help: None,
},
}),
}
}
}
@ -206,7 +206,9 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
if radix == 10 {
match int_from_string(val, span) {
Ok(val) => Value::Int { val, span },
Err(error) => Value::Error { error },
Err(error) => Value::Error {
error: Box::new(error),
},
}
} else {
convert_int(input, span, radix)
@ -232,10 +234,10 @@ fn action(input: &Value, args: &Arguments, span: Span) -> Value {
.unwrap()
{
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(),
span
},
}),
}
} else {
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.
Value::Error { .. } => input.clone(),
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "integer, float, filesize, date, string, binary, duration or bool"
.into(),
wrong_type: other.get_type().to_string(),
dst_span: 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) {
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") {
// 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),
Err(e) => {
return Value::Error {
error: ShellError::CantConvert {
error: Box::new(ShellError::CantConvert {
to_type: "string".to_string(),
from_type: "int".to_string(),
span: head,
help: Some(e.to_string()),
},
}),
}
}
}
@ -316,24 +318,24 @@ fn convert_int(input: &Value, head: Span, radix: u32) -> Value {
Value::Error { .. } => return input.clone(),
other => {
return Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string and integer".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.expect_span(),
},
}),
};
}
};
match i64::from_str_radix(i.trim(), radix) {
Ok(n) => Value::int(n, head),
Err(_reason) => Value::Error {
error: ShellError::CantConvert {
error: Box::new(ShellError::CantConvert {
to_type: "string".to_string(),
from_type: "int".to_string(),
span: head,
help: None,
},
}),
},
}
}
@ -483,9 +485,9 @@ mod test {
}
#[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("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(
#[case] dt_in: DateTime<FixedOffset>,
#[case] int_expected: i64,
@ -522,14 +524,15 @@ mod test {
},
Span::test_data(),
);
if let Value::Error {
error: ShellError::IncorrectValue { msg: e, .. },
} = actual
{
assert!(
e.contains(err_expected),
"{e:?} doesn't contain {err_expected}"
);
if let Value::Error { error } = actual {
if let ShellError::IncorrectValue { msg: e, .. } = *error {
assert!(
e.contains(err_expected),
"{e:?} doesn't contain {err_expected}"
);
} else {
panic!("Unexpected error variant {error:?}")
}
} else {
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::Error { .. } => input,
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "string".into(),
wrong_type: other.get_type().to_string(),
dst_span: call.head,
src_span: other.expect_span(),
},
}),
},
};
Ok(res.into_pipeline_data())

View File

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

View File

@ -217,7 +217,7 @@ fn action(
Ok(Value::Nothing { span: *span })
}
// 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 {
exp_input_type: "list".into(),
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,
Err(_) => {
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,
None => {
return Value::Error {
error: ShellError::UnsupportedInput(
error: Box::new(ShellError::UnsupportedInput(
"The given local datetime representation is invalid."
.to_string(),
format!("timestamp is {a:?}"),
span,
Span::unknown(),
),
)),
}
}
};
@ -476,13 +476,13 @@ pub fn create_column(
Some(val) => val,
None => {
return Value::Error {
error: ShellError::UnsupportedInput(
error: Box::new(ShellError::UnsupportedInput(
"The given local datetime representation is invalid."
.to_string(),
format!("timestamp is {a:?}"),
span,
Span::unknown(),
),
)),
}
}
};
@ -526,13 +526,13 @@ pub fn create_column(
Some(val) => val,
None => {
return Value::Error {
error: ShellError::UnsupportedInput(
error: Box::new(ShellError::UnsupportedInput(
"The given local datetime representation is invalid."
.to_string(),
format!("timestamp is {a:?}"),
span,
Span::unknown(),
),
)),
}
}
};
@ -541,13 +541,13 @@ pub fn create_column(
Some(val) => val,
None => {
return Value::Error {
error: ShellError::UnsupportedInput(
error: Box::new(ShellError::UnsupportedInput(
"The given local datetime representation is invalid."
.to_string(),
format!("timestamp is {a:?}"),
span,
Span::unknown(),
),
)),
}
}
};

View File

@ -132,10 +132,10 @@ where
span,
},
Err(_) => Value::Error {
error: ShellError::TypeMismatch {
error: Box::new(ShellError::TypeMismatch {
err_message: "invalid format".to_string(),
span,
},
}),
},
}
}
@ -152,7 +152,10 @@ fn format_helper(value: Value, formatter: &str, formatter_span: Span, head_span:
}
}
_ => 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 {
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,
},
_ => 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::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::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)
}
_ => 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()) {
Ok(dt) => Value::Date { val: dt, span },
Err(_) => Value::Error {
error: ShellError::TypeMismatch {
error: Box::new(ShellError::TypeMismatch {
err_message: String::from("invalid time zone"),
span: timezone.span,
},
}),
},
}
}

View File

@ -15,12 +15,12 @@ pub(crate) fn parse_date_from_string(
LocalResult::Single(d) => Ok(d),
LocalResult::Ambiguous(d, _) => Ok(d),
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 {
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 {
match eval_expression(engine_state, stack, inner_expr) {
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 {
Value::Error {
error: ShellError::GenericError(
error: Box::new(ShellError::GenericError(
e.to_string(),
e.to_string(),
Some(span),
None,
Vec::new(),
),
)),
}
} else if !confirmed {
let msg = format!("{:} not copied to {:}", src.display(), dst.display());
@ -518,13 +518,13 @@ fn copy_symlink(
Ok(p) => p,
Err(err) => {
return Value::Error {
error: ShellError::GenericError(
error: Box::new(ShellError::GenericError(
err.to_string(),
err.to_string(),
Some(span),
None,
vec![],
),
)),
}
}
};
@ -551,7 +551,13 @@ fn copy_symlink(
Value::String { val: msg, span }
}
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),
};
Value::Error { error: shell_error }
Value::Error {
error: Box::new(shell_error),
}
}

View File

@ -255,10 +255,14 @@ impl Command for Ls {
);
match entry {
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 }),

View File

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

View File

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

View File

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

View File

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

View File

@ -167,7 +167,9 @@ with 'transpose' first."#
Err(ShellError::Break(_)) => None,
Err(error) => {
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 {
Ok(x) => x,
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) {
@ -208,7 +214,7 @@ with 'transpose' first."#
Ok(v) => Some(v.into_value(span)),
Err(ShellError::Break(_)) => None,
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 })
}
}

View File

@ -101,7 +101,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
}
}
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 {
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) {
@ -144,7 +148,7 @@ a variable. On the other hand, the "row condition" syntax is not supported."#
}
}
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 {
error: chain_error_with_input(error, x.span()),
error: Box::new(chain_error_with_input(error, x.span())),
}),
}
.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.
Value::Error { error } => return Err(error),
Value::Error { error } => return Err(*error),
other => {
return Err(ShellError::UnsupportedInput(
"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.
Value::Error { error } => Err(error),
Value::Error { error } => Err(*error),
other => Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "list, binary or range".into(),
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> {
let tag = match item.span() {
Ok(x) => x,
Err(e) => return vec![Value::Error { error: e }],
Err(e) => return vec![Value::Error { error: Box::new(e) }],
};
let res = {
@ -172,19 +172,19 @@ fn flat_value(columns: &[CellPath], item: &Value, _name_tag: Span, all: bool) ->
Value::Error { .. } => return vec![item.clone()],
other => {
return vec![Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "record".into(),
wrong_type: other.get_type().to_string(),
dst_span: _name_tag,
src_span: other.expect_span(),
},
}),
}];
}
};
let s = match item.span() {
Ok(x) => x,
Err(e) => return vec![Value::Error { error: e }],
Err(e) => return vec![Value::Error { error: Box::new(e) }],
};
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 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(),
"value originates from here".into(),
s,
*span
)}
))}
];
}
// 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 } => {
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(),
"value originates from here".into(),
s,
*span
)}
))}
];
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -158,9 +158,13 @@ impl Command for Move {
call.head,
) {
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 {

View File

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

View File

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

View File

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

View File

@ -132,12 +132,12 @@ fn update(
if let Err(e) =
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
}
Err(e) => Value::Error { error: e },
Err(e) => Value::Error { error: Box::new(e) },
}
},
ctrlc,
@ -174,7 +174,7 @@ fn update(
let replacement = replacement.clone();
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

View File

@ -253,7 +253,7 @@ fn process_cell(
redirect_stderr,
) {
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) =
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
}
Err(e) => Value::Error { error: e },
Err(e) => Value::Error { error: Box::new(e) },
}
},
ctrlc,
@ -195,7 +195,7 @@ fn upsert(
let replacement = replacement.clone();
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

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 {
exp_input_type: "record or table".into(),
@ -176,7 +176,7 @@ fn values(
Ok(vals.into_pipeline_data(ctrlc).set_metadata(metadata))
}
// Propagate errors
PipelineData::Value(Value::Error { error }, ..) => Err(error),
PipelineData::Value(Value::Error { error }, ..) => Err(*error),
PipelineData::Value(other, ..) => Err(ShellError::OnlySupportsThisInputType {
exp_input_type: "record or table".into(),
wrong_type: other.get_type().to_string(),

View File

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

View File

@ -77,7 +77,9 @@ impl Command for FromJson {
} else {
match convert_string_to_value(x.to_string(), span) {
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) => {
if *u > i64::MAX as u64 {
Value::Error {
error: ShellError::CantConvert {
error: Box::new(ShellError::CantConvert {
to_type: "i64 sized integer".into(),
from_type: "value larger than i64".into(),
span,
help: None,
},
}),
}
} else {
Value::Int {

View File

@ -93,7 +93,7 @@ fn collect_binary(input: PipelineData, span: Span) -> Result<Vec<u8>, ShellError
Some(Value::Binary { val: b, .. }) => {
bytes.extend_from_slice(&b);
}
Some(Value::Error { error }) => return Err(error),
Some(Value::Error { error }) => return Err(*error),
Some(x) => {
return Err(ShellError::UnsupportedInput(
"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),
// 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())),
}
}
@ -122,7 +122,7 @@ fn to_string_tagged_value(
Value::Date { val, .. } => Ok(val.to_string()),
Value::Nothing { .. } => Ok(String::new()),
// Propagate existing errors
Value::Error { error } => Err(error.clone()),
Value::Error { error } => Err(*error.clone()),
_ => Err(make_unsupported_input_error(v, head, span)),
}
}

View File

@ -70,12 +70,12 @@ impl Command for ToJson {
}
.into_pipeline_data()),
_ => Ok(Value::Error {
error: ShellError::CantConvert {
error: Box::new(ShellError::CantConvert {
to_type: "JSON".into(),
from_type: value.get_type().to_string(),
span,
help: None,
},
}),
}
.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::Error { error } => return Err(error.clone()),
Value::Error { error } => return Err(*error.clone()),
Value::Closure { .. } | Value::Block { .. } | Value::Range { .. } => nu_json::Value::Null,
Value::Binary { val, .. } => {
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.
Value::Duration { val, .. } => Ok(format!("{}ns", *val)),
// Propagate existing errors
Value::Error { error } => Err(error.clone()),
Value::Error { error } => Err(*error.clone()),
// FIXME: make filesizes use the shortest lossless representation.
Value::Filesize { val, .. } => Ok(format!("{}b", *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)
}
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(
val.iter()
.map(|x| toml::Value::Integer(*x as i64))
@ -118,12 +118,12 @@ fn toml_into_pipeline_data(
}
.into_pipeline_data()),
_ => Ok(Value::Error {
error: ShellError::CantConvert {
error: Box::new(ShellError::CantConvert {
to_type: "TOML".into(),
from_type: value_type.to_string(),
span,
help: None,
},
}),
}
.into_pipeline_data()),
}
@ -137,7 +137,7 @@ fn value_to_toml_value(
match v {
Value::Record { .. } => helper(engine_state, v),
// Propagate existing errors
Value::Error { error } => Err(error.clone()),
Value::Error { error } => Err(*error.clone()),
_ => Err(ShellError::UnsupportedInput(
format!("{:?} is not valid top-level TOML", v.get_type()),
"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::Closure { .. } => 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(
val.iter()
.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()),
_ => Ok(Value::Error {
error: ShellError::CantConvert {
error: Box::new(ShellError::CantConvert {
to_type: "YAML".into(),
from_type: value.get_type().to_string(),
span: head,
help: None,
},
}),
}
.into_pipeline_data()),
}

View File

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

View File

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

View File

@ -68,12 +68,12 @@ fn abs_helper(val: Value, head: Span) -> Value {
},
Value::Error { .. } => val,
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
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 }
} else {
Value::Error {
error: ShellError::UnsupportedInput(
error: Box::new(ShellError::UnsupportedInput(
"'arccos' undefined for values outside the closed interval [-1, 1].".into(),
"value originates from here".into(),
head,
span,
),
)),
}
}
}
Value::Error { .. } => value,
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.expect_span(),
},
}),
},
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -96,13 +96,13 @@ fn operate(value: Value, head: Span, base: f64) -> Value {
if val <= 0.0 {
return Value::Error {
error: ShellError::UnsupportedInput(
error: Box::new(ShellError::UnsupportedInput(
"'math log' undefined for values outside the open interval (0, Inf)."
.into(),
"value originates from here".into(),
head,
span,
),
)),
};
}
// Specialize for better precision/performance
@ -118,12 +118,12 @@ fn operate(value: Value, head: Span, base: f64) -> Value {
}
Value::Error { .. } => value,
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
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, .. } => {
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(
"Unable to give a result with this input".to_string(),
"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 { .. } => {
acc = acc.add(head, value, head)?;
}
Value::Error { error } => return Err(error.clone()),
Value::Error { error } => return Err(*error.clone()),
other => {
return Err(ShellError::UnsupportedInput(
"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 { .. } => {
acc = acc.mul(head, value, head)?;
}
Value::Error { error } => return Err(error.clone()),
Value::Error { error } => return Err(*error.clone()),
other => {
return Err(ShellError::UnsupportedInput(
"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::Error { .. } => value,
other => Value::Error {
error: ShellError::OnlySupportsThisInputType {
error: Box::new(ShellError::OnlySupportsThisInputType {
exp_input_type: "numeric".into(),
wrong_type: other.get_type().to_string(),
dst_span: head,
src_span: other.expect_span(),
},
}),
},
}
}

View File

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

View File

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

View File

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

View File

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

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