You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I found this question on SO where two more or less identical calls to Rc::ptr_eq return different results, depending on where the Rc<RefCell<_>> is cast to a trait object but also how the program is compiled. It behaves inconsistently when the function in question is not inlined or when incremental compilation is turned on. I've whittled it down to a smaller example (though it can probably be reduced further):
use std::{cell::RefCell, rc::Rc};structS;traitT{}implTforS{}structC{r:Rc<RefCell<dynT>>,}implC{fnhas_dyn_other(&self,other:&Rc<RefCell<dynT>>) -> bool{Rc::ptr_eq(&self.r, other)}fnhas_other<A:T + 'static>(&self,other:&Rc<RefCell<A>>) -> bool{Rc::ptr_eq(&self.r,&(Rc::clone(other)asRc<RefCell<dynT>>))}}#[test]fnweird_trait_obj(){let s = Rc::new(RefCell::new(S));let c = C{r:Rc::clone(&s)asRc<RefCell<dynT>>,};// passesassert!(Rc::ptr_eq(&(Rc::clone(&s)asRc<RefCell<dyn T>>), &c.r));// passesassert!(Rc::ptr_eq(
&(Rc::clone(&s)asRc<RefCell<dyn T>>),
&(Rc::clone(&s)asRc<RefCell<dyn T>>)));// passesassert!(c.has_dyn_other(&(Rc::clone(&s)asRc<RefCell<dyn T>>)));// passes with `incremental = false` or `#[inline(always)]`, fails otherwiseassert!(c.has_other(&s));}
I expected to see this happen: I would have thought either all or none of the asserts would pass regardless of how it's compiled. I don't know how Rc<RefCell<T>> as Rc<RefCell<dyn Trait>> actually works, so I'm not sure which one. I'm guessing it looks more like Rc<dyn RefCell<Trait>> where the Rc points at a trait object that in turn points at the RefCell as its instance? I don't know how else it might work.
Instead, this happened: That last test is sensitive to at least two distinct factors: is incremental compilation on and is C::has_other inlined or not. Adding #[inline(always)] makes the assert pass regardless of incremental compilation.
thread 'weird_trait_obj' panicked at 'assertion failed: c.has_other(&s)', src/lib.rs:37:5
stack backtrace:
0: rust_begin_unwind
at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/std/src/panicking.rs:584:5
1: core::panicking::panic_fmt
at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/panicking.rs:142:14
2: core::panicking::panic
at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/panicking.rs:48:5
3: rcrefcelltest::weird_trait_obj
at ./src/lib.rs:37:5
4: rcrefcelltest::weird_trait_obj::{{closure}}
at ./src/lib.rs:21:1
5: core::ops::function::FnOnce::call_once
at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/ops/function.rs:248:5
6: core::ops::function::FnOnce::call_once
at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/ops/function.rs:248:5
The text was updated successfully, but these errors were encountered:
Returns true if the two Rcs point to the same allocation in a vein similar to ptr::eq. See that function for caveats when comparing dyn Trait pointers.
I found this question on SO where two more or less identical calls to
Rc::ptr_eq
return different results, depending on where theRc<RefCell<_>>
is cast to a trait object but also how the program is compiled. It behaves inconsistently when the function in question is not inlined or when incremental compilation is turned on. I've whittled it down to a smaller example (though it can probably be reduced further):I expected to see this happen: I would have thought either all or none of the asserts would pass regardless of how it's compiled. I don't know how
Rc<RefCell<T>> as Rc<RefCell<dyn Trait>>
actually works, so I'm not sure which one. I'm guessing it looks more likeRc<dyn RefCell<Trait>>
where theRc
points at a trait object that in turn points at theRefCell
as its instance? I don't know how else it might work.Instead, this happened: That last test is sensitive to at least two distinct factors: is incremental compilation on and is
C::has_other
inlined or not. Adding#[inline(always)]
makes the assert pass regardless of incremental compilation.Meta
rustc --version --verbose
:Backtrace
The text was updated successfully, but these errors were encountered: