Skip to content

Commit

Permalink
Rollup merge of #98137 - michaelwoerister:fix-unsized-rc-arc-natvis, …
Browse files Browse the repository at this point in the history
…r=wesleywiser

debuginfo: Fix NatVis for Rc and Arc with unsized pointees.

Currently, the NatVis for `Rc<T>` and `Arc<T>` does not support unsized `T`. For both `Rc<T>` and `Rc<dyn SomeTrait>` the visualizers fail:

```txt
    [Reference count] : -> must be used on pointers and . on structures
    [Weak reference count] : -> must be used on pointers and . on structures
```

This PR fixes the visualizers. For slices we can even give show the elements, so one now gets something like:

```txt
slice_rc         : { len=3 }
    [Length]         : 3
    [Reference count] : 41
    [Weak reference count] : 2
    [0]              : 1
    [1]              : 2
    [2]              : 3
```

r? `@wesleywiser`
  • Loading branch information
matthiaskrgr authored Jun 16, 2022
2 parents f4297b0 + 95adaa2 commit ae58a55
Show file tree
Hide file tree
Showing 2 changed files with 214 additions and 56 deletions.
126 changes: 110 additions & 16 deletions src/etc/natvis/liballoc.natvis
Original file line number Diff line number Diff line change
Expand Up @@ -59,39 +59,133 @@
</Expand>
</Type>

<!--
The display string for Rc, Arc, etc is optional because the expression cannot be evaluated
if the pointee is unsized (i.e. if `ptr.pointer` is a fat pointer).
There are also two versions for the reference count fields, one for sized and one for
dyn pointees.
Rc<[T]> and Arc<[T]> are handled separately altogether so we can actually show
the slice values.
-->
<!-- alloc::rc::Rc<T> -->
<Type Name="alloc::rc::Rc&lt;*&gt;">
<DisplayString>{ptr.pointer->value}</DisplayString>
<DisplayString Optional="true">{ptr.pointer->value}</DisplayString>
<Expand>
<ExpandedItem>ptr.pointer->value</ExpandedItem>
<Item Name="[Reference count]">ptr.pointer->strong</Item>
<Item Name="[Weak reference count]">ptr.pointer->weak</Item>
<!-- thin -->
<ExpandedItem Optional="true">ptr.pointer->value</ExpandedItem>
<Item Name="[Reference count]" Optional="true">ptr.pointer->strong</Item>
<Item Name="[Weak reference count]" Optional="true">ptr.pointer->weak</Item>

<!-- dyn -->
<Item Name="[Reference count]" Optional="true">ptr.pointer.pointer->strong</Item>
<Item Name="[Weak reference count]" Optional="true">ptr.pointer.pointer->weak</Item>
</Expand>
</Type>

<!-- alloc::rc::Rc<[T]> -->
<Type Name="alloc::rc::Rc&lt;slice$&lt;*&gt; &gt;">
<DisplayString>{{ len={ptr.pointer.length} }}</DisplayString>
<Expand>
<Item Name="[Length]" ExcludeView="simple">ptr.pointer.length</Item>
<Item Name="[Reference count]">ptr.pointer.data_ptr->strong</Item>
<Item Name="[Weak reference count]">ptr.pointer.data_ptr->weak</Item>
<ArrayItems>
<Size>ptr.pointer.length</Size>
<!-- We add +2 to the data_ptr in order to skip the ref count fields in the RcBox -->
<ValuePointer>($T1*)(((size_t*)ptr.pointer.data_ptr) + 2)</ValuePointer>
</ArrayItems>
</Expand>
</Type>

<!-- alloc::rc::Weak<T> -->
<Type Name="alloc::rc::Weak&lt;*&gt;">
<DisplayString>{ptr.pointer->value}</DisplayString>
<DisplayString Optional="true">{ptr.pointer->value}</DisplayString>
<Expand>
<!-- thin -->
<ExpandedItem Optional="true">ptr.pointer->value</ExpandedItem>
<Item Name="[Reference count]" Optional="true">ptr.pointer->strong</Item>
<Item Name="[Weak reference count]" Optional="true">ptr.pointer->weak</Item>

<!-- dyn -->
<Item Name="[Reference count]" Optional="true">ptr.pointer.pointer->strong</Item>
<Item Name="[Weak reference count]" Optional="true">ptr.pointer.pointer->weak</Item>
</Expand>
</Type>

<!-- alloc::rc::Weak<[T]> -->
<Type Name="alloc::rc::Weak&lt;slice$&lt;*&gt; &gt;">
<DisplayString>{{ len={ptr.pointer.length} }}</DisplayString>
<Expand>
<ExpandedItem>ptr.pointer->value</ExpandedItem>
<Item Name="[Reference count]">ptr.pointer->strong</Item>
<Item Name="[Weak reference count]">ptr.pointer->weak</Item>
<Item Name="[Length]" ExcludeView="simple">ptr.pointer.length</Item>
<Item Name="[Reference count]">ptr.pointer.data_ptr->strong</Item>
<Item Name="[Weak reference count]">ptr.pointer.data_ptr->weak</Item>
<ArrayItems>
<Size>ptr.pointer.length</Size>
<ValuePointer>($T1*)(((size_t*)ptr.pointer.data_ptr) + 2)</ValuePointer>
</ArrayItems>
</Expand>
</Type>

<!-- alloc::sync::Arc<T> -->
<Type Name="alloc::sync::Arc&lt;*&gt;">
<DisplayString>{ptr.pointer->data}</DisplayString>
<DisplayString Optional="true">{ptr.pointer->data}</DisplayString>
<Expand>
<ExpandedItem>ptr.pointer->data</ExpandedItem>
<Item Name="[Reference count]">ptr.pointer->strong</Item>
<Item Name="[Weak reference count]">ptr.pointer->weak</Item>
<!-- thin -->
<ExpandedItem Optional="true">ptr.pointer->data</ExpandedItem>
<Item Name="[Reference count]" Optional="true">ptr.pointer->strong</Item>
<Item Name="[Weak reference count]" Optional="true">ptr.pointer->weak</Item>

<!-- dyn -->
<Item Name="[Reference count]" Optional="true">ptr.pointer.pointer->strong</Item>
<Item Name="[Weak reference count]" Optional="true">ptr.pointer.pointer->weak</Item>
</Expand>
</Type>

<!-- alloc::sync::Arc<[T]> -->
<Type Name="alloc::sync::Arc&lt;slice$&lt;*&gt; &gt;">
<DisplayString>{{ len={ptr.pointer.length} }}</DisplayString>
<Expand>
<Item Name="[Length]" ExcludeView="simple">ptr.pointer.length</Item>
<Item Name="[Reference count]">ptr.pointer.data_ptr->strong</Item>
<Item Name="[Weak reference count]">ptr.pointer.data_ptr->weak</Item>
<ArrayItems>
<Size>ptr.pointer.length</Size>
<ValuePointer>($T1*)(((size_t*)ptr.pointer.data_ptr) + 2)</ValuePointer>
</ArrayItems>
</Expand>
</Type>

<!-- alloc::sync::Weak<T> -->
<Type Name="alloc::sync::Weak&lt;*&gt;">
<DisplayString>{ptr.pointer->data}</DisplayString>
<DisplayString Optional="true">{ptr.pointer->data}</DisplayString>
<Expand>
<ExpandedItem>ptr.pointer->data</ExpandedItem>
<Item Name="[Reference count]">ptr.pointer->strong</Item>
<Item Name="[Weak reference count]">ptr.pointer->weak</Item>
<!-- thin -->
<ExpandedItem Optional="true">ptr.pointer->data</ExpandedItem>
<Item Name="[Reference count]" Optional="true">ptr.pointer->strong</Item>
<Item Name="[Weak reference count]" Optional="true">ptr.pointer->weak</Item>

<!-- dyn -->
<Item Name="[Reference count]" Optional="true">ptr.pointer.pointer->strong</Item>
<Item Name="[Weak reference count]" Optional="true">ptr.pointer.pointer->weak</Item>
</Expand>
</Type>

<!-- alloc::sync::Weak<[T]> -->
<Type Name="alloc::sync::Weak&lt;slice$&lt;*&gt; &gt;">
<DisplayString>{{ len={ptr.pointer.length} }}</DisplayString>
<Expand>
<Item Name="[Length]" ExcludeView="simple">ptr.pointer.length</Item>
<Item Name="[Reference count]">ptr.pointer.data_ptr->strong</Item>
<Item Name="[Weak reference count]">ptr.pointer.data_ptr->weak</Item>
<ArrayItems>
<Size>ptr.pointer.length</Size>
<ValuePointer>($T1*)(((size_t*)ptr.pointer.data_ptr) + 2)</ValuePointer>
</ArrayItems>
</Expand>
</Type>

<Type Name="alloc::borrow::Cow&lt;*&gt;">
<DisplayString Condition="RUST$ENUM$DISR == 0x0">Borrowed({__0})</DisplayString>
<DisplayString Condition="RUST$ENUM$DISR == 0x1">Owned({__0})</DisplayString>
Expand Down
144 changes: 104 additions & 40 deletions src/test/debuginfo/rc_arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,74 +8,138 @@

// gdb-command:run

// gdb-command:print r
// gdb-check:[...]$1 = Rc(strong=2, weak=1) = {value = 42, strong = 2, weak = 1}
// gdb-command:print a
// gdb-check:[...]$2 = Arc(strong=2, weak=1) = {value = 42, strong = 2, weak = 1}

// gdb-command:print rc
// gdb-check:[...]$1 = Rc(strong=11, weak=1) = {value = 111, strong = 11, weak = 1}
// gdb-command:print arc
// gdb-check:[...]$2 = Arc(strong=21, weak=1) = {value = 222, strong = 21, weak = 1}

// === LLDB TESTS ==================================================================================

// lldb-command:run

// lldb-command:print r
// lldb-check:[...]$0 = strong=2, weak=1 { value = 42 }
// lldb-command:print a
// lldb-check:[...]$1 = strong=2, weak=1 { data = 42 }
// lldb-command:print rc
// lldb-check:[...]$0 = strong=11, weak=1 { value = 111 }
// lldb-command:print arc
// lldb-check:[...]$1 = strong=21, weak=1 { data = 222 }

// === CDB TESTS ==================================================================================

// cdb-command:g

// cdb-command:dx r,d
// cdb-check:r,d : 42 [Type: alloc::rc::Rc<i32>]
// cdb-check: [<Raw View>] [Type: alloc::rc::Rc<i32>]
// cdb-check: [Reference count] : 2 [Type: core::cell::Cell<usize>]
// cdb-command:dx rc,d
// cdb-check:rc,d : 111 [Type: alloc::rc::Rc<i32>]
// cdb-check: [Reference count] : 11 [Type: core::cell::Cell<usize>]
// cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell<usize>]

// cdb-command:dx weak_rc,d
// cdb-check:weak_rc,d : 111 [Type: alloc::rc::Weak<i32>]
// cdb-check: [Reference count] : 11 [Type: core::cell::Cell<usize>]
// cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell<usize>]

// cdb-command:dx arc,d
// cdb-check:arc,d : 222 [Type: alloc::sync::Arc<i32>]
// cdb-check: [Reference count] : 21 [Type: core::sync::atomic::AtomicUsize]
// cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize]

// cdb-command:dx weak_arc,d
// cdb-check:weak_arc,d : 222 [Type: alloc::sync::Weak<i32>]
// cdb-check: [Reference count] : 21 [Type: core::sync::atomic::AtomicUsize]
// cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize]

// cdb-command:dx dyn_rc,d
// cdb-check:dyn_rc,d [Type: alloc::rc::Rc<dyn$<core::fmt::Debug> >]
// cdb-check: [Reference count] : 31 [Type: core::cell::Cell<usize>]
// cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell<usize>]

// cdb-command:dx r1,d
// cdb-check:r1,d : 42 [Type: alloc::rc::Rc<i32>]
// cdb-check: [<Raw View>] [Type: alloc::rc::Rc<i32>]
// cdb-check: [Reference count] : 2 [Type: core::cell::Cell<usize>]
// cdb-command:dx dyn_rc_weak,d
// cdb-check:dyn_rc_weak,d [Type: alloc::rc::Weak<dyn$<core::fmt::Debug> >]
// cdb-check: [Reference count] : 31 [Type: core::cell::Cell<usize>]
// cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell<usize>]

// cdb-command:dx w1,d
// cdb-check:w1,d : 42 [Type: alloc::rc::Weak<i32>]
// cdb-check: [<Raw View>] [Type: alloc::rc::Weak<i32>]
// cdb-check: [Reference count] : 2 [Type: core::cell::Cell<usize>]
// cdb-command:dx slice_rc,d
// cdb-check:slice_rc,d : { len=3 } [Type: alloc::rc::Rc<slice$<u32> >]
// cdb-check: [Length] : 3 [Type: [...]]
// cdb-check: [Reference count] : 41 [Type: core::cell::Cell<usize>]
// cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell<usize>]
// cdb-check: [0] : 1 [Type: u32]
// cdb-check: [1] : 2 [Type: u32]
// cdb-check: [2] : 3 [Type: u32]

// cdb-command:dx slice_rc_weak,d
// cdb-check:slice_rc_weak,d : { len=3 } [Type: alloc::rc::Weak<slice$<u32> >]
// cdb-check: [Length] : 3 [Type: [...]]
// cdb-check: [Reference count] : 41 [Type: core::cell::Cell<usize>]
// cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell<usize>]
// cdb-check: [0] : 1 [Type: u32]
// cdb-check: [1] : 2 [Type: u32]
// cdb-check: [2] : 3 [Type: u32]

// cdb-command:dx a,d
// cdb-check:a,d : 42 [Type: alloc::sync::Arc<i32>]
// cdb-check: [<Raw View>] [Type: alloc::sync::Arc<i32>]
// cdb-check: [Reference count] : 2 [Type: core::sync::atomic::AtomicUsize]
// cdb-command:dx dyn_arc,d
// cdb-check:dyn_arc,d [Type: alloc::sync::Arc<dyn$<core::fmt::Debug> >]
// cdb-check: [Reference count] : 51 [Type: core::sync::atomic::AtomicUsize]
// cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize]

// cdb-command:dx a1,d
// cdb-check:a1,d : 42 [Type: alloc::sync::Arc<i32>]
// cdb-check: [<Raw View>] [Type: alloc::sync::Arc<i32>]
// cdb-check: [Reference count] : 2 [Type: core::sync::atomic::AtomicUsize]
// cdb-command:dx dyn_arc_weak,d
// cdb-check:dyn_arc_weak,d [Type: alloc::sync::Weak<dyn$<core::fmt::Debug> >]
// cdb-check: [Reference count] : 51 [Type: core::sync::atomic::AtomicUsize]
// cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize]

// cdb-command:dx w2,d
// cdb-check:w2,d : 42 [Type: alloc::sync::Weak<i32>]
// cdb-check: [<Raw View>] [Type: alloc::sync::Weak<i32>]
// cdb-check: [Reference count] : 2 [Type: core::sync::atomic::AtomicUsize]
// cdb-command:dx slice_arc,d
// cdb-check:slice_arc,d : { len=3 } [Type: alloc::sync::Arc<slice$<u32> >]
// cdb-check: [Length] : 3 [Type: [...]]
// cdb-check: [Reference count] : 61 [Type: core::sync::atomic::AtomicUsize]
// cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize]
// cdb-check: [0] : 4 [Type: u32]
// cdb-check: [1] : 5 [Type: u32]
// cdb-check: [2] : 6 [Type: u32]

// cdb-command:dx slice_arc_weak,d
// cdb-check:slice_arc_weak,d : { len=3 } [Type: alloc::sync::Weak<slice$<u32> >]
// cdb-check: [Length] : 3 [Type: [...]]
// cdb-check: [Reference count] : 61 [Type: core::sync::atomic::AtomicUsize]
// cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::AtomicUsize]
// cdb-check: [0] : 4 [Type: u32]
// cdb-check: [1] : 5 [Type: u32]
// cdb-check: [2] : 6 [Type: u32]

use std::fmt::Debug;
use std::rc::Rc;
use std::sync::Arc;

fn main() {
let r = Rc::new(42);
let r1 = Rc::clone(&r);
let w1 = Rc::downgrade(&r);
let rc = Rc::new(111);
inc_ref_count(&rc, 10);
let weak_rc = Rc::downgrade(&rc);

let arc = Arc::new(222);
inc_ref_count(&arc, 20);
let weak_arc = Arc::downgrade(&arc);

let dyn_rc: Rc<dyn Debug> = Rc::new(333);
inc_ref_count(&dyn_rc, 30);
let dyn_rc_weak = Rc::downgrade(&dyn_rc);

let slice_rc: Rc<[u32]> = Rc::from(vec![1, 2, 3]);
inc_ref_count(&slice_rc, 40);
let slice_rc_weak = Rc::downgrade(&slice_rc);

let a = Arc::new(42);
let a1 = Arc::clone(&a);
let w2 = Arc::downgrade(&a);
let dyn_arc: Arc<dyn Debug> = Arc::new(444);
inc_ref_count(&dyn_arc, 50);
let dyn_arc_weak = Arc::downgrade(&dyn_arc);

let slice_arc: Arc<[u32]> = Arc::from(vec![4, 5, 6]);
inc_ref_count(&slice_arc, 60);
let slice_arc_weak = Arc::downgrade(&slice_arc);

zzz(); // #break
}

fn zzz() { () }
fn inc_ref_count<T: Clone>(rc: &T, count: usize) {
for _ in 0..count {
std::mem::forget(rc.clone());
}
}

fn zzz() {
()
}

0 comments on commit ae58a55

Please sign in to comment.