From 57bd824b5a8f37b7c7eb22ea197350c0995b2b2a Mon Sep 17 00:00:00 2001 From: Luuk Wester Date: Sat, 18 Jan 2025 17:38:24 +0100 Subject: [PATCH 1/4] Make niches into nices --- crates/ide/src/hover/render.rs | 96 +++++++++++++++++++++++++++++++++- crates/ide/src/hover/tests.rs | 2 +- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 46242b75dd..7fe344cfa4 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -1082,7 +1082,19 @@ fn render_memory_layout( if config.niches { if let Some(niches) = layout.niches() { - format_to!(label, "niches = {niches}, "); + if niches > 1024 { + if is_pwr2(niches) { + format_to!(label, "niches = 2{}, ", pwr2_to_exponent(niches)); + } else if is_pwr2plus1(niches) { + format_to!(label, "niches = 2{} + 1, ", pwr2_to_exponent(niches - 1)); + } else if is_pwr2minus1(niches) { + format_to!(label, "niches = 2{} - 1, ", pwr2_to_exponent(niches + 1)); + } else { + format_to!(label, "niches = really rather quite large, "); + } + } else { + format_to!(label, "niches = {niches}, "); + } } } label.pop(); // ' ' @@ -1210,3 +1222,85 @@ fn render_dyn_compatibility( } } } + +fn is_pwr2(val: u128) -> bool { + val.count_ones() == 1 +} + +fn is_pwr2minus1(val: u128) -> bool { + val == u128::MAX || (val + 1).count_ones() == 1 +} + +fn is_pwr2plus1(val: u128) -> bool { + val != 0 && (val - 1).count_ones() == 1 +} + +fn pwr2_to_exponent(num: u128) -> String { + const DIGITS: [char; 10] = ['⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹']; + (127 - num.leading_zeros()) + .to_string() + .chars() + .map(|c| c.to_digit(10).unwrap() as usize) + .map(|idx| DIGITS[idx]) + .collect::() +} + +#[cfg(test)] +mod tests { + use super::*; + + const TESTERS: [u128; 10] = [0, 1, 2, 3, 4, 255, 256, 257, u128::MAX - 1, u128::MAX]; + + #[test] + fn test_is_pwr2() { + const OUTCOMES: [bool; 10] = + [false, true, true, false, true, false, true, false, false, false]; + for (test, expected) in TESTERS.iter().zip(OUTCOMES) { + let actual = is_pwr2(*test); + assert_eq!(actual, expected, "is_pwr2({test}) gave {actual}, expected {expected}"); + } + } + + #[test] + fn test_is_pwr2minus1() { + const OUTCOMES: [bool; 10] = + [true, true, false, true, false, true, false, false, false, true]; + for (test, expected) in TESTERS.iter().zip(OUTCOMES) { + let actual = is_pwr2minus1(*test); + assert_eq!(actual, expected, "is_pwr2minu1({test}) gave {actual}, expected {expected}"); + } + } + + #[test] + fn test_is_pwr2plus1() { + const OUTCOMES: [bool; 10] = + [false, false, true, true, false, false, false, true, false, false]; + for (test, expected) in TESTERS.iter().zip(OUTCOMES) { + let actual = is_pwr2plus1(*test); + assert_eq!(actual, expected, "is_pwr2plus1({test}) gave {actual}, expected {expected}"); + } + } + + #[test] + fn test_pwr2_to_exponent() { + const TESTERS: [u128; 9] = [ + 1, + 2, + 4, + 8, + 16, + 9223372036854775808, + 18446744073709551616, + 36893488147419103232, + 170141183460469231731687303715884105728, + ]; + const OUTCOMES: [&str; 9] = ["⁰", "¹", "²", "³", "⁴", "⁶³", "⁶⁴", "⁶⁵", "¹²⁷"]; + for (test, expected) in TESTERS.iter().zip(OUTCOMES) { + let actual = pwr2_to_exponent(*test); + assert_eq!( + actual, expected, + "pwr2_to_exponent({test}) returned {actual}, expected {expected}", + ); + } + } +} diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 014b751f95..63eb772fde 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -1357,7 +1357,7 @@ fn hover_enum_limit() { --- - size = 12 (0xC), align = 4, niches = 4294967288 + size = 12 (0xC), align = 4, niches = really rather quite large "#]], ); } From 6b6e0195936e84920284f3dd17a93b2c1127ff84 Mon Sep 17 00:00:00 2001 From: Luuk Wester Date: Tue, 21 Jan 2025 10:33:28 +0100 Subject: [PATCH 2/4] make large niche description more terse, switch to using u128::is_power_of_two --- crates/ide/src/hover/render.rs | 8 ++++---- crates/ide/src/hover/tests.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 7fe344cfa4..95be7c5618 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -1090,7 +1090,7 @@ fn render_memory_layout( } else if is_pwr2minus1(niches) { format_to!(label, "niches = 2{} - 1, ", pwr2_to_exponent(niches + 1)); } else { - format_to!(label, "niches = really rather quite large, "); + format_to!(label, "niches = a lot, "); } } else { format_to!(label, "niches = {niches}, "); @@ -1224,15 +1224,15 @@ fn render_dyn_compatibility( } fn is_pwr2(val: u128) -> bool { - val.count_ones() == 1 + val.is_power_of_two() } fn is_pwr2minus1(val: u128) -> bool { - val == u128::MAX || (val + 1).count_ones() == 1 + val == u128::MAX || is_pwr2(val + 1) } fn is_pwr2plus1(val: u128) -> bool { - val != 0 && (val - 1).count_ones() == 1 + val != 0 && is_pwr2(val - 1) } fn pwr2_to_exponent(num: u128) -> String { diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs index 63eb772fde..064a845dc5 100644 --- a/crates/ide/src/hover/tests.rs +++ b/crates/ide/src/hover/tests.rs @@ -1357,7 +1357,7 @@ fn hover_enum_limit() { --- - size = 12 (0xC), align = 4, niches = really rather quite large + size = 12 (0xC), align = 4, niches = a lot "#]], ); } From 705eb84941c2d2eb3daa741fb6a99216572737f4 Mon Sep 17 00:00:00 2001 From: Luuk Wester Date: Tue, 21 Jan 2025 14:45:30 +0100 Subject: [PATCH 3/4] switch from using leading zeros to trailing zeros --- crates/ide/src/hover/render.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index 95be7c5618..fb7c2904af 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -1235,9 +1235,12 @@ fn is_pwr2plus1(val: u128) -> bool { val != 0 && is_pwr2(val - 1) } +/// Formats a power of two as an exponent of two, i.e. 16 => ⁴. Note that `num` MUST be a power +/// of 2, or this function will panic. fn pwr2_to_exponent(num: u128) -> String { const DIGITS: [char; 10] = ['⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹']; - (127 - num.leading_zeros()) + assert_eq!(num.count_ones(), 1); + num.trailing_zeros() .to_string() .chars() .map(|c| c.to_digit(10).unwrap() as usize) From 5ad3de8b29840c5975ae04b4d0d5f5d85dafc179 Mon Sep 17 00:00:00 2001 From: Luuk Wester Date: Tue, 21 Jan 2025 14:47:07 +0100 Subject: [PATCH 4/4] remove is_pwr2 --- crates/ide/src/hover/render.rs | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs index fb7c2904af..40f3406b72 100644 --- a/crates/ide/src/hover/render.rs +++ b/crates/ide/src/hover/render.rs @@ -1083,7 +1083,7 @@ fn render_memory_layout( if config.niches { if let Some(niches) = layout.niches() { if niches > 1024 { - if is_pwr2(niches) { + if niches.is_power_of_two() { format_to!(label, "niches = 2{}, ", pwr2_to_exponent(niches)); } else if is_pwr2plus1(niches) { format_to!(label, "niches = 2{} + 1, ", pwr2_to_exponent(niches - 1)); @@ -1223,16 +1223,12 @@ fn render_dyn_compatibility( } } -fn is_pwr2(val: u128) -> bool { - val.is_power_of_two() -} - fn is_pwr2minus1(val: u128) -> bool { - val == u128::MAX || is_pwr2(val + 1) + val == u128::MAX || (val + 1).is_power_of_two() } fn is_pwr2plus1(val: u128) -> bool { - val != 0 && is_pwr2(val - 1) + val != 0 && (val - 1).is_power_of_two() } /// Formats a power of two as an exponent of two, i.e. 16 => ⁴. Note that `num` MUST be a power @@ -1254,16 +1250,6 @@ mod tests { const TESTERS: [u128; 10] = [0, 1, 2, 3, 4, 255, 256, 257, u128::MAX - 1, u128::MAX]; - #[test] - fn test_is_pwr2() { - const OUTCOMES: [bool; 10] = - [false, true, true, false, true, false, true, false, false, false]; - for (test, expected) in TESTERS.iter().zip(OUTCOMES) { - let actual = is_pwr2(*test); - assert_eq!(actual, expected, "is_pwr2({test}) gave {actual}, expected {expected}"); - } - } - #[test] fn test_is_pwr2minus1() { const OUTCOMES: [bool; 10] =