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
{{ message }}
Repository navigation
Trait bounds not properly propagated in #[derive(SmartPointer)] #127647
When deriving SmartPointer on a struct with additional bounds the resulting impl is missing a bound resulting in a compile error. This behavior was not explicitly mentioned in SmartPointer RFC, so I assume it's a bug. See #123430
#![feature(derive_smart_pointer)]#[derive(core::marker::SmartPointer)]#[repr(transparent)]// Remove the OnDrop bound to make it compile but then the functionality is lostpubstructPtr<'a,#[pointee]T:OnDrop + ?Sized,X>{data:&'amutT,x: core::marker::PhantomData<X>,}pubtraitOnDrop{fnon_drop(&mutself);}
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:
error[E0277]: the trait bound `__S: OnDrop` is not satisfied
--> src/lib.rs:3:10
|
3 | #[derive(core::marker::SmartPointer)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `OnDrop` is not implemented for `__S`
|
note: required by a bound in `Ptr`
--> src/lib.rs:6:34
|
6 | pub struct Ptr<'a, #[pointee] T: OnDrop + ?Sized, X> {
| ^^^^^^ required by this bound in `Ptr`
= note: this error originates in the derive macro `core::marker::SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` (lib) due to 1 previous error
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:
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.
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.
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.
Activity
tgross35 commentedon Jul 12, 2024
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
Darksonn commentedon Jul 12, 2024
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:
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
Kixunil commentedon Jul 13, 2024
Oh, I've just noticed that when you expand the macro the bounds are not applied to the
__Sparameter which needs them too because it's used as an argument intoPtrgenerics. 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.dingxiangfei2009 commentedon Jul 13, 2024
cc @Darksonn I have one open question. There could be more convoluted bounds that involves the pointee type like the following.
For now, #127681 does not rewrite
Tinto__S. Should the macro apply this substitution? I feel that the answer is probably "depends".Darksonn commentedon Jul 13, 2024
This is what I have in the RFC:
Does that work?
dingxiangfei2009 commentedon Jul 13, 2024
Okay #127681 is updated, so that given a
#[pointee] Tgeneric parameter aU: Trait<T>bound is commuted to aU: Trait<__S>bound at both the generic and where-clause position, regardless of whetherUis bound or free.So now
struct<#[pointee] T, U: Trait<T>>...generates animpl<T, __S: Unsize<T> + ?Sized, U: Trait<T> + Trait<__S>>struct<#[pointee] T: Trait<T>>...generates animpl<T: Trait<T>, __S: Unsize<T> + ?Sized + Trait<__S>>struct<#[pointee] T: Trait<T>> where SomeType<T>: Trait<T> + ...generates animpl<T: Trait<T>, __S: Unsize<T> + ?Sized> where SomeType<T>: Trait<T> + ..., SomeType<__S>: Trait<__S> + ...Tests are added for these cases.
Rollup merge of rust-lang#127681 - dingxiangfei2009:smart-ptr-bounds,…
Rollup merge of rust-lang#127681 - dingxiangfei2009:smart-ptr-bounds,…
Rollup merge of rust-lang#127681 - dingxiangfei2009:smart-ptr-bounds,…
Unrolled build for rust-lang#127681