diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index b405e3ed31..89fe9a7a91 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -42,11 +42,17 @@ pub fn eval_call( let mut callee_stack = caller_stack.gather_captures(engine_state, &block.captures); - for (param_idx, param) in decl + for (param_idx, (param, required)) in decl .signature() .required_positional .iter() - .chain(decl.signature().optional_positional.iter()) + .map(|p| (p, true)) + .chain( + decl.signature() + .optional_positional + .iter() + .map(|p| (p, false)), + ) .enumerate() { let var_id = param @@ -55,6 +61,14 @@ pub fn eval_call( if let Some(arg) = call.positional_nth(param_idx) { let result = eval_expression(engine_state, caller_stack, arg)?; + if required && !result.get_type().is_subtype(¶m.shape.to_type()) { + return Err(ShellError::CantConvert { + to_type: param.shape.to_type().to_string(), + from_type: result.get_type().to_string(), + span: result.span(), + help: None, + }); + } callee_stack.add_var(var_id, result); } else if let Some(value) = ¶m.default_value { callee_stack.add_var(var_id, value.to_owned()); diff --git a/crates/nu-protocol/src/ty.rs b/crates/nu-protocol/src/ty.rs index ac22e7e634..729d8c1eb7 100644 --- a/crates/nu-protocol/src/ty.rs +++ b/crates/nu-protocol/src/ty.rs @@ -40,11 +40,11 @@ impl Type { let is_subtype_collection = |this: &[(String, Type)], that: &[(String, Type)]| { if this.is_empty() || that.is_empty() { true - } else if this.len() > that.len() { + } else if this.len() < that.len() { false } else { - this.iter().all(|(col_x, ty_x)| { - if let Some((_, ty_y)) = that.iter().find(|(col_y, _)| col_x == col_y) { + that.iter().all(|(col_y, ty_y)| { + if let Some((_, ty_x)) = this.iter().find(|(col_x, _)| col_x == col_y) { ty_x.is_subtype(ty_y) } else { false diff --git a/crates/nu-std/std/log.nu b/crates/nu-std/std/log.nu index ebb7152970..5c56e9212a 100644 --- a/crates/nu-std/std/log.nu +++ b/crates/nu-std/std/log.nu @@ -185,6 +185,7 @@ export def critical [ --short (-s) # Whether to use a short prefix --format (-f): string # A format (for further reference: help std log) ] { + let format = $format | default "" handle-log $message (log-types | get CRITICAL) $format $short } @@ -194,6 +195,7 @@ export def error [ --short (-s) # Whether to use a short prefix --format (-f): string # A format (for further reference: help std log) ] { + let format = $format | default "" handle-log $message (log-types | get ERROR) $format $short } @@ -203,6 +205,7 @@ export def warning [ --short (-s) # Whether to use a short prefix --format (-f): string # A format (for further reference: help std log) ] { + let format = $format | default "" handle-log $message (log-types | get WARNING) $format $short } @@ -212,6 +215,7 @@ export def info [ --short (-s) # Whether to use a short prefix --format (-f): string # A format (for further reference: help std log) ] { + let format = $format | default "" handle-log $message (log-types | get INFO) $format $short } @@ -221,6 +225,7 @@ export def debug [ --short (-s) # Whether to use a short prefix --format (-f): string # A format (for further reference: help std log) ] { + let format = $format | default "" handle-log $message (log-types | get DEBUG) $format $short } diff --git a/src/tests/test_custom_commands.rs b/src/tests/test_custom_commands.rs index d2a562b1f6..93b2c83628 100644 --- a/src/tests/test_custom_commands.rs +++ b/src/tests/test_custom_commands.rs @@ -214,3 +214,18 @@ fn infinite_recursion_does_not_panic() { "#); assert!(actual.err.contains("Recursion limit (50) reached")); } + +#[test] +fn type_check_for_during_eval() -> TestResult { + fail_test( + r#"def spam [foo: string] { $foo | describe }; def outer [--foo: string] { spam $foo }; outer"#, + "can't convert nothing to string", + ) +} +#[test] +fn type_check_for_during_eval2() -> TestResult { + fail_test( + r#"def spam [foo: string] { $foo | describe }; def outer [--foo: any] { spam $foo }; outer"#, + "can't convert nothing to string", + ) +} diff --git a/src/tests/test_type_check.rs b/src/tests/test_type_check.rs index 2590997d7f..ed912f8fff 100644 --- a/src/tests/test_type_check.rs +++ b/src/tests/test_type_check.rs @@ -114,6 +114,14 @@ fn record_subtyping_allows_general_inner() -> TestResult { ) } +#[test] +fn record_subtyping_works() -> TestResult { + run_test( + r#"def merge_records [other: record] { "" }; merge_records {"bar": 3, "foo": 4}"#, + "", + ) +} + #[test] fn transpose_into_load_env() -> TestResult { run_test(