mirror of
https://github.com/nushell/nushell.git
synced 2024-12-22 23:23:12 +01:00
raise ParseError if assign to a non-variable or non-mutable-variable (#14405)
# Description While reviewing #14388, I think we can make some improvement on parser. For the following code: ```nushell let a = 3 a = 10 # should be error $a = 10 # another error ``` I think they can raise `ParseError`, so nushell doesn't need to move forward compiling IR block. # User-Facing Changes ```nushell let a = 3 a = 10 ``` Will raise parse error instead of compile error. # Tests + Formatting Added 1 test.
This commit is contained in:
parent
dc9e8161d9
commit
817830940b
@ -148,3 +148,14 @@ fn def_should_not_mutate_mut() {
|
||||
assert!(actual.err.contains("capture of mutable variable"));
|
||||
assert!(!actual.status.success())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assign_to_non_mut_variable_raises_parse_error() {
|
||||
let actual = nu!("let x = 3; $x = 4");
|
||||
assert!(actual
|
||||
.err
|
||||
.contains("parser::assignment_requires_mutable_variable"));
|
||||
|
||||
let actual = nu!("mut x = 3; x = 5");
|
||||
assert!(actual.err.contains("parser::assignment_requires_variable"));
|
||||
}
|
||||
|
@ -4988,6 +4988,20 @@ pub fn parse_assignment_expression(
|
||||
|
||||
// Parse the lhs and operator as usual for a math expression
|
||||
let mut lhs = parse_expression(working_set, lhs_spans);
|
||||
// make sure that lhs is a mutable variable.
|
||||
match &lhs.expr {
|
||||
Expr::FullCellPath(p) => {
|
||||
if let Expr::Var(var_id) = p.head.expr {
|
||||
if var_id != nu_protocol::ENV_VARIABLE_ID
|
||||
&& !working_set.get_variable(var_id).mutable
|
||||
{
|
||||
working_set.error(ParseError::AssignmentRequiresMutableVar(lhs.span))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => working_set.error(ParseError::AssignmentRequiresVar(lhs.span)),
|
||||
}
|
||||
|
||||
let mut operator = parse_assignment_operator(working_set, op_span);
|
||||
|
||||
// Re-parse the right-hand side as a subexpression
|
||||
|
@ -515,6 +515,30 @@ pub enum ParseError {
|
||||
help("To spread arguments, the command needs to define a multi-positional parameter in its signature, such as ...rest")
|
||||
)]
|
||||
UnexpectedSpreadArg(String, #[label = "unexpected spread argument"] Span),
|
||||
|
||||
/// Invalid assignment left-hand side
|
||||
///
|
||||
/// ## Resolution
|
||||
///
|
||||
/// Assignment requires that you assign to a mutable variable or cell path.
|
||||
#[error("Assignment to an immutable variable.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::assignment_requires_mutable_variable),
|
||||
help("declare the variable with `mut`, or shadow it again with `let`")
|
||||
)]
|
||||
AssignmentRequiresMutableVar(#[label("needs to be a mutable variable")] Span),
|
||||
|
||||
/// Invalid assignment left-hand side
|
||||
///
|
||||
/// ## Resolution
|
||||
///
|
||||
/// Assignment requires that you assign to a variable or variable cell path.
|
||||
#[error("Assignment operations require a variable.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::assignment_requires_variable),
|
||||
help("try assigning to a variable or a cell path of a variable")
|
||||
)]
|
||||
AssignmentRequiresVar(#[label("needs to be a variable")] Span),
|
||||
}
|
||||
|
||||
impl ParseError {
|
||||
@ -603,6 +627,8 @@ impl ParseError {
|
||||
ParseError::RedirectingBuiltinCommand(_, s, _) => *s,
|
||||
ParseError::UnexpectedSpreadArg(_, s) => *s,
|
||||
ParseError::ExtraTokensAfterClosingDelimiter(s) => *s,
|
||||
ParseError::AssignmentRequiresVar(s) => *s,
|
||||
ParseError::AssignmentRequiresMutableVar(s) => *s,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user