Skip to content

Commit 64ac0c0

Browse files
authored
Merge pull request #145 from dtolnay/addrof
Eliminate functionally duplicate vtable methods on rustc 1.51+
2 parents 2987c9b + ef08267 commit 64ac0c0

File tree

4 files changed

+110
-20
lines changed

4 files changed

+110
-20
lines changed

.github/workflows/ci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
strategy:
1313
fail-fast: false
1414
matrix:
15-
rust: [nightly, beta, stable]
15+
rust: [nightly, beta, stable, 1.51.0, 1.50.0]
1616
steps:
1717
- uses: actions/checkout@v2
1818
- uses: dtolnay/rust-toolchain@master

build.rs

+4
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ fn main() {
5656
if rustc < 38 {
5757
println!("cargo:rustc-cfg=anyhow_no_macro_reexport");
5858
}
59+
60+
if rustc < 51 {
61+
println!("cargo:rustc-cfg=anyhow_no_ptr_addr_of");
62+
}
5963
}
6064

6165
fn compile_probe() -> Option<ExitStatus> {

src/error.rs

+75-19
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
use crate::alloc::Box;
22
use crate::backtrace::Backtrace;
33
use crate::chain::Chain;
4-
use crate::ptr::{Mut, Own, Ref};
4+
#[cfg(any(feature = "std", anyhow_no_ptr_addr_of))]
5+
use crate::ptr::Mut;
6+
use crate::ptr::{Own, Ref};
57
use crate::{Error, StdError};
68
use core::any::TypeId;
79
use core::fmt::{self, Debug, Display};
810
use core::mem::ManuallyDrop;
11+
#[cfg(not(anyhow_no_ptr_addr_of))]
12+
use core::ptr;
913
use core::ptr::NonNull;
1014

1115
#[cfg(feature = "std")]
@@ -81,9 +85,11 @@ impl Error {
8185
let vtable = &ErrorVTable {
8286
object_drop: object_drop::<E>,
8387
object_ref: object_ref::<E>,
88+
#[cfg(anyhow_no_ptr_addr_of)]
8489
object_mut: object_mut::<E>,
8590
object_boxed: object_boxed::<E>,
8691
object_downcast: object_downcast::<E>,
92+
#[cfg(anyhow_no_ptr_addr_of)]
8793
object_downcast_mut: object_downcast_mut::<E>,
8894
object_drop_rest: object_drop_front::<E>,
8995
#[cfg(all(not(backtrace), feature = "backtrace"))]
@@ -103,10 +109,11 @@ impl Error {
103109
let vtable = &ErrorVTable {
104110
object_drop: object_drop::<MessageError<M>>,
105111
object_ref: object_ref::<MessageError<M>>,
106-
#[cfg(feature = "std")]
112+
#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))]
107113
object_mut: object_mut::<MessageError<M>>,
108114
object_boxed: object_boxed::<MessageError<M>>,
109115
object_downcast: object_downcast::<M>,
116+
#[cfg(anyhow_no_ptr_addr_of)]
110117
object_downcast_mut: object_downcast_mut::<M>,
111118
object_drop_rest: object_drop_front::<M>,
112119
#[cfg(all(not(backtrace), feature = "backtrace"))]
@@ -127,10 +134,11 @@ impl Error {
127134
let vtable = &ErrorVTable {
128135
object_drop: object_drop::<DisplayError<M>>,
129136
object_ref: object_ref::<DisplayError<M>>,
130-
#[cfg(feature = "std")]
137+
#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))]
131138
object_mut: object_mut::<DisplayError<M>>,
132139
object_boxed: object_boxed::<DisplayError<M>>,
133140
object_downcast: object_downcast::<M>,
141+
#[cfg(anyhow_no_ptr_addr_of)]
134142
object_downcast_mut: object_downcast_mut::<M>,
135143
object_drop_rest: object_drop_front::<M>,
136144
#[cfg(all(not(backtrace), feature = "backtrace"))]
@@ -153,9 +161,11 @@ impl Error {
153161
let vtable = &ErrorVTable {
154162
object_drop: object_drop::<ContextError<C, E>>,
155163
object_ref: object_ref::<ContextError<C, E>>,
164+
#[cfg(anyhow_no_ptr_addr_of)]
156165
object_mut: object_mut::<ContextError<C, E>>,
157166
object_boxed: object_boxed::<ContextError<C, E>>,
158167
object_downcast: context_downcast::<C, E>,
168+
#[cfg(anyhow_no_ptr_addr_of)]
159169
object_downcast_mut: context_downcast_mut::<C, E>,
160170
object_drop_rest: context_drop_rest::<C, E>,
161171
#[cfg(all(not(backtrace), feature = "backtrace"))]
@@ -176,9 +186,11 @@ impl Error {
176186
let vtable = &ErrorVTable {
177187
object_drop: object_drop::<BoxedError>,
178188
object_ref: object_ref::<BoxedError>,
189+
#[cfg(anyhow_no_ptr_addr_of)]
179190
object_mut: object_mut::<BoxedError>,
180191
object_boxed: object_boxed::<BoxedError>,
181192
object_downcast: object_downcast::<Box<dyn StdError + Send + Sync>>,
193+
#[cfg(anyhow_no_ptr_addr_of)]
182194
object_downcast_mut: object_downcast_mut::<Box<dyn StdError + Send + Sync>>,
183195
object_drop_rest: object_drop_front::<Box<dyn StdError + Send + Sync>>,
184196
#[cfg(all(not(backtrace), feature = "backtrace"))]
@@ -284,10 +296,11 @@ impl Error {
284296
let vtable = &ErrorVTable {
285297
object_drop: object_drop::<ContextError<C, Error>>,
286298
object_ref: object_ref::<ContextError<C, Error>>,
287-
#[cfg(feature = "std")]
299+
#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))]
288300
object_mut: object_mut::<ContextError<C, Error>>,
289301
object_boxed: object_boxed::<ContextError<C, Error>>,
290302
object_downcast: context_chain_downcast::<C>,
303+
#[cfg(anyhow_no_ptr_addr_of)]
291304
object_downcast_mut: context_chain_downcast_mut::<C>,
292305
object_drop_rest: context_chain_drop_rest::<C>,
293306
#[cfg(all(not(backtrace), feature = "backtrace"))]
@@ -396,14 +409,20 @@ impl Error {
396409
E: Display + Debug + Send + Sync + 'static,
397410
{
398411
let target = TypeId::of::<E>();
412+
let inner = self.inner.by_mut();
399413
unsafe {
400414
// Use vtable to find NonNull<()> which points to a value of type E
401415
// somewhere inside the data structure.
402-
let addr =
403-
match (vtable(self.inner.ptr).object_downcast_mut)(self.inner.by_mut(), target) {
404-
Some(addr) => addr.extend(),
405-
None => return Err(self),
406-
};
416+
#[cfg(not(anyhow_no_ptr_addr_of))]
417+
let addr = match (vtable(inner.ptr).object_downcast)(inner.by_ref(), target) {
418+
Some(addr) => addr.by_mut().extend(),
419+
None => return Err(self),
420+
};
421+
#[cfg(anyhow_no_ptr_addr_of)]
422+
let addr = match (vtable(inner.ptr).object_downcast_mut)(inner, target) {
423+
Some(addr) => addr.extend(),
424+
None => return Err(self),
425+
};
407426

408427
// Prepare to read E out of the data structure. We'll drop the rest
409428
// of the data structure separately so that E is not dropped.
@@ -477,7 +496,14 @@ impl Error {
477496
unsafe {
478497
// Use vtable to find NonNull<()> which points to a value of type E
479498
// somewhere inside the data structure.
499+
500+
#[cfg(not(anyhow_no_ptr_addr_of))]
501+
let addr =
502+
(vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?.by_mut();
503+
504+
#[cfg(anyhow_no_ptr_addr_of)]
480505
let addr = (vtable(self.inner.ptr).object_downcast_mut)(self.inner.by_mut(), target)?;
506+
481507
Some(addr.cast::<E>().deref_mut())
482508
}
483509
}
@@ -536,11 +562,12 @@ impl Drop for Error {
536562

537563
struct ErrorVTable {
538564
object_drop: unsafe fn(Own<ErrorImpl>),
539-
object_ref: unsafe fn(Ref<ErrorImpl>) -> &(dyn StdError + Send + Sync + 'static),
540-
#[cfg(feature = "std")]
565+
object_ref: unsafe fn(Ref<ErrorImpl>) -> Ref<dyn StdError + Send + Sync + 'static>,
566+
#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))]
541567
object_mut: unsafe fn(Mut<ErrorImpl>) -> &mut (dyn StdError + Send + Sync + 'static),
542568
object_boxed: unsafe fn(Own<ErrorImpl>) -> Box<dyn StdError + Send + Sync + 'static>,
543569
object_downcast: unsafe fn(Ref<ErrorImpl>, TypeId) -> Option<Ref<()>>,
570+
#[cfg(anyhow_no_ptr_addr_of)]
544571
object_downcast_mut: unsafe fn(Mut<ErrorImpl>, TypeId) -> Option<Mut<()>>,
545572
object_drop_rest: unsafe fn(Own<ErrorImpl>, TypeId),
546573
#[cfg(all(not(backtrace), feature = "backtrace"))]
@@ -566,17 +593,26 @@ unsafe fn object_drop_front<E>(e: Own<ErrorImpl>, target: TypeId) {
566593
}
567594

568595
// Safety: requires layout of *e to match ErrorImpl<E>.
569-
unsafe fn object_ref<E>(e: Ref<ErrorImpl>) -> &(dyn StdError + Send + Sync + 'static)
596+
unsafe fn object_ref<E>(e: Ref<ErrorImpl>) -> Ref<dyn StdError + Send + Sync + 'static>
570597
where
571598
E: StdError + Send + Sync + 'static,
572599
{
573600
// Attach E's native StdError vtable onto a pointer to self._object.
574-
&e.cast::<ErrorImpl<E>>().deref()._object
601+
602+
let unerased = e.cast::<ErrorImpl<E>>();
603+
604+
#[cfg(not(anyhow_no_ptr_addr_of))]
605+
return Ref::from_raw(NonNull::new_unchecked(
606+
ptr::addr_of!((*unerased.as_ptr())._object) as *mut E,
607+
));
608+
609+
#[cfg(anyhow_no_ptr_addr_of)]
610+
return Ref::new(&unerased.deref()._object);
575611
}
576612

577613
// Safety: requires layout of *e to match ErrorImpl<E>, and for `e` to be derived
578614
// from a `&mut`
579-
#[cfg(feature = "std")]
615+
#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))]
580616
unsafe fn object_mut<E>(e: Mut<ErrorImpl>) -> &mut (dyn StdError + Send + Sync + 'static)
581617
where
582618
E: StdError + Send + Sync + 'static,
@@ -602,14 +638,26 @@ where
602638
if TypeId::of::<E>() == target {
603639
// Caller is looking for an E pointer and e is ErrorImpl<E>, take a
604640
// pointer to its E field.
605-
let unerased = e.cast::<ErrorImpl<E>>().deref();
606-
Some(Ref::new(&unerased._object).cast::<()>())
641+
642+
let unerased = e.cast::<ErrorImpl<E>>();
643+
644+
#[cfg(not(anyhow_no_ptr_addr_of))]
645+
return Some(
646+
Ref::from_raw(NonNull::new_unchecked(
647+
ptr::addr_of!((*unerased.as_ptr())._object) as *mut E,
648+
))
649+
.cast::<()>(),
650+
);
651+
652+
#[cfg(anyhow_no_ptr_addr_of)]
653+
return Some(Ref::new(&unerased.deref()._object).cast::<()>());
607654
} else {
608655
None
609656
}
610657
}
611658

612659
// Safety: requires layout of *e to match ErrorImpl<E>.
660+
#[cfg(anyhow_no_ptr_addr_of)]
613661
unsafe fn object_downcast_mut<E>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>>
614662
where
615663
E: 'static,
@@ -649,7 +697,7 @@ where
649697
}
650698

651699
// Safety: requires layout of *e to match ErrorImpl<ContextError<C, E>>.
652-
#[cfg(feature = "std")]
700+
#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))]
653701
unsafe fn context_downcast_mut<C, E>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>>
654702
where
655703
C: 'static,
@@ -705,6 +753,7 @@ where
705753
}
706754

707755
// Safety: requires layout of *e to match ErrorImpl<ContextError<C, Error>>.
756+
#[cfg(anyhow_no_ptr_addr_of)]
708757
unsafe fn context_chain_downcast_mut<C>(e: Mut<ErrorImpl>, target: TypeId) -> Option<Mut<()>>
709758
where
710759
C: 'static,
@@ -798,14 +847,21 @@ impl ErrorImpl {
798847
pub(crate) unsafe fn error(this: Ref<Self>) -> &(dyn StdError + Send + Sync + 'static) {
799848
// Use vtable to attach E's native StdError vtable for the right
800849
// original type E.
801-
(vtable(this.ptr).object_ref)(this)
850+
(vtable(this.ptr).object_ref)(this).deref()
802851
}
803852

804853
#[cfg(feature = "std")]
805854
pub(crate) unsafe fn error_mut(this: Mut<Self>) -> &mut (dyn StdError + Send + Sync + 'static) {
806855
// Use vtable to attach E's native StdError vtable for the right
807856
// original type E.
808-
(vtable(this.ptr).object_mut)(this)
857+
858+
#[cfg(not(anyhow_no_ptr_addr_of))]
859+
return (vtable(this.ptr).object_ref)(this.by_ref())
860+
.by_mut()
861+
.deref_mut();
862+
863+
#[cfg(anyhow_no_ptr_addr_of)]
864+
return (vtable(this.ptr).object_mut)(this);
809865
}
810866

811867
#[cfg(any(backtrace, feature = "backtrace"))]

src/ptr.rs

+30
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,34 @@ where
9191
}
9292
}
9393

94+
#[cfg(not(anyhow_no_ptr_addr_of))]
95+
pub fn from_raw(ptr: NonNull<T>) -> Self {
96+
Ref {
97+
ptr,
98+
lifetime: PhantomData,
99+
}
100+
}
101+
94102
pub fn cast<U: CastTo>(self) -> Ref<'a, U::Target> {
95103
Ref {
96104
ptr: self.ptr.cast(),
97105
lifetime: PhantomData,
98106
}
99107
}
100108

109+
#[cfg(not(anyhow_no_ptr_addr_of))]
110+
pub fn by_mut(self) -> Mut<'a, T> {
111+
Mut {
112+
ptr: self.ptr,
113+
lifetime: PhantomData,
114+
}
115+
}
116+
117+
#[cfg(not(anyhow_no_ptr_addr_of))]
118+
pub fn as_ptr(self) -> *const T {
119+
self.ptr.as_ptr() as *const T
120+
}
121+
101122
pub unsafe fn deref(self) -> &'a T {
102123
&*self.ptr.as_ptr()
103124
}
@@ -127,6 +148,7 @@ impl<'a, T> Mut<'a, T>
127148
where
128149
T: ?Sized,
129150
{
151+
#[cfg(anyhow_no_ptr_addr_of)]
130152
pub fn new(ptr: &'a mut T) -> Self {
131153
Mut {
132154
ptr: NonNull::from(ptr),
@@ -141,6 +163,14 @@ where
141163
}
142164
}
143165

166+
#[cfg(not(anyhow_no_ptr_addr_of))]
167+
pub fn by_ref(self) -> Ref<'a, T> {
168+
Ref {
169+
ptr: self.ptr,
170+
lifetime: PhantomData,
171+
}
172+
}
173+
144174
pub fn extend<'b>(self) -> Mut<'b, T> {
145175
Mut {
146176
ptr: self.ptr,

0 commit comments

Comments
 (0)