diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index 7fa74c7826..cb2cb84984 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -72,9 +72,8 @@ pub fn eval_call( if let Some(arg) = call.positional_nth(param_idx) { let result = eval_expression(engine_state, caller_stack, arg)?; callee_stack.add_var(var_id, result); - } else if let Some(arg) = ¶m.default_value { - let result = eval_expression(engine_state, caller_stack, arg)?; - callee_stack.add_var(var_id, result); + } else if let Some(value) = ¶m.default_value { + callee_stack.add_var(var_id, value.to_owned()); } else { callee_stack.add_var(var_id, Value::nothing(call.head)); } diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index 3fb0dcf5fb..9f4127d128 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -3735,8 +3735,19 @@ pub fn parse_signature_helper(working_set: &mut StateWorkingSet, span: Span) -> } } } + + *default_value = if let Ok(constant) = + eval_constant(working_set, &expression) + { + Some(constant) + } else { + working_set.error(ParseError::NonConstantDefaultValue( + expression.span, + )); + None + }; + *shape = expression.ty.to_shape(); - *default_value = Some(expression); *required = false; } Arg::RestPositional(..) => { diff --git a/crates/nu-protocol/src/parse_error.rs b/crates/nu-protocol/src/parse_error.rs index 935e272c21..2696e8a16e 100644 --- a/crates/nu-protocol/src/parse_error.rs +++ b/crates/nu-protocol/src/parse_error.rs @@ -338,6 +338,10 @@ pub enum ParseError { #[label = "parameter {0} needs to be '{1}' instead of '{2}'"] Span, ), + #[error("Default values should be constant expressions.")] + #[diagnostic(code(nu::parser::non_constant_default_value))] + NonConstantDefaultValue(#[label = "expected a constant value"] Span), + #[error("Extra columns.")] #[diagnostic(code(nu::parser::extra_columns))] ExtraColumns( @@ -472,6 +476,7 @@ impl ParseError { ParseError::IncompleteParser(s) => *s, ParseError::RestNeedsName(s) => *s, ParseError::ParameterMismatchType(_, _, _, s) => *s, + ParseError::NonConstantDefaultValue(s) => *s, ParseError::ExtraColumns(_, s) => *s, ParseError::MissingColumns(_, s) => *s, ParseError::AssignmentMismatch(_, _, s) => *s, diff --git a/crates/nu-protocol/src/signature.rs b/crates/nu-protocol/src/signature.rs index 491ba06ada..8e2e35883f 100644 --- a/crates/nu-protocol/src/signature.rs +++ b/crates/nu-protocol/src/signature.rs @@ -11,6 +11,7 @@ use crate::PipelineData; use crate::ShellError; use crate::SyntaxShape; use crate::Type; +use crate::Value; use crate::VarId; use std::fmt::Write; @@ -35,7 +36,7 @@ pub struct PositionalArg { // For custom commands pub var_id: Option, - pub default_value: Option, + pub default_value: Option, } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] diff --git a/src/tests/test_engine.rs b/src/tests/test_engine.rs index df9b03aa9b..a8cfd24d8c 100644 --- a/src/tests/test_engine.rs +++ b/src/tests/test_engine.rs @@ -323,8 +323,16 @@ fn default_value12() -> TestResult { } #[test] -fn default_value_expression() -> TestResult { - run_test(r#"def foo [x = ("foo" | str length)] { $x }; foo"#, "3") +fn default_value_constant() -> TestResult { + run_test(r#"def foo [x = "foo"] { $x }; foo"#, "foo") +} + +#[test] +fn default_value_not_constant() -> TestResult { + fail_test( + r#"def foo [x = ("foo" | str length)] { $x }; foo"#, + "expected a constant", + ) } #[test]