diff --git a/crates/nu-parser/src/parser.rs b/crates/nu-parser/src/parser.rs index ae1bb6a048..530ca63767 100644 --- a/crates/nu-parser/src/parser.rs +++ b/crates/nu-parser/src/parser.rs @@ -5439,6 +5439,17 @@ pub fn parse_pipeline( new_command.comments.extend_from_slice(&command.comments); new_command.parts.extend_from_slice(&command.parts); } + LiteElement::Redirection(span, ..) => { + working_set.error(ParseError::RedirectionInLetMut(*span, None)) + } + LiteElement::SeparateRedirection { out, err } => { + working_set.error(ParseError::RedirectionInLetMut( + out.0.min(err.0), + Some(out.0.max(err.0)), + )) + } + LiteElement::SameTargetRedirection { redirection, .. } => working_set + .error(ParseError::RedirectionInLetMut(redirection.0, None)), _ => panic!("unsupported"), } } diff --git a/crates/nu-parser/tests/test_parser.rs b/crates/nu-parser/tests/test_parser.rs index 8278f702ab..901f339844 100644 --- a/crates/nu-parser/tests/test_parser.rs +++ b/crates/nu-parser/tests/test_parser.rs @@ -781,6 +781,30 @@ fn test_nothing_comparison_eq() { ) )) } +#[rstest] +#[case(b"let a = 1 err> /dev/null", "RedirectionInLetMut")] +#[case(b"let a = 1 out> /dev/null", "RedirectionInLetMut")] +#[case(b"mut a = 1 err> /dev/null", "RedirectionInLetMut")] +#[case(b"mut a = 1 out> /dev/null", "RedirectionInLetMut")] +// This two cases cause AssignInPipeline instead of RedirectionInLetMut +#[case(b"let a = 1 out+err> /dev/null", "AssignInPipeline")] +#[case(b"mut a = 1 out+err> /dev/null", "AssignInPipeline")] +fn test_redirection_with_letmut(#[case] phase: &[u8], #[case] expected: &str) { + let engine_state = EngineState::new(); + let mut working_set = StateWorkingSet::new(&engine_state); + let _block = parse(&mut working_set, None, phase, true); + match expected { + "RedirectionInLetMut" => assert!(matches!( + working_set.parse_errors.first(), + Some(ParseError::RedirectionInLetMut(_, _)) + )), + "AssignInPipeline" => assert!(matches!( + working_set.parse_errors.first(), + Some(ParseError::AssignInPipeline(_, _, _, _)) + )), + _ => panic!("unexpected pattern"), + } +} #[test] fn test_nothing_comparison_neq() { diff --git a/crates/nu-protocol/src/parse_error.rs b/crates/nu-protocol/src/parse_error.rs index 14e2939e16..95f1e665eb 100644 --- a/crates/nu-protocol/src/parse_error.rs +++ b/crates/nu-protocol/src/parse_error.rs @@ -466,6 +466,13 @@ pub enum ParseError { #[label("{label}")] span: Span, }, + + #[error("Redirection can not be used with let/mut.")] + #[diagnostic()] + RedirectionInLetMut( + #[label("Not allowed here")] Span, + #[label("...and here")] Option, + ), } impl ParseError { @@ -550,6 +557,7 @@ impl ParseError { ParseError::UnknownOperator(_, _, s) => *s, ParseError::InvalidLiteral(_, _, s) => *s, ParseError::LabeledErrorWithHelp { span: s, .. } => *s, + ParseError::RedirectionInLetMut(s, _) => *s, } } }