mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 07:46:01 +02:00
fix: panic of if command as a constant expr by bringing back Type::Block
(#16122)
Fixes #16110. Alternative to #16120 # Description # User-Facing Changes no more panic # Tests + Formatting +1 # After Submitting
This commit is contained in:
@ -60,11 +60,13 @@ impl Command for If {
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let call = call.assert_ast_call()?;
|
let call = call.assert_ast_call()?;
|
||||||
let cond = call.positional_nth(0).expect("checked through parser");
|
let cond = call.positional_nth(0).expect("checked through parser");
|
||||||
let then_block = call
|
let then_expr = call.positional_nth(1).expect("checked through parser");
|
||||||
.positional_nth(1)
|
let then_block = then_expr
|
||||||
.expect("checked through parser")
|
|
||||||
.as_block()
|
.as_block()
|
||||||
.expect("internal error: missing block");
|
.ok_or_else(|| ShellError::TypeMismatch {
|
||||||
|
err_message: "expected block".into(),
|
||||||
|
span: then_expr.span,
|
||||||
|
})?;
|
||||||
let else_case = call.positional_nth(2);
|
let else_case = call.positional_nth(2);
|
||||||
|
|
||||||
if eval_constant(working_set, cond)?.as_bool()? {
|
if eval_constant(working_set, cond)?.as_bool()? {
|
||||||
|
@ -353,6 +353,7 @@ fn nu_value_to_sqlite_type(val: &Value) -> Result<&'static str, ShellError> {
|
|||||||
|
|
||||||
// intentionally enumerated so that any future types get handled
|
// intentionally enumerated so that any future types get handled
|
||||||
Type::Any
|
Type::Any
|
||||||
|
| Type::Block
|
||||||
| Type::CellPath
|
| Type::CellPath
|
||||||
| Type::Closure
|
| Type::Closure
|
||||||
| Type::Custom(_)
|
| Type::Custom(_)
|
||||||
|
@ -2487,7 +2487,7 @@ pub fn parse_module(
|
|||||||
working_set,
|
working_set,
|
||||||
Expr::Block(block_id),
|
Expr::Block(block_id),
|
||||||
block_expr_span,
|
block_expr_span,
|
||||||
Type::Any,
|
Type::Block,
|
||||||
);
|
);
|
||||||
|
|
||||||
let module_decl_id = working_set
|
let module_decl_id = working_set
|
||||||
|
@ -4768,7 +4768,7 @@ pub fn parse_block_expression(working_set: &mut StateWorkingSet, span: Span) ->
|
|||||||
|
|
||||||
let block_id = working_set.add_block(Arc::new(output));
|
let block_id = working_set.add_block(Arc::new(output));
|
||||||
|
|
||||||
Expression::new(working_set, Expr::Block(block_id), span, Type::Any)
|
Expression::new(working_set, Expr::Block(block_id), span, Type::Block)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_match_block_expression(working_set: &mut StateWorkingSet, span: Span) -> Expression {
|
pub fn parse_match_block_expression(working_set: &mut StateWorkingSet, span: Span) -> Expression {
|
||||||
|
@ -88,6 +88,7 @@ pub fn type_compatible(lhs: &Type, rhs: &Type) -> bool {
|
|||||||
(Type::Int, Type::Number) => true,
|
(Type::Int, Type::Number) => true,
|
||||||
(Type::Number, Type::Float) => true,
|
(Type::Number, Type::Float) => true,
|
||||||
(Type::Float, Type::Number) => true,
|
(Type::Float, Type::Number) => true,
|
||||||
|
(Type::Closure, Type::Block) => true,
|
||||||
(Type::Any, _) => true,
|
(Type::Any, _) => true,
|
||||||
(_, Type::Any) => true,
|
(_, Type::Any) => true,
|
||||||
(Type::Record(lhs), Type::Record(rhs)) | (Type::Table(lhs), Type::Table(rhs)) => {
|
(Type::Record(lhs), Type::Record(rhs)) | (Type::Table(lhs), Type::Table(rhs)) => {
|
||||||
|
@ -143,7 +143,7 @@ impl SyntaxShape {
|
|||||||
|
|
||||||
match self {
|
match self {
|
||||||
SyntaxShape::Any => Type::Any,
|
SyntaxShape::Any => Type::Any,
|
||||||
SyntaxShape::Block => Type::Any,
|
SyntaxShape::Block => Type::Block,
|
||||||
SyntaxShape::Closure(_) => Type::Closure,
|
SyntaxShape::Closure(_) => Type::Closure,
|
||||||
SyntaxShape::Binary => Type::Binary,
|
SyntaxShape::Binary => Type::Binary,
|
||||||
SyntaxShape::CellPath => Type::Any,
|
SyntaxShape::CellPath => Type::Any,
|
||||||
|
@ -9,6 +9,7 @@ use strum_macros::EnumIter;
|
|||||||
pub enum Type {
|
pub enum Type {
|
||||||
Any,
|
Any,
|
||||||
Binary,
|
Binary,
|
||||||
|
Block,
|
||||||
Bool,
|
Bool,
|
||||||
CellPath,
|
CellPath,
|
||||||
Closure,
|
Closure,
|
||||||
@ -110,6 +111,7 @@ impl Type {
|
|||||||
Type::Range => SyntaxShape::Range,
|
Type::Range => SyntaxShape::Range,
|
||||||
Type::Bool => SyntaxShape::Boolean,
|
Type::Bool => SyntaxShape::Boolean,
|
||||||
Type::String => SyntaxShape::String,
|
Type::String => SyntaxShape::String,
|
||||||
|
Type::Block => SyntaxShape::Block, // FIXME needs more accuracy
|
||||||
Type::Closure => SyntaxShape::Closure(None), // FIXME needs more accuracy
|
Type::Closure => SyntaxShape::Closure(None), // FIXME needs more accuracy
|
||||||
Type::CellPath => SyntaxShape::CellPath,
|
Type::CellPath => SyntaxShape::CellPath,
|
||||||
Type::Duration => SyntaxShape::Duration,
|
Type::Duration => SyntaxShape::Duration,
|
||||||
@ -134,6 +136,7 @@ impl Type {
|
|||||||
match self {
|
match self {
|
||||||
Type::Closure => String::from("closure"),
|
Type::Closure => String::from("closure"),
|
||||||
Type::Bool => String::from("bool"),
|
Type::Bool => String::from("bool"),
|
||||||
|
Type::Block => String::from("block"),
|
||||||
Type::CellPath => String::from("cell-path"),
|
Type::CellPath => String::from("cell-path"),
|
||||||
Type::Date => String::from("datetime"),
|
Type::Date => String::from("datetime"),
|
||||||
Type::Duration => String::from("duration"),
|
Type::Duration => String::from("duration"),
|
||||||
@ -159,6 +162,7 @@ impl Type {
|
|||||||
impl Display for Type {
|
impl Display for Type {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
|
Type::Block => write!(f, "block"),
|
||||||
Type::Closure => write!(f, "closure"),
|
Type::Closure => write!(f, "closure"),
|
||||||
Type::Bool => write!(f, "bool"),
|
Type::Bool => write!(f, "bool"),
|
||||||
Type::CellPath => write!(f, "cell-path"),
|
Type::CellPath => write!(f, "cell-path"),
|
||||||
|
@ -410,6 +410,15 @@ fn if_const() {
|
|||||||
assert_eq!(actual.out, "no!");
|
assert_eq!(actual.out, "no!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(&"const x = if true ()", "expected block, found nothing")]
|
||||||
|
#[case(&"const x = if true {foo: bar}", "expected block, found record")]
|
||||||
|
#[case(&"const x = if true {1: 2}", "expected block")]
|
||||||
|
fn if_const_error(#[case] inp: &str, #[case] expect: &str) {
|
||||||
|
let actual = nu!(inp);
|
||||||
|
assert!(actual.err.contains(expect));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn const_glob_type() {
|
fn const_glob_type() {
|
||||||
let actual = nu!("const x: glob = 'aa'; $x | describe");
|
let actual = nu!("const x: glob = 'aa'; $x | describe");
|
||||||
|
Reference in New Issue
Block a user