mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 14:36:08 +02:00
Rework operator type errors (#14429)
# Description This PR adds two new `ParseError` and `ShellError` cases for type errors relating to operators. - `OperatorUnsupportedType` is used when a type is not supported by an operator in any way, shape, or form. E.g., `+` does not support `bool`. - `OperatorIncompatibleTypes` is used when a operator is used with types it supports, but the combination of types provided cannot be used together. E.g., `filesize + duration` is not a valid combination. The other preexisting error cases related to operators have been removed and replaced with the new ones above. Namely: - `ShellError::OperatorMismatch` - `ShellError::UnsupportedOperator` - `ParseError::UnsupportedOperationLHS` - `ParseError::UnsupportedOperationRHS` - `ParseError::UnsupportedOperationTernary` # User-Facing Changes - `help operators` now lists the precedence of `not` as 55 instead of 0 (above the other boolean operators). Fixes #13675. - `math median` and `math mode` now ignore NaN values so that `[NaN NaN] | math median` and `[NaN NaN] | math mode` no longer trigger a type error. Instead, it's now an empty input error. Fixing this in earnest can be left for a future PR. - Comparisons with `nan` now return false instead of causing an error. E.g., `1 == nan` is now `false`. - All the operator type errors have been standardized and reworked. In particular, they can now have a help message, which is currently used for types errors relating to `++`. ```nu [1] ++ 2 ``` ``` Error: nu::parser::operator_unsupported_type × The '++' operator does not work on values of type 'int'. ╭─[entry #1:1:5] 1 │ [1] ++ 2 · ─┬ ┬ · │ ╰── int · ╰── does not support 'int' ╰──── help: if you meant to append a value to a list or a record to a table, use the `append` command or wrap the value in a list. For example: `$list ++ $value` should be `$list ++ [$value]` or `$list | append $value`. ```
This commit is contained in:
@ -1,11 +1,9 @@
|
||||
use crate::{ShellError, Span};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Display;
|
||||
|
||||
use super::{Expr, Expression};
|
||||
use crate::{ShellError, Span};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Comparison {
|
||||
Equal,
|
||||
NotEqual,
|
||||
@ -23,26 +21,90 @@ pub enum Comparison {
|
||||
EndsWith,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
impl Comparison {
|
||||
pub const fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Equal => "==",
|
||||
Self::NotEqual => "!=",
|
||||
Self::LessThan => "<",
|
||||
Self::GreaterThan => ">",
|
||||
Self::LessThanOrEqual => "<=",
|
||||
Self::GreaterThanOrEqual => ">=",
|
||||
Self::RegexMatch => "=~",
|
||||
Self::NotRegexMatch => "!~",
|
||||
Self::In => "in",
|
||||
Self::NotIn => "not-in",
|
||||
Self::Has => "has",
|
||||
Self::NotHas => "not-has",
|
||||
Self::StartsWith => "starts-with",
|
||||
Self::EndsWith => "ends-with",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Comparison {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Math {
|
||||
Plus,
|
||||
Concat,
|
||||
Minus,
|
||||
Add,
|
||||
Subtract,
|
||||
Multiply,
|
||||
Divide,
|
||||
FloorDivide,
|
||||
Modulo,
|
||||
FloorDivision,
|
||||
Pow,
|
||||
Concatenate,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
impl Math {
|
||||
pub const fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Add => "+",
|
||||
Self::Subtract => "-",
|
||||
Self::Multiply => "*",
|
||||
Self::Divide => "/",
|
||||
Self::FloorDivide => "//",
|
||||
Self::Modulo => "mod",
|
||||
Self::Pow => "**",
|
||||
Self::Concatenate => "++",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Math {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Boolean {
|
||||
And,
|
||||
Or,
|
||||
Xor,
|
||||
And,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
impl Boolean {
|
||||
pub const fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Or => "or",
|
||||
Self::Xor => "xor",
|
||||
Self::And => "and",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Boolean {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Bits {
|
||||
BitOr,
|
||||
BitXor,
|
||||
@ -51,17 +113,54 @@ pub enum Bits {
|
||||
ShiftRight,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Assignment {
|
||||
Assign,
|
||||
PlusAssign,
|
||||
ConcatAssign,
|
||||
MinusAssign,
|
||||
MultiplyAssign,
|
||||
DivideAssign,
|
||||
impl Bits {
|
||||
pub const fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::BitOr => "bit-or",
|
||||
Self::BitXor => "bit-xor",
|
||||
Self::BitAnd => "bit-and",
|
||||
Self::ShiftLeft => "bit-shl",
|
||||
Self::ShiftRight => "bit-shr",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
impl fmt::Display for Bits {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Assignment {
|
||||
Assign,
|
||||
AddAssign,
|
||||
SubtractAssign,
|
||||
MultiplyAssign,
|
||||
DivideAssign,
|
||||
ConcatenateAssign,
|
||||
}
|
||||
|
||||
impl Assignment {
|
||||
pub const fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Assign => "=",
|
||||
Self::AddAssign => "+=",
|
||||
Self::SubtractAssign => "-=",
|
||||
Self::MultiplyAssign => "*=",
|
||||
Self::DivideAssign => "/=",
|
||||
Self::ConcatenateAssign => "++=",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Assignment {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum Operator {
|
||||
Comparison(Comparison),
|
||||
Math(Math),
|
||||
@ -71,14 +170,24 @@ pub enum Operator {
|
||||
}
|
||||
|
||||
impl Operator {
|
||||
pub fn precedence(&self) -> u8 {
|
||||
pub const fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Comparison(comparison) => comparison.as_str(),
|
||||
Self::Math(math) => math.as_str(),
|
||||
Self::Boolean(boolean) => boolean.as_str(),
|
||||
Self::Bits(bits) => bits.as_str(),
|
||||
Self::Assignment(assignment) => assignment.as_str(),
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn precedence(&self) -> u8 {
|
||||
match self {
|
||||
Self::Math(Math::Pow) => 100,
|
||||
Self::Math(Math::Multiply)
|
||||
| Self::Math(Math::Divide)
|
||||
| Self::Math(Math::Modulo)
|
||||
| Self::Math(Math::FloorDivision) => 95,
|
||||
Self::Math(Math::Plus) | Self::Math(Math::Minus) => 90,
|
||||
| Self::Math(Math::FloorDivide) => 95,
|
||||
Self::Math(Math::Add) | Self::Math(Math::Subtract) => 90,
|
||||
Self::Bits(Bits::ShiftLeft) | Self::Bits(Bits::ShiftRight) => 85,
|
||||
Self::Comparison(Comparison::NotRegexMatch)
|
||||
| Self::Comparison(Comparison::RegexMatch)
|
||||
@ -94,7 +203,7 @@ impl Operator {
|
||||
| Self::Comparison(Comparison::NotIn)
|
||||
| Self::Comparison(Comparison::Has)
|
||||
| Self::Comparison(Comparison::NotHas)
|
||||
| Self::Math(Math::Concat) => 80,
|
||||
| Self::Math(Math::Concatenate) => 80,
|
||||
Self::Bits(Bits::BitAnd) => 75,
|
||||
Self::Bits(Bits::BitXor) => 70,
|
||||
Self::Bits(Bits::BitOr) => 60,
|
||||
@ -106,46 +215,9 @@ impl Operator {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Operator {
|
||||
impl fmt::Display for Operator {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Operator::Assignment(Assignment::Assign) => write!(f, "="),
|
||||
Operator::Assignment(Assignment::PlusAssign) => write!(f, "+="),
|
||||
Operator::Assignment(Assignment::ConcatAssign) => write!(f, "++="),
|
||||
Operator::Assignment(Assignment::MinusAssign) => write!(f, "-="),
|
||||
Operator::Assignment(Assignment::MultiplyAssign) => write!(f, "*="),
|
||||
Operator::Assignment(Assignment::DivideAssign) => write!(f, "/="),
|
||||
Operator::Comparison(Comparison::Equal) => write!(f, "=="),
|
||||
Operator::Comparison(Comparison::NotEqual) => write!(f, "!="),
|
||||
Operator::Comparison(Comparison::LessThan) => write!(f, "<"),
|
||||
Operator::Comparison(Comparison::GreaterThan) => write!(f, ">"),
|
||||
Operator::Comparison(Comparison::RegexMatch) => write!(f, "=~ or like"),
|
||||
Operator::Comparison(Comparison::NotRegexMatch) => write!(f, "!~ or not-like"),
|
||||
Operator::Comparison(Comparison::LessThanOrEqual) => write!(f, "<="),
|
||||
Operator::Comparison(Comparison::GreaterThanOrEqual) => write!(f, ">="),
|
||||
Operator::Comparison(Comparison::StartsWith) => write!(f, "starts-with"),
|
||||
Operator::Comparison(Comparison::EndsWith) => write!(f, "ends-with"),
|
||||
Operator::Comparison(Comparison::In) => write!(f, "in"),
|
||||
Operator::Comparison(Comparison::NotIn) => write!(f, "not-in"),
|
||||
Operator::Comparison(Comparison::Has) => write!(f, "has"),
|
||||
Operator::Comparison(Comparison::NotHas) => write!(f, "not-has"),
|
||||
Operator::Math(Math::Plus) => write!(f, "+"),
|
||||
Operator::Math(Math::Concat) => write!(f, "++"),
|
||||
Operator::Math(Math::Minus) => write!(f, "-"),
|
||||
Operator::Math(Math::Multiply) => write!(f, "*"),
|
||||
Operator::Math(Math::Divide) => write!(f, "/"),
|
||||
Operator::Math(Math::Modulo) => write!(f, "mod"),
|
||||
Operator::Math(Math::FloorDivision) => write!(f, "//"),
|
||||
Operator::Math(Math::Pow) => write!(f, "**"),
|
||||
Operator::Boolean(Boolean::And) => write!(f, "and"),
|
||||
Operator::Boolean(Boolean::Or) => write!(f, "or"),
|
||||
Operator::Boolean(Boolean::Xor) => write!(f, "xor"),
|
||||
Operator::Bits(Bits::BitOr) => write!(f, "bit-or"),
|
||||
Operator::Bits(Bits::BitXor) => write!(f, "bit-xor"),
|
||||
Operator::Bits(Bits::BitAnd) => write!(f, "bit-and"),
|
||||
Operator::Bits(Bits::ShiftLeft) => write!(f, "bit-shl"),
|
||||
Operator::Bits(Bits::ShiftRight) => write!(f, "bit-shr"),
|
||||
}
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +234,7 @@ pub struct RangeOperator {
|
||||
pub next_op_span: Span,
|
||||
}
|
||||
|
||||
impl Display for RangeOperator {
|
||||
impl fmt::Display for RangeOperator {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self.inclusion {
|
||||
RangeInclusion::Inclusive => write!(f, ".."),
|
||||
@ -176,7 +248,7 @@ pub fn eval_operator(op: &Expression) -> Result<Operator, ShellError> {
|
||||
Expression {
|
||||
expr: Expr::Operator(operator),
|
||||
..
|
||||
} => Ok(operator.clone()),
|
||||
} => Ok(*operator),
|
||||
Expression { span, expr, .. } => Err(ShellError::UnknownOperator {
|
||||
op_token: format!("{expr:?}"),
|
||||
span: *span,
|
||||
|
@ -1,11 +1,10 @@
|
||||
use crate::{ast::RedirectionSource, did_you_mean, Span, Type};
|
||||
use miette::Diagnostic;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
fmt::Display,
|
||||
str::{from_utf8, Utf8Error},
|
||||
};
|
||||
|
||||
use crate::{ast::RedirectionSource, did_you_mean, Span, Type};
|
||||
use miette::Diagnostic;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Clone, Debug, Error, Diagnostic, Serialize, Deserialize)]
|
||||
@ -115,38 +114,36 @@ pub enum ParseError {
|
||||
span: Span,
|
||||
},
|
||||
|
||||
#[error("{0} is not supported on values of type {3}")]
|
||||
#[diagnostic(code(nu::parser::unsupported_operation))]
|
||||
UnsupportedOperationLHS(
|
||||
String,
|
||||
#[label = "doesn't support this value"] Span,
|
||||
#[label("{3}")] Span,
|
||||
Type,
|
||||
),
|
||||
/// One or more of the values have types not supported by the operator.
|
||||
#[error("The '{op}' operator does not work on values of type '{unsupported}'.")]
|
||||
#[diagnostic(code(nu::parser::operator_unsupported_type))]
|
||||
OperatorUnsupportedType {
|
||||
op: &'static str,
|
||||
unsupported: Type,
|
||||
#[label = "does not support '{unsupported}'"]
|
||||
op_span: Span,
|
||||
#[label("{unsupported}")]
|
||||
unsupported_span: Span,
|
||||
#[help]
|
||||
help: Option<&'static str>,
|
||||
},
|
||||
|
||||
#[error("{0} is not supported between {3} and {5}.")]
|
||||
#[diagnostic(code(nu::parser::unsupported_operation))]
|
||||
UnsupportedOperationRHS(
|
||||
String,
|
||||
#[label = "doesn't support these values"] Span,
|
||||
#[label("{3}")] Span,
|
||||
Type,
|
||||
#[label("{5}")] Span,
|
||||
Type,
|
||||
),
|
||||
|
||||
#[error("{0} is not supported between {3}, {5}, and {7}.")]
|
||||
#[diagnostic(code(nu::parser::unsupported_operation))]
|
||||
UnsupportedOperationTernary(
|
||||
String,
|
||||
#[label = "doesn't support these values"] Span,
|
||||
#[label("{3}")] Span,
|
||||
Type,
|
||||
#[label("{5}")] Span,
|
||||
Type,
|
||||
#[label("{7}")] Span,
|
||||
Type,
|
||||
),
|
||||
/// The operator supports the types of both values, but not the specific combination of their types.
|
||||
#[error("Types '{lhs}' and '{rhs}' are not compatible for the '{op}' operator.")]
|
||||
#[diagnostic(code(nu::parser::operator_incompatible_types))]
|
||||
OperatorIncompatibleTypes {
|
||||
op: &'static str,
|
||||
lhs: Type,
|
||||
rhs: Type,
|
||||
#[label = "does not operate between '{lhs}' and '{rhs}'"]
|
||||
op_span: Span,
|
||||
#[label("{lhs}")]
|
||||
lhs_span: Span,
|
||||
#[label("{rhs}")]
|
||||
rhs_span: Span,
|
||||
#[help]
|
||||
help: Option<&'static str>,
|
||||
},
|
||||
|
||||
#[error("Capture of mutable variable.")]
|
||||
#[diagnostic(code(nu::parser::expected_keyword))]
|
||||
@ -564,9 +561,8 @@ impl ParseError {
|
||||
ParseError::ExpectedWithStringMsg(_, s) => *s,
|
||||
ParseError::ExpectedWithDidYouMean(_, _, s) => *s,
|
||||
ParseError::Mismatch(_, _, s) => *s,
|
||||
ParseError::UnsupportedOperationLHS(_, _, s, _) => *s,
|
||||
ParseError::UnsupportedOperationRHS(_, _, _, _, s, _) => *s,
|
||||
ParseError::UnsupportedOperationTernary(_, _, _, _, _, _, s, _) => *s,
|
||||
ParseError::OperatorUnsupportedType { op_span, .. } => *op_span,
|
||||
ParseError::OperatorIncompatibleTypes { op_span, .. } => *op_span,
|
||||
ParseError::ExpectedKeyword(_, s) => *s,
|
||||
ParseError::UnexpectedKeyword(_, s) => *s,
|
||||
ParseError::CantAliasKeyword(_, s) => *s,
|
||||
|
@ -17,22 +17,35 @@ pub mod location;
|
||||
/// and pass it into an error viewer to display to the user.
|
||||
#[derive(Debug, Clone, Error, Diagnostic, PartialEq)]
|
||||
pub enum ShellError {
|
||||
/// An operator received two arguments of incompatible types.
|
||||
///
|
||||
/// ## Resolution
|
||||
///
|
||||
/// Check each argument's type and convert one or both as needed.
|
||||
#[error("Type mismatch during operation.")]
|
||||
#[diagnostic(code(nu::shell::type_mismatch))]
|
||||
OperatorMismatch {
|
||||
#[label = "type mismatch for operator"]
|
||||
/// One or more of the values have types not supported by the operator.
|
||||
#[error("The '{op}' operator does not work on values of type '{unsupported}'.")]
|
||||
#[diagnostic(code(nu::shell::operator_unsupported_type))]
|
||||
OperatorUnsupportedType {
|
||||
op: Operator,
|
||||
unsupported: Type,
|
||||
#[label = "does not support '{unsupported}'"]
|
||||
op_span: Span,
|
||||
lhs_ty: String,
|
||||
#[label("{lhs_ty}")]
|
||||
#[label("{unsupported}")]
|
||||
unsupported_span: Span,
|
||||
#[help]
|
||||
help: Option<&'static str>,
|
||||
},
|
||||
|
||||
/// The operator supports the types of both values, but not the specific combination of their types.
|
||||
#[error("Types '{lhs}' and '{rhs}' are not compatible for the '{op}' operator.")]
|
||||
#[diagnostic(code(nu::shell::operator_incompatible_types))]
|
||||
OperatorIncompatibleTypes {
|
||||
op: Operator,
|
||||
lhs: Type,
|
||||
rhs: Type,
|
||||
#[label = "does not operate between '{lhs}' and '{rhs}'"]
|
||||
op_span: Span,
|
||||
#[label("{lhs}")]
|
||||
lhs_span: Span,
|
||||
rhs_ty: String,
|
||||
#[label("{rhs_ty}")]
|
||||
#[label("{rhs}")]
|
||||
rhs_span: Span,
|
||||
#[help]
|
||||
help: Option<&'static str>,
|
||||
},
|
||||
|
||||
/// An arithmetic operation's resulting value overflowed its possible size.
|
||||
@ -156,20 +169,6 @@ pub enum ShellError {
|
||||
call_span: Span,
|
||||
},
|
||||
|
||||
/// This value cannot be used with this operator.
|
||||
///
|
||||
/// ## Resolution
|
||||
///
|
||||
/// Not all values, for example custom values, can be used with all operators. Either
|
||||
/// implement support for the operator on this type, or convert the type to a supported one.
|
||||
#[error("Unsupported operator: {operator}.")]
|
||||
#[diagnostic(code(nu::shell::unsupported_operator))]
|
||||
UnsupportedOperator {
|
||||
operator: Operator,
|
||||
#[label = "unsupported operator"]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
/// Invalid assignment left-hand side
|
||||
///
|
||||
/// ## Resolution
|
||||
|
@ -235,14 +235,14 @@ pub trait Eval {
|
||||
let rhs = Self::eval::<D>(state, mut_state, rhs)?;
|
||||
|
||||
match math {
|
||||
Math::Plus => lhs.add(op_span, &rhs, expr_span),
|
||||
Math::Minus => lhs.sub(op_span, &rhs, expr_span),
|
||||
Math::Add => lhs.add(op_span, &rhs, expr_span),
|
||||
Math::Subtract => lhs.sub(op_span, &rhs, expr_span),
|
||||
Math::Multiply => lhs.mul(op_span, &rhs, expr_span),
|
||||
Math::Divide => lhs.div(op_span, &rhs, expr_span),
|
||||
Math::Concat => lhs.concat(op_span, &rhs, expr_span),
|
||||
Math::FloorDivide => lhs.floor_div(op_span, &rhs, expr_span),
|
||||
Math::Modulo => lhs.modulo(op_span, &rhs, expr_span),
|
||||
Math::FloorDivision => lhs.floor_div(op_span, &rhs, expr_span),
|
||||
Math::Pow => lhs.pow(op_span, &rhs, expr_span),
|
||||
Math::Concatenate => lhs.concat(op_span, &rhs, expr_span),
|
||||
}
|
||||
}
|
||||
Operator::Comparison(comparison) => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::{cmp::Ordering, fmt};
|
||||
|
||||
use crate::{ast::Operator, ShellError, Span, Value};
|
||||
use crate::{ast::Operator, ShellError, Span, Type, Value};
|
||||
|
||||
/// Trait definition for a custom [`Value`](crate::Value) type
|
||||
#[typetag::serde(tag = "type")]
|
||||
@ -68,7 +68,7 @@ pub trait CustomValue: fmt::Debug + Send + Sync {
|
||||
///
|
||||
/// The Operator enum is used to indicate the expected operation.
|
||||
///
|
||||
/// Default impl raises [`ShellError::UnsupportedOperator`].
|
||||
/// Default impl raises [`ShellError::OperatorUnsupportedType`].
|
||||
fn operation(
|
||||
&self,
|
||||
lhs_span: Span,
|
||||
@ -77,7 +77,13 @@ pub trait CustomValue: fmt::Debug + Send + Sync {
|
||||
right: &Value,
|
||||
) -> Result<Value, ShellError> {
|
||||
let _ = (lhs_span, right);
|
||||
Err(ShellError::UnsupportedOperator { operator, span: op })
|
||||
Err(ShellError::OperatorUnsupportedType {
|
||||
op: operator,
|
||||
unsupported: Type::Custom(self.type_name().into()),
|
||||
op_span: op,
|
||||
unsupported_span: lhs_span,
|
||||
help: None,
|
||||
})
|
||||
}
|
||||
|
||||
/// For custom values in plugins: return `true` here if you would like to be notified when all
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user