From 34da26d039b85581332e58893cd539951a888c4f Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> Date: Fri, 5 Jul 2024 19:31:27 +0530 Subject: [PATCH] fix: exotic types return float on division, self on modulo (#13301) Related to #13298 # Description Exotic types like `Duration` and `Filesize` return a float on division by the same type, i.e., the unit is gone since division results in a scalar. When using the modulo operator, the output type has the same unit. # User-Facing Changes Division results in a float like the following: ```sh ~/Public/nushell> 512sec / 3sec 170.66666666666666 ``` Modulo results in an output with the same unit: ```sh ~/Public/nushell> 512sec mod 3sec 2sec ``` Type checking isn't confused with output types: ```sh ~/Public/nushell> (512sec mod 3sec) / 0.5sec 4 ``` # Tests + Formatting Existing tests are passing. # After Submitting --- crates/nu-parser/src/type_check.rs | 52 ++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/crates/nu-parser/src/type_check.rs b/crates/nu-parser/src/type_check.rs index 872bb6a94c..6999a0469b 100644 --- a/crates/nu-parser/src/type_check.rs +++ b/crates/nu-parser/src/type_check.rs @@ -278,8 +278,7 @@ pub fn math_result_type( ) } }, - Operator::Math(Math::Divide) | Operator::Math(Math::Modulo) => match (&lhs.ty, &rhs.ty) - { + Operator::Math(Math::Divide) => match (&lhs.ty, &rhs.ty) { (Type::Int, Type::Int) => (Type::Int, None), (Type::Float, Type::Int) => (Type::Float, None), (Type::Int, Type::Float) => (Type::Float, None), @@ -292,6 +291,55 @@ pub fn math_result_type( (Type::Filesize, Type::Filesize) => (Type::Float, None), (Type::Filesize, Type::Int) => (Type::Filesize, None), (Type::Filesize, Type::Float) => (Type::Filesize, None), + (Type::Duration, Type::Duration) => (Type::Float, None), + (Type::Duration, Type::Int) => (Type::Duration, None), + (Type::Duration, Type::Float) => (Type::Duration, None), + + (Type::Custom(a), Type::Custom(b)) if a == b => (Type::Custom(a.clone()), None), + (Type::Custom(a), _) => (Type::Custom(a.clone()), None), + + (Type::Any, _) => (Type::Any, None), + (_, Type::Any) => (Type::Any, None), + (Type::Int | Type::Float | Type::Filesize | Type::Duration, _) => { + *op = Expression::garbage(working_set, op.span); + ( + Type::Any, + Some(ParseError::UnsupportedOperationRHS( + "division".into(), + op.span, + lhs.span, + lhs.ty.clone(), + rhs.span, + rhs.ty.clone(), + )), + ) + } + _ => { + *op = Expression::garbage(working_set, op.span); + ( + Type::Any, + Some(ParseError::UnsupportedOperationLHS( + "division".into(), + op.span, + lhs.span, + lhs.ty.clone(), + )), + ) + } + }, + Operator::Math(Math::Modulo) => match (&lhs.ty, &rhs.ty) { + (Type::Int, Type::Int) => (Type::Int, None), + (Type::Float, Type::Int) => (Type::Float, None), + (Type::Int, Type::Float) => (Type::Float, None), + (Type::Float, Type::Float) => (Type::Float, None), + (Type::Number, Type::Number) => (Type::Number, None), + (Type::Number, Type::Int) => (Type::Number, None), + (Type::Int, Type::Number) => (Type::Number, None), + (Type::Number, Type::Float) => (Type::Number, None), + (Type::Float, Type::Number) => (Type::Number, None), + (Type::Filesize, Type::Filesize) => (Type::Filesize, None), + (Type::Filesize, Type::Int) => (Type::Filesize, None), + (Type::Filesize, Type::Float) => (Type::Filesize, None), (Type::Duration, Type::Duration) => (Type::Duration, None), (Type::Duration, Type::Int) => (Type::Duration, None), (Type::Duration, Type::Float) => (Type::Duration, None),