mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 22:57:58 +02:00
Fix parse-time pipeline type checking to support multiple output types for same input type (#16111)
# Description Fixes #15485 This PR changes pipeline checking to keep track of all possible output types instead of only first type matching input type which appears in the input/output types. For example, in this command: ```nushell def foo []: [int -> string, int -> record] { # ... } ``` An `int` input to the command may result in a string or a record to be output. Before this PR, Nushell would always assume that an `int` input would cause a `string` output because it's the first matching input/output type pair. This would cause issues during type checking where the parser would incorrectly determine the output type. After this PR, Nushell considers the command to output either a string or a record. # User-Facing Changes * Parse-time pipeline type checking now properly supports commands with multiple pipeline output types for the same pipeline input type # Tests + Formatting Added a couple tests # After Submitting N/A --------- Co-authored-by: Bahex <Bahex@users.noreply.github.com>
This commit is contained in:
@ -6,6 +6,7 @@ use nu_protocol::{
|
||||
PipelineData, PipelineMetadata, PositionalArg, Range, Record, RegId, ShellError, Signals,
|
||||
Signature, Span, Spanned, Type, Value, VarId,
|
||||
ast::{Bits, Block, Boolean, CellPath, Comparison, Math, Operator},
|
||||
combined_type_string,
|
||||
debugger::DebugContext,
|
||||
engine::{
|
||||
Argument, Closure, EngineState, ErrorHandler, Matcher, Redirection, Stack, StateWorkingSet,
|
||||
@ -1315,37 +1316,21 @@ fn check_input_types(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut input_types = io_types
|
||||
.iter()
|
||||
.map(|(input, _)| input.to_string())
|
||||
.collect::<Vec<String>>();
|
||||
let input_types: Vec<Type> = io_types.iter().map(|(input, _)| input.clone()).collect();
|
||||
let expected_string = combined_type_string(&input_types, "and");
|
||||
|
||||
let expected_string = match input_types.len() {
|
||||
0 => {
|
||||
return Err(ShellError::NushellFailed {
|
||||
msg: "Command input type strings is empty, despite being non-zero earlier"
|
||||
.to_string(),
|
||||
});
|
||||
}
|
||||
1 => input_types.swap_remove(0),
|
||||
2 => input_types.join(" and "),
|
||||
_ => {
|
||||
input_types
|
||||
.last_mut()
|
||||
.expect("Vector with length >2 has no elements")
|
||||
.insert_str(0, "and ");
|
||||
input_types.join(", ")
|
||||
}
|
||||
};
|
||||
|
||||
match input {
|
||||
PipelineData::Empty => Err(ShellError::PipelineEmpty { dst_span: head }),
|
||||
_ => Err(ShellError::OnlySupportsThisInputType {
|
||||
match (input, expected_string) {
|
||||
(PipelineData::Empty, _) => Err(ShellError::PipelineEmpty { dst_span: head }),
|
||||
(_, Some(expected_string)) => Err(ShellError::OnlySupportsThisInputType {
|
||||
exp_input_type: expected_string,
|
||||
wrong_type: input.get_type().to_string(),
|
||||
dst_span: head,
|
||||
src_span: input.span().unwrap_or(Span::unknown()),
|
||||
}),
|
||||
// expected_string didn't generate properly, so we can't show the proper error
|
||||
(_, None) => Err(ShellError::NushellFailed {
|
||||
msg: "Command input type strings is empty, despite being non-zero earlier".to_string(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user