Repository: rust-lang/rust-analyzer
Pull request #18973 (2025-01-18 16:38:34)

Make niches into nices
Format niche information like so:
![image](https://github.com/user-attachments/assets/a3b36f10-94e7-4749-9e51-ee0d5913c2e0)



Patch:
diff --git a/Cargo.lock b/Cargo.lock
index cdc6aef54a..3a7ebb9da4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1434,7 +1434,7 @@ dependencies = [
  "libc",
  "perf-event",
  "tikv-jemalloc-ctl",
- "windows-sys 0.59.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -1719,7 +1719,7 @@ dependencies = [
  "vfs",
  "vfs-notify",
  "walkdir",
- "windows-sys 0.59.0",
+ "windows-sys 0.52.0",
  "xflags",
  "xshell",
 ]
@@ -1942,7 +1942,7 @@ dependencies = [
  "jod-thread",
  "libc",
  "miow",
- "windows-sys 0.59.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index 46242b75dd..40f3406b72 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 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));
+                } else if is_pwr2minus1(niches) {
+                    format_to!(label, "niches = 2{} - 1, ", pwr2_to_exponent(niches + 1));
+                } else {
+                    format_to!(label, "niches = a lot, ");
+                }
+            } else {
+                format_to!(label, "niches = {niches}, ");
+            }
         }
     }
     label.pop(); // ' '
@@ -1210,3 +1222,74 @@ fn render_dyn_compatibility(
         }
     }
 }
+
+fn is_pwr2minus1(val: u128) -> bool {
+    val == u128::MAX || (val + 1).is_power_of_two()
+}
+
+fn is_pwr2plus1(val: u128) -> bool {
+    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
+/// of 2, or this function will panic.
+fn pwr2_to_exponent(num: u128) -> String {
+    const DIGITS: [char; 10] = ['⁰', '¹', '²', '³', '⁴', '⁵', '⁶', '⁷', '⁸', '⁹'];
+    assert_eq!(num.count_ones(), 1);
+    num.trailing_zeros()
+        .to_string()
+        .chars()
+        .map(|c| c.to_digit(10).unwrap() as usize)
+        .map(|idx| DIGITS[idx])
+        .collect::<String>()
+}
+
+#[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_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/profile/Cargo.toml b/crates/profile/Cargo.toml
index 3179c810f6..5eb746f86a 100644
--- a/crates/profile/Cargo.toml
+++ b/crates/profile/Cargo.toml
@@ -21,7 +21,8 @@ jemalloc-ctl = { version = "0.5.0", package = "tikv-jemalloc-ctl", optional = tr
 perf-event = "=0.4.7"
 
 [target.'cfg(windows)'.dependencies]
-windows-sys = { version = "0.59", features = [
+windows-sys = { version = "0.52", features = [
+    "Win32_Foundation",
     "Win32_System_Threading",
     "Win32_System_ProcessStatus",
 ] }
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index c24cbb4a31..d06130ce8c 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -76,10 +76,7 @@ vfs.workspace = true
 paths.workspace = true
 
 [target.'cfg(windows)'.dependencies]
-windows-sys = { version = "0.59", features = [
-  "Win32_System_Diagnostics_Debug",
-  "Win32_System_Threading",
-] }
+windows-sys = { version = "0.52", features = ["Win32_System_Diagnostics_Debug", "Win32_System_Threading"] }
 
 [target.'cfg(not(target_env = "msvc"))'.dependencies]
 jemallocator = { version = "0.5.0", package = "tikv-jemallocator", optional = true }
diff --git a/crates/stdx/Cargo.toml b/crates/stdx/Cargo.toml
index 1ebb48c577..bf0d6df9ad 100644
--- a/crates/stdx/Cargo.toml
+++ b/crates/stdx/Cargo.toml
@@ -23,7 +23,7 @@ itertools.workspace = true
 
 [target.'cfg(windows)'.dependencies]
 miow = "0.6.0"
-windows-sys = { version = "0.59", features = ["Win32_Foundation"] }
+windows-sys = { version = "0.52", features = ["Win32_Foundation"] }
 
 [features]
 # Uncomment to enable for the whole crate graph
diff --git a/docs/dev/README.md b/docs/dev/README.md
index 3ba492e095..cd0f49174c 100644
--- a/docs/dev/README.md
+++ b/docs/dev/README.md
@@ -154,21 +154,19 @@ There are also several VS Code commands which might be of interest:
 
 * `rust-analyzer: Status` shows some memory-usage statistics.
 
-* `rust-analyzer: View Hir` shows the HIR expressions within the function containing the cursor.
-
-* If `rust-analyzer.showSyntaxTree` is enabled in settings, `Rust Syntax Tree: Focus on Rust Syntax Tree View` shows the syntax tree of the current file.
+* `rust-analyzer: Syntax Tree` shows syntax tree of the current file/selection.
 
-  You can click on nodes in the rust editor to go to the corresponding syntax node.
+* `rust-analyzer: View Hir` shows the HIR expressions within the function containing the cursor.
 
-  You can click on `Reveal Syntax Element` next to a syntax node to go to the corresponding rust code and highlight the proper text range.
+  You can hover over syntax nodes in the opened text file to see the appropriate
+  rust code that it refers to and the rust editor will also highlight the proper
+  text range.
 
   If you trigger Go to Definition in the inspected Rust source file,
-  the syntax tree view should scroll to and select the
+  the syntax tree read-only editor should scroll to and select the
   appropriate syntax node token.
 
-  You can click on `Copy` next to a syntax node to copy a text representation of the node.
-
-  ![demo](https://github.com/user-attachments/assets/2d20ae87-0abf-495f-bee8-54aa2494a00d)
+  ![demo](https://user-images.githubusercontent.com/36276403/78225773-6636a480-74d3-11ea-9d9f-1c9d42da03b0.png)
 
 ## Profiling
 


Test patch:
diff --git a/crates/ide/src/hover/tests.rs b/crates/ide/src/hover/tests.rs
index 014b751f95..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 = 4294967288
+            size = 12 (0xC), align = 4, niches = a lot
         "#]],
     );
 }