Repository: intellij-rust/intellij-rust
Issue: Vec contents not shown in debugger

<!--
Hello and thank you for the issue!
If you would like to report a bug, we have added some points below that you can fill out.
Consider using "Help | Create New Issue" action that fills out all necessary information automatically.
Feel free to remove all the irrelevant text to request a new feature.
-->

## Environment

* **IntelliJ Rust plugin version:** 0.4.168.4555-221
* **Rust toolchain version:** rustc 1.62.0-nightly (4ca19e09d 2022-04-19)
* **IDE name and version:** CLion 2022.1 build #CL-221.5080.224
* **Operating system:** Arch Linux 5.17.3-arch1-1

## Problem description
Vec and slice content is not viewed in the debug window. It's as if they are empty: I can click the small triangle to "expand" but then nothing pops up.

## Steps to reproduce
Make a simple test project like
```rust
#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        let result = 2 + 2;
        let x = vec![2, 3, 4];
        assert_eq!(result, 4);
    }
}
```
and add a breakpoint at the assertion. Start the debugger and observe the bug.

<!--
Please include as much of your codebase as needed to reproduce the error.
If the relevant files are large, please provide a link to a public repository or a [Gist](https://gist.github.com/).

If you provide a screenshot of some code, please also copy-paste the corresponding code snippet here.
-->


Changed files:
prettyPrinters/lldb_providers.py, prettyPrinters/gdb_providers.py

diff --git a/prettyPrinters/gdb_providers.py b/prettyPrinters/gdb_providers.py
index f87210e38..7304073f5 100644
--- a/prettyPrinters/gdb_providers.py
+++ b/prettyPrinters/gdb_providers.py
@@ -9,6 +9,18 @@ if version_info[0] >= 3:
 ZERO_FIELD = "__0"
 FIRST_FIELD = "__1"
 
+
+def unwrap_unique_or_non_null(unique_or_nonnull):
+    # type: (Value) -> Value
+    """
+    rust 1.33.0: struct Unique<T: ?Sized> { pointer: *const T, ... }
+    rust 1.62.0: struct Unique<T: ?Sized> { pointer: NonNull<T>, ... }
+    struct NonNull<T> { pointer: *const T }
+    """
+    ptr = unique_or_nonnull["pointer"]
+    return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr["pointer"]
+
+
 class StructProvider:
     def __init__(self, valobj):
         # type: (Value) -> None
@@ -96,7 +108,7 @@ class StdStringProvider:
         self.valobj = valobj
         vec = valobj["vec"]
         self.length = int(vec["len"])
-        self.data_ptr = vec["buf"]["ptr"]["pointer"]
+        self.data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"])
 
     def to_string(self):
         return self.data_ptr.lazy_string(encoding="utf-8", length=self.length)
@@ -115,7 +127,7 @@ class StdOsStringProvider:
         vec = buf[ZERO_FIELD] if is_windows else buf
 
         self.length = int(vec["len"])
-        self.data_ptr = vec["buf"]["ptr"]["pointer"]
+        self.data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"])
 
     def to_string(self):
         return self.data_ptr.lazy_string(encoding="utf-8", length=self.length)
@@ -145,7 +157,7 @@ class StdVecProvider:
         # type: (Value) -> None
         self.valobj = valobj
         self.length = int(valobj["len"])
-        self.data_ptr = valobj["buf"]["ptr"]["pointer"]
+        self.data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"])
 
     def to_string(self):
         return "size={}".format(self.length)
@@ -166,7 +178,7 @@ class StdVecDequeProvider:
         self.head = int(valobj["head"])
         self.tail = int(valobj["tail"])
         self.cap = int(valobj["buf"]["cap"])
-        self.data_ptr = valobj["buf"]["ptr"]["pointer"]
+        self.data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"])
         if self.head >= self.tail:
             self.size = self.head - self.tail
         else:
@@ -188,7 +200,7 @@ class StdRcProvider:
     def __init__(self, valobj, is_atomic=False):
         # type: (Value, bool) -> None
         self.valobj = valobj
-        self.ptr = valobj["ptr"]["pointer"]
+        self.ptr = unwrap_unique_or_non_null(valobj["ptr"])
         self.value = self.ptr["data" if is_atomic else "value"]
         self.strong = self.ptr["strong"]["v" if is_atomic else "value"]["value"]
         self.weak = self.ptr["weak"]["v" if is_atomic else "value"]["value"] - 1
@@ -266,7 +278,7 @@ def children_of_btree_map(map):
         if node_ptr.type.name.startswith("alloc::collections::btree::node::BoxedNode<"):
             node_ptr = node_ptr["ptr"]
 
-        node_ptr = node_ptr["pointer"]
+        node_ptr = unwrap_unique_or_non_null(node_ptr)
         leaf = node_ptr.dereference()
         keys = leaf["keys"]
         vals = leaf["vals"]
diff --git a/prettyPrinters/lldb_providers.py b/prettyPrinters/lldb_providers.py
index 8536427c0..0051524c3 100644
--- a/prettyPrinters/lldb_providers.py
+++ b/prettyPrinters/lldb_providers.py
@@ -40,6 +40,21 @@ if PY3:
     from typing import Optional
 
 
+def unwrap_unique_or_non_null(unique_or_nonnull):
+    # type: (SBValue) -> SBValue
+    """
+    rust 1.33.0: struct Unique<T: ?Sized> { pointer: *const T, ... }
+    rust 1.62.0: struct Unique<T: ?Sized> { pointer: NonNull<T>, ... }
+    struct NonNull<T> { pointer: *const T }
+    """
+    ptr = unique_or_nonnull.GetChildMemberWithName("pointer")
+    inner_ptr = ptr.GetChildMemberWithName("pointer")
+    if inner_ptr.IsValid():
+        return inner_ptr
+    else:
+        return ptr
+
+
 class ValueBuilder:
     def __init__(self, valobj):
         # type: (SBValue) -> None
@@ -267,9 +282,9 @@ class StdVecSyntheticProvider:
 
     struct Vec<T> { buf: RawVec<T>, len: usize }
     struct RawVec<T> { ptr: Unique<T>, cap: usize, ... }
-    rust 1.31.1: struct Unique<T: ?Sized> { pointer: NonZero<*const T>, ... }
     rust 1.33.0: struct Unique<T: ?Sized> { pointer: *const T, ... }
-    struct NonZero<T>(T)
+    rust 1.62.0: struct Unique<T: ?Sized> { pointer: NonNull<T>, ... }
+    struct NonNull<T> { pointer: *const T }
     """
 
     def __init__(self, valobj, _dict):
@@ -300,9 +315,7 @@ class StdVecSyntheticProvider:
         # type: () -> None
         self.length = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()
         self.buf = self.valobj.GetChildMemberWithName("buf")
-
-        self.data_ptr = self.buf.GetChildMemberWithName("ptr").GetChildMemberWithName("pointer")
-
+        self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr"))
         self.element_type = self.data_ptr.GetType().GetPointeeType()
         self.element_type_size = self.element_type.GetByteSize()
 
@@ -348,9 +361,7 @@ class StdVecDequeSyntheticProvider:
         self.buf = self.valobj.GetChildMemberWithName("buf")
         self.cap = self.buf.GetChildMemberWithName("cap").GetValueAsUnsigned()
         self.size = self.head - self.tail if self.head >= self.tail else self.cap + self.head - self.tail
-
-        self.data_ptr = self.buf.GetChildMemberWithName("ptr").GetChildMemberWithName("pointer")
-
+        self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr"))
         self.element_type = self.data_ptr.GetType().GetPointeeType()
         self.element_type_size = self.element_type.GetByteSize()
 
@@ -455,9 +466,7 @@ class StdRcSyntheticProvider:
     """Pretty-printer for alloc::rc::Rc<T> and alloc::sync::Arc<T>
 
     struct Rc<T> { ptr: NonNull<RcBox<T>>, ... }
-    rust 1.31.1: struct NonNull<T> { pointer: NonZero<*const T> }
-    rust 1.33.0: struct NonNull<T> { pointer: *const T }
-    struct NonZero<T>(T)
+    struct NonNull<T> { pointer: *const T }
     struct RcBox<T> { strong: Cell<usize>, weak: Cell<usize>, value: T }
     struct Cell<T> { value: UnsafeCell<T> }
     struct UnsafeCell<T> { value: T }
@@ -470,16 +479,11 @@ class StdRcSyntheticProvider:
     def __init__(self, valobj, _dict, is_atomic=False):
         # type: (SBValue, dict, bool) -> None
         self.valobj = valobj
-
-        self.ptr = self.valobj.GetChildMemberWithName("ptr").GetChildMemberWithName("pointer")
-
+        self.ptr = unwrap_unique_or_non_null(self.valobj.GetChildMemberWithName("ptr"))
         self.value = self.ptr.GetChildMemberWithName("data" if is_atomic else "value")
-
         self.strong = self.ptr.GetChildMemberWithName("strong").GetChildAtIndex(0).GetChildMemberWithName("value")
         self.weak = self.ptr.GetChildMemberWithName("weak").GetChildAtIndex(0).GetChildMemberWithName("value")
-
         self.value_builder = ValueBuilder(valobj)
-
         self.update()
 
     def num_children(self):