Rollup merge of #129467 - dingxiangfei2009:smart-pointer-relax-pointee, r=compiler-errors
derive(SmartPointer): assume pointee from the single generic and better error messages Fix #129465 Actually RFC says that `#[pointee]` can be inferred when there is no ambiguity, or there is only one generic type parameter so to say. cc ```@Darksonn``` r? ```@compiler-errors```
This commit is contained in:
commit
d2418cb888
@ -11,7 +11,6 @@
|
|||||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||||
use rustc_span::symbol::{sym, Ident};
|
use rustc_span::symbol::{sym, Ident};
|
||||||
use rustc_span::{Span, Symbol};
|
use rustc_span::{Span, Symbol};
|
||||||
use smallvec::{smallvec, SmallVec};
|
|
||||||
use thin_vec::{thin_vec, ThinVec};
|
use thin_vec::{thin_vec, ThinVec};
|
||||||
|
|
||||||
macro_rules! path {
|
macro_rules! path {
|
||||||
@ -68,43 +67,63 @@ pub(crate) fn expand_deriving_smart_ptr(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Convert generic parameters (from the struct) into generic args.
|
// Convert generic parameters (from the struct) into generic args.
|
||||||
let mut pointee_param = None;
|
let self_params: Vec<_> = generics
|
||||||
let mut multiple_pointee_diag: SmallVec<[_; 2]> = smallvec![];
|
.params
|
||||||
let self_params = generics
|
.iter()
|
||||||
|
.map(|p| match p.kind {
|
||||||
|
GenericParamKind::Lifetime => GenericArg::Lifetime(cx.lifetime(p.span(), p.ident)),
|
||||||
|
GenericParamKind::Type { .. } => GenericArg::Type(cx.ty_ident(p.span(), p.ident)),
|
||||||
|
GenericParamKind::Const { .. } => GenericArg::Const(cx.const_ident(p.span(), p.ident)),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let type_params: Vec<_> = generics
|
||||||
.params
|
.params
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(idx, p)| match p.kind {
|
.filter_map(|(idx, p)| {
|
||||||
GenericParamKind::Lifetime => GenericArg::Lifetime(cx.lifetime(p.span(), p.ident)),
|
if let GenericParamKind::Type { .. } = p.kind {
|
||||||
GenericParamKind::Type { .. } => {
|
Some((idx, p.span(), p.attrs().iter().any(|attr| attr.has_name(sym::pointee))))
|
||||||
if p.attrs().iter().any(|attr| attr.has_name(sym::pointee)) {
|
|
||||||
if pointee_param.is_some() {
|
|
||||||
multiple_pointee_diag.push(cx.dcx().struct_span_err(
|
|
||||||
p.span(),
|
|
||||||
"`SmartPointer` can only admit one type as pointee",
|
|
||||||
));
|
|
||||||
} else {
|
} else {
|
||||||
pointee_param = Some(idx);
|
None
|
||||||
}
|
}
|
||||||
}
|
|
||||||
GenericArg::Type(cx.ty_ident(p.span(), p.ident))
|
|
||||||
}
|
|
||||||
GenericParamKind::Const { .. } => GenericArg::Const(cx.const_ident(p.span(), p.ident)),
|
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect();
|
||||||
let Some(pointee_param_idx) = pointee_param else {
|
|
||||||
|
let pointee_param_idx = if type_params.is_empty() {
|
||||||
|
// `#[derive(SmartPointer)]` requires at least one generic type on the target `struct`
|
||||||
cx.dcx().struct_span_err(
|
cx.dcx().struct_span_err(
|
||||||
span,
|
span,
|
||||||
"At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits",
|
"`SmartPointer` can only be derived on `struct`s that are generic over at least one type",
|
||||||
).emit();
|
).emit();
|
||||||
return;
|
return;
|
||||||
};
|
} else if type_params.len() == 1 {
|
||||||
if !multiple_pointee_diag.is_empty() {
|
// Regardless of the only type param being designed as `#[pointee]` or not, we can just use it as such
|
||||||
for diag in multiple_pointee_diag {
|
type_params[0].0
|
||||||
diag.emit();
|
} else {
|
||||||
}
|
let mut pointees = type_params
|
||||||
|
.iter()
|
||||||
|
.filter_map(|&(idx, span, is_pointee)| is_pointee.then_some((idx, span)))
|
||||||
|
.fuse();
|
||||||
|
match (pointees.next(), pointees.next()) {
|
||||||
|
(Some((idx, _span)), None) => idx,
|
||||||
|
(None, _) => {
|
||||||
|
cx.dcx().struct_span_err(
|
||||||
|
span,
|
||||||
|
"exactly one generic type parameter must be marked as #[pointee] to derive SmartPointer traits",
|
||||||
|
).emit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
(Some((_, one)), Some((_, another))) => {
|
||||||
|
cx.dcx()
|
||||||
|
.struct_span_err(
|
||||||
|
vec![one, another],
|
||||||
|
"only one type parameter can be marked as `#[pointee]` when deriving SmartPointer traits",
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Create the type of `self`.
|
// Create the type of `self`.
|
||||||
let path = cx.path_all(span, false, vec![name_ident], self_params.clone());
|
let path = cx.path_all(span, false, vec![name_ident], self_params.clone());
|
||||||
|
@ -20,3 +20,9 @@ pub struct MyPointer2<'a, Y, Z: MyTrait<T>, #[pointee] T: ?Sized + MyTrait<T>, X
|
|||||||
data: &'a mut T,
|
data: &'a mut T,
|
||||||
x: core::marker::PhantomData<X>,
|
x: core::marker::PhantomData<X>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(SmartPointer)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
struct MyPointerWithoutPointee<'a, T: ?Sized> {
|
||||||
|
ptr: &'a T,
|
||||||
|
}
|
||||||
|
@ -42,3 +42,18 @@ impl<'a, Y, Z: MyTrait<T> + MyTrait<__S>, T: ?Sized + MyTrait<T> +
|
|||||||
MyTrait<__S>> ::core::ops::CoerceUnsized<MyPointer2<'a, Y, Z, __S, X>> for
|
MyTrait<__S>> ::core::ops::CoerceUnsized<MyPointer2<'a, Y, Z, __S, X>> for
|
||||||
MyPointer2<'a, Y, Z, T, X> where Y: MyTrait<T>, Y: MyTrait<__S> {
|
MyPointer2<'a, Y, Z, T, X> where Y: MyTrait<T>, Y: MyTrait<__S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
struct MyPointerWithoutPointee<'a, T: ?Sized> {
|
||||||
|
ptr: &'a T,
|
||||||
|
}
|
||||||
|
#[automatically_derived]
|
||||||
|
impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized>
|
||||||
|
::core::ops::DispatchFromDyn<MyPointerWithoutPointee<'a, __S>> for
|
||||||
|
MyPointerWithoutPointee<'a, T> {
|
||||||
|
}
|
||||||
|
#[automatically_derived]
|
||||||
|
impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized>
|
||||||
|
::core::ops::CoerceUnsized<MyPointerWithoutPointee<'a, __S>> for
|
||||||
|
MyPointerWithoutPointee<'a, T> {
|
||||||
|
}
|
||||||
|
@ -9,13 +9,6 @@ enum NotStruct<'a, T: ?Sized> {
|
|||||||
Variant(&'a T),
|
Variant(&'a T),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(SmartPointer)]
|
|
||||||
//~^ ERROR: At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits
|
|
||||||
#[repr(transparent)]
|
|
||||||
struct NoPointee<'a, T: ?Sized> {
|
|
||||||
ptr: &'a T,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(SmartPointer)]
|
#[derive(SmartPointer)]
|
||||||
//~^ ERROR: `SmartPointer` can only be derived on `struct`s with at least one field
|
//~^ ERROR: `SmartPointer` can only be derived on `struct`s with at least one field
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
@ -30,6 +23,23 @@ struct NoField<'a, #[pointee] T: ?Sized> {}
|
|||||||
//~^ ERROR: lifetime parameter `'a` is never used
|
//~^ ERROR: lifetime parameter `'a` is never used
|
||||||
//~| ERROR: type parameter `T` is never used
|
//~| ERROR: type parameter `T` is never used
|
||||||
|
|
||||||
|
#[derive(SmartPointer)]
|
||||||
|
//~^ ERROR: `SmartPointer` can only be derived on `struct`s that are generic over at least one type
|
||||||
|
#[repr(transparent)]
|
||||||
|
struct NoGeneric<'a>(&'a u8);
|
||||||
|
|
||||||
|
#[derive(SmartPointer)]
|
||||||
|
//~^ ERROR: exactly one generic type parameter must be marked as #[pointee] to derive SmartPointer traits
|
||||||
|
#[repr(transparent)]
|
||||||
|
struct AmbiguousPointee<'a, T1: ?Sized, T2: ?Sized> {
|
||||||
|
a: (&'a T1, &'a T2),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(SmartPointer)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &'a B));
|
||||||
|
//~^ ERROR: only one type parameter can be marked as `#[pointee]` when deriving SmartPointer traits
|
||||||
|
|
||||||
#[derive(SmartPointer)]
|
#[derive(SmartPointer)]
|
||||||
//~^ ERROR: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`
|
//~^ ERROR: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`
|
||||||
struct NotTransparent<'a, #[pointee] T: ?Sized> {
|
struct NotTransparent<'a, #[pointee] T: ?Sized> {
|
||||||
|
@ -6,7 +6,7 @@ LL | #[derive(SmartPointer)]
|
|||||||
|
|
|
|
||||||
= note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits
|
error: `SmartPointer` can only be derived on `struct`s with at least one field
|
||||||
--> $DIR/deriving-smart-pointer-neg.rs:12:10
|
--> $DIR/deriving-smart-pointer-neg.rs:12:10
|
||||||
|
|
|
|
||||||
LL | #[derive(SmartPointer)]
|
LL | #[derive(SmartPointer)]
|
||||||
@ -22,7 +22,7 @@ LL | #[derive(SmartPointer)]
|
|||||||
|
|
|
|
||||||
= note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: `SmartPointer` can only be derived on `struct`s with at least one field
|
error: `SmartPointer` can only be derived on `struct`s that are generic over at least one type
|
||||||
--> $DIR/deriving-smart-pointer-neg.rs:26:10
|
--> $DIR/deriving-smart-pointer-neg.rs:26:10
|
||||||
|
|
|
|
||||||
LL | #[derive(SmartPointer)]
|
LL | #[derive(SmartPointer)]
|
||||||
@ -30,8 +30,22 @@ LL | #[derive(SmartPointer)]
|
|||||||
|
|
|
|
||||||
= note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: exactly one generic type parameter must be marked as #[pointee] to derive SmartPointer traits
|
||||||
|
--> $DIR/deriving-smart-pointer-neg.rs:31:10
|
||||||
|
|
|
||||||
|
LL | #[derive(SmartPointer)]
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: only one type parameter can be marked as `#[pointee]` when deriving SmartPointer traits
|
||||||
|
--> $DIR/deriving-smart-pointer-neg.rs:40:39
|
||||||
|
|
|
||||||
|
LL | struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &'a B));
|
||||||
|
| ^ ^
|
||||||
|
|
||||||
error: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`
|
error: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`
|
||||||
--> $DIR/deriving-smart-pointer-neg.rs:33:10
|
--> $DIR/deriving-smart-pointer-neg.rs:43:10
|
||||||
|
|
|
|
||||||
LL | #[derive(SmartPointer)]
|
LL | #[derive(SmartPointer)]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
@ -39,13 +53,13 @@ LL | #[derive(SmartPointer)]
|
|||||||
= note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: `derive(SmartPointer)` requires T to be marked `?Sized`
|
error: `derive(SmartPointer)` requires T to be marked `?Sized`
|
||||||
--> $DIR/deriving-smart-pointer-neg.rs:41:36
|
--> $DIR/deriving-smart-pointer-neg.rs:51:36
|
||||||
|
|
|
|
||||||
LL | struct NoMaybeSized<'a, #[pointee] T> {
|
LL | struct NoMaybeSized<'a, #[pointee] T> {
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
error[E0392]: lifetime parameter `'a` is never used
|
error[E0392]: lifetime parameter `'a` is never used
|
||||||
--> $DIR/deriving-smart-pointer-neg.rs:22:16
|
--> $DIR/deriving-smart-pointer-neg.rs:15:16
|
||||||
|
|
|
|
||||||
LL | struct NoField<'a, #[pointee] T: ?Sized> {}
|
LL | struct NoField<'a, #[pointee] T: ?Sized> {}
|
||||||
| ^^ unused lifetime parameter
|
| ^^ unused lifetime parameter
|
||||||
@ -53,7 +67,7 @@ LL | struct NoField<'a, #[pointee] T: ?Sized> {}
|
|||||||
= help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
|
= help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
|
||||||
|
|
||||||
error[E0392]: type parameter `T` is never used
|
error[E0392]: type parameter `T` is never used
|
||||||
--> $DIR/deriving-smart-pointer-neg.rs:22:31
|
--> $DIR/deriving-smart-pointer-neg.rs:15:31
|
||||||
|
|
|
|
||||||
LL | struct NoField<'a, #[pointee] T: ?Sized> {}
|
LL | struct NoField<'a, #[pointee] T: ?Sized> {}
|
||||||
| ^ unused type parameter
|
| ^ unused type parameter
|
||||||
@ -61,7 +75,7 @@ LL | struct NoField<'a, #[pointee] T: ?Sized> {}
|
|||||||
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
|
||||||
|
|
||||||
error[E0392]: lifetime parameter `'a` is never used
|
error[E0392]: lifetime parameter `'a` is never used
|
||||||
--> $DIR/deriving-smart-pointer-neg.rs:29:20
|
--> $DIR/deriving-smart-pointer-neg.rs:22:20
|
||||||
|
|
|
|
||||||
LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
|
LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
|
||||||
| ^^ unused lifetime parameter
|
| ^^ unused lifetime parameter
|
||||||
@ -69,13 +83,13 @@ LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
|
|||||||
= help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
|
= help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
|
||||||
|
|
||||||
error[E0392]: type parameter `T` is never used
|
error[E0392]: type parameter `T` is never used
|
||||||
--> $DIR/deriving-smart-pointer-neg.rs:29:35
|
--> $DIR/deriving-smart-pointer-neg.rs:22:35
|
||||||
|
|
|
|
||||||
LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
|
LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
|
||||||
| ^ unused type parameter
|
| ^ unused type parameter
|
||||||
|
|
|
|
||||||
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
|
||||||
|
|
||||||
error: aborting due to 10 previous errors
|
error: aborting due to 12 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0392`.
|
For more information about this error, try `rustc --explain E0392`.
|
||||||
|
Loading…
Reference in New Issue
Block a user