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> {
|
||||
let call = call.assert_ast_call()?;
|
||||
let cond = call.positional_nth(0).expect("checked through parser");
|
||||
let then_block = call
|
||||
.positional_nth(1)
|
||||
.expect("checked through parser")
|
||||
let then_expr = call.positional_nth(1).expect("checked through parser");
|
||||
let then_block = then_expr
|
||||
.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);
|
||||
|
||||
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
|
||||
Type::Any
|
||||
| Type::Block
|
||||
| Type::CellPath
|
||||
| Type::Closure
|
||||
| Type::Custom(_)
|
||||
|
@ -2487,7 +2487,7 @@ pub fn parse_module(
|
||||
working_set,
|
||||
Expr::Block(block_id),
|
||||
block_expr_span,
|
||||
Type::Any,
|
||||
Type::Block,
|
||||
);
|
||||
|
||||
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));
|
||||
|
||||
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 {
|
||||
|
@ -88,6 +88,7 @@ pub fn type_compatible(lhs: &Type, rhs: &Type) -> bool {
|
||||
(Type::Int, Type::Number) => true,
|
||||
(Type::Number, Type::Float) => true,
|
||||
(Type::Float, Type::Number) => true,
|
||||
(Type::Closure, Type::Block) => true,
|
||||
(Type::Any, _) => true,
|
||||
(_, Type::Any) => true,
|
||||
(Type::Record(lhs), Type::Record(rhs)) | (Type::Table(lhs), Type::Table(rhs)) => {
|
||||
|
@ -143,7 +143,7 @@ impl SyntaxShape {
|
||||
|
||||
match self {
|
||||
SyntaxShape::Any => Type::Any,
|
||||
SyntaxShape::Block => Type::Any,
|
||||
SyntaxShape::Block => Type::Block,
|
||||
SyntaxShape::Closure(_) => Type::Closure,
|
||||
SyntaxShape::Binary => Type::Binary,
|
||||
SyntaxShape::CellPath => Type::Any,
|
||||
|
@ -9,6 +9,7 @@ use strum_macros::EnumIter;
|
||||
pub enum Type {
|
||||
Any,
|
||||
Binary,
|
||||
Block,
|
||||
Bool,
|
||||
CellPath,
|
||||
Closure,
|
||||
@ -110,6 +111,7 @@ impl Type {
|
||||
Type::Range => SyntaxShape::Range,
|
||||
Type::Bool => SyntaxShape::Boolean,
|
||||
Type::String => SyntaxShape::String,
|
||||
Type::Block => SyntaxShape::Block, // FIXME needs more accuracy
|
||||
Type::Closure => SyntaxShape::Closure(None), // FIXME needs more accuracy
|
||||
Type::CellPath => SyntaxShape::CellPath,
|
||||
Type::Duration => SyntaxShape::Duration,
|
||||
@ -134,6 +136,7 @@ impl Type {
|
||||
match self {
|
||||
Type::Closure => String::from("closure"),
|
||||
Type::Bool => String::from("bool"),
|
||||
Type::Block => String::from("block"),
|
||||
Type::CellPath => String::from("cell-path"),
|
||||
Type::Date => String::from("datetime"),
|
||||
Type::Duration => String::from("duration"),
|
||||
@ -159,6 +162,7 @@ impl Type {
|
||||
impl Display for Type {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Type::Block => write!(f, "block"),
|
||||
Type::Closure => write!(f, "closure"),
|
||||
Type::Bool => write!(f, "bool"),
|
||||
Type::CellPath => write!(f, "cell-path"),
|
||||
|
@ -410,6 +410,15 @@ fn if_const() {
|
||||
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]
|
||||
fn const_glob_type() {
|
||||
let actual = nu!("const x: glob = 'aa'; $x | describe");
|
||||
|
Reference in New Issue
Block a user