Closed Kixunil closed 1 month ago
Note this is a pretty incomplete feature so there may be some things that just haven't gotten updated yet, but it is good to have the bug report.
@rustbot label +F-derive_smart_pointer +T-compiler -needs-triage
Thank you for catching this. It looks like we will need this to be fixed before we can use the macro for its intended purpose with linked lists, as the relevant smart pointer is defined with a trait bound:
#[repr(transparent)]
pub struct ListArc<T, const ID: u64 = 0>
where
T: ListArcSafe<ID> + ?Sized,
{
arc: Arc<T>,
}
It would make sense to add a test that ensures that the relevant parts of the linked list example compiles. (link 1, link 2).
cc @dingxiangfei2009
Oh, I've just noticed that when you expand the macro the bounds are not applied to the __S
parameter which needs them too because it's used as an argument into Ptr
generics. It looks like #125575 doesn't copy the bounds (but I have no compiler knowledge so this is just an educated guess). Edit: I've linked it below.
cc @Darksonn I have one open question. There could be more convoluted bounds that involves the pointee type like the following.
#[derive(SmartPointer)]
#[repr(transparent)]
pub struct Ptr<#[pointee] T>
where
T: Trait<T>,
{ .. }
pub trait Trait<U> { .. }
For now, #127681 does not rewrite T
into __S
. Should the macro apply this substitution? I feel that the answer is probably "depends".
This is what I have in the RFC:
For every trait bound declared on the trait, add it twice to the trait implementation. Once exactly as written, and once with every instance of the #[pointee] parameter replaced with U.
Does that work?
Okay #127681 is updated, so that given a #[pointee] T
generic parameter a U: Trait<T>
bound is commuted to a U: Trait<__S>
bound at both the generic and where-clause position, regardless of whether U
is bound or free.
So now
struct<#[pointee] T, U: Trait<T>>...
generates an impl<T, __S: Unsize<T> + ?Sized, U: Trait<T> + Trait<__S>>
struct<#[pointee] T: Trait<T>>...
generates an impl<T: Trait<T>, __S: Unsize<T> + ?Sized + Trait<__S>>
struct<#[pointee] T: Trait<T>> where SomeType<T>: Trait<T> + ...
generates an impl<T: Trait<T>, __S: Unsize<T> + ?Sized> where SomeType<T>: Trait<T> + ..., SomeType<__S>: Trait<__S> + ...
Tests are added for these cases.
When deriving
SmartPointer
on a struct with additional bounds the resultingimpl
is missing a bound resulting in a compile error. This behavior was not explicitly mentioned inSmartPointer
RFC, so I assume it's a bug. See #123430I tried this code: (playground)
I expected to see this happen: the code compiles and provides a smart pointer that executes
on_drop
when the smart pointer is dropped.Instead, this happened: compile error:
Meta
rustc --version --verbose
: