reject pointee without ?Sized

This commit is contained in:
Ding Xiang Fei 2024-07-31 22:50:45 +08:00
parent 99322d84c4
commit 14a0963f96
No known key found for this signature in database
GPG Key ID: 3CD748647EEF6359
3 changed files with 69 additions and 37 deletions

View File

@ -1,5 +1,3 @@
use std::mem::swap;
use ast::ptr::P;
use ast::HasAttrs;
use rustc_ast::mut_visit::MutVisitor;
@ -154,13 +152,28 @@ pub fn expand_deriving_smart_ptr(
{
let pointee = &mut impl_generics.params[pointee_param_idx];
self_bounds = pointee.bounds.clone();
if !contains_maybe_sized_bound(&self_bounds)
&& !contains_maybe_sized_bound_on_pointee(
&generics.where_clause.predicates,
pointee_ty_ident.name,
)
{
cx.dcx()
.struct_span_err(
pointee_ty_ident.span,
format!(
"`derive(SmartPointer)` requires {} to be marked `?Sized`",
pointee_ty_ident.name
),
)
.emit();
return;
}
let arg = GenericArg::Type(s_ty.clone());
let unsize = cx.path_all(span, true, path!(span, core::marker::Unsize), vec![arg]);
pointee.bounds.push(cx.trait_bound(unsize, false));
let mut attrs = thin_vec![];
swap(&mut pointee.attrs, &mut attrs);
// Drop `#[pointee]` attribute since it should not be recognized outside `derive(SmartPointer)`
pointee.attrs = attrs.into_iter().filter(|attr| !attr.has_name(sym::pointee)).collect();
pointee.attrs.retain(|attr| !attr.has_name(sym::pointee));
}
// # Rewrite generic parameter bounds
@ -169,14 +182,14 @@ pub fn expand_deriving_smart_ptr(
// ```
// struct<
// U: Trait<T>,
// #[pointee] T: Trait<T>,
// #[pointee] T: Trait<T> + ?Sized,
// V: Trait<T>> ...
// ```
// ... generates this `impl` generic parameters
// ```
// impl<
// U: Trait<T> + Trait<__S>,
// T: Trait<T> + Unsize<__S>, // (**)
// T: Trait<T> + ?Sized + Unsize<__S>, // (**)
// __S: Trait<__S> + ?Sized, // (*)
// V: Trait<T> + Trait<__S>> ...
// ```
@ -218,23 +231,6 @@ pub fn expand_deriving_smart_ptr(
//
// We now insert `__S` with the missing bounds marked with (*) above.
// We should also write the bounds from `#[pointee]` to `__S` as required by `Unsize<__S>`.
let sized = cx.path_global(span, path!(span, core::marker::Sized));
// For some reason, we are not allowed to write `?Sized` bound twice like `__S: ?Sized + ?Sized`.
if !contains_maybe_sized_bound(&self_bounds)
&& !contains_maybe_sized_bound_on_pointee(
&generics.where_clause.predicates,
pointee_ty_ident.name,
)
{
self_bounds.push(GenericBound::Trait(
cx.poly_trait_ref(span, sized),
TraitBoundModifiers {
polarity: ast::BoundPolarity::Maybe(span),
constness: ast::BoundConstness::Never,
asyncness: ast::BoundAsyncness::Normal,
},
));
}
{
let mut substitution =
TypeSubstitution { from_name: pointee_ty_ident.name, to_ty: &s_ty, rewritten: false };
@ -252,7 +248,7 @@ pub fn expand_deriving_smart_ptr(
// where
// U: Trait<V> + Trait<T>,
// Companion<T>: Trait<T>,
// T: Trait<T>,
// T: Trait<T> + ?Sized,
// { .. }
// ```
// ... will have a impl prelude like so
@ -263,8 +259,8 @@ pub fn expand_deriving_smart_ptr(
// U: Trait<__S>,
// Companion<T>: Trait<T>,
// Companion<__S>: Trait<__S>,
// T: Trait<T>,
// __S: Trait<__S>,
// T: Trait<T> + ?Sized,
// __S: Trait<__S> + ?Sized,
// ```
//
// We should also write a few new `where` bounds from `#[pointee] T` to `__S`

View File

@ -1,5 +1,6 @@
#![feature(derive_smart_pointer, arbitrary_self_types)]
extern crate core;
use std::marker::SmartPointer;
#[derive(SmartPointer)]
@ -35,6 +36,13 @@ struct NotTransparent<'a, #[pointee] T: ?Sized> {
ptr: &'a T,
}
#[derive(SmartPointer)]
#[repr(transparent)]
struct NoMaybeSized<'a, #[pointee] T> {
//~^ ERROR: `derive(SmartPointer)` requires T to be marked `?Sized`
ptr: &'a T,
}
// However, reordering attributes should work nevertheless.
#[repr(transparent)]
#[derive(SmartPointer)]
@ -42,4 +50,26 @@ struct ThisIsAPossibleSmartPointer<'a, #[pointee] T: ?Sized> {
ptr: &'a T,
}
// Also, these paths to Sized should work
#[derive(SmartPointer)]
#[repr(transparent)]
struct StdSized<'a, #[pointee] T: ?std::marker::Sized> {
ptr: &'a T,
}
#[derive(SmartPointer)]
#[repr(transparent)]
struct CoreSized<'a, #[pointee] T: ?core::marker::Sized> {
ptr: &'a T,
}
#[derive(SmartPointer)]
#[repr(transparent)]
struct GlobalStdSized<'a, #[pointee] T: ?::std::marker::Sized> {
ptr: &'a T,
}
#[derive(SmartPointer)]
#[repr(transparent)]
struct GlobalCoreSized<'a, #[pointee] T: ?::core::marker::Sized> {
ptr: &'a T,
}
fn main() {}

View File

@ -1,5 +1,5 @@
error: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`
--> $DIR/deriving-smart-pointer-neg.rs:5:10
--> $DIR/deriving-smart-pointer-neg.rs:6:10
|
LL | #[derive(SmartPointer)]
| ^^^^^^^^^^^^
@ -7,7 +7,7 @@ LL | #[derive(SmartPointer)]
= 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
--> $DIR/deriving-smart-pointer-neg.rs:11:10
--> $DIR/deriving-smart-pointer-neg.rs:12:10
|
LL | #[derive(SmartPointer)]
| ^^^^^^^^^^^^
@ -15,7 +15,7 @@ LL | #[derive(SmartPointer)]
= 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
--> $DIR/deriving-smart-pointer-neg.rs:18:10
--> $DIR/deriving-smart-pointer-neg.rs:19:10
|
LL | #[derive(SmartPointer)]
| ^^^^^^^^^^^^
@ -23,7 +23,7 @@ LL | #[derive(SmartPointer)]
= 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
--> $DIR/deriving-smart-pointer-neg.rs:25:10
--> $DIR/deriving-smart-pointer-neg.rs:26:10
|
LL | #[derive(SmartPointer)]
| ^^^^^^^^^^^^
@ -31,15 +31,21 @@ LL | #[derive(SmartPointer)]
= 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 `#[repr(transparent)]`
--> $DIR/deriving-smart-pointer-neg.rs:32:10
--> $DIR/deriving-smart-pointer-neg.rs:33: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: `derive(SmartPointer)` requires T to be marked `?Sized`
--> $DIR/deriving-smart-pointer-neg.rs:41:36
|
LL | struct NoMaybeSized<'a, #[pointee] T> {
| ^
error[E0392]: lifetime parameter `'a` is never used
--> $DIR/deriving-smart-pointer-neg.rs:21:16
--> $DIR/deriving-smart-pointer-neg.rs:22:16
|
LL | struct NoField<'a, #[pointee] T: ?Sized> {}
| ^^ unused lifetime parameter
@ -47,7 +53,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`
error[E0392]: type parameter `T` is never used
--> $DIR/deriving-smart-pointer-neg.rs:21:31
--> $DIR/deriving-smart-pointer-neg.rs:22:31
|
LL | struct NoField<'a, #[pointee] T: ?Sized> {}
| ^ unused type parameter
@ -55,7 +61,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`
error[E0392]: lifetime parameter `'a` is never used
--> $DIR/deriving-smart-pointer-neg.rs:28:20
--> $DIR/deriving-smart-pointer-neg.rs:29:20
|
LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
| ^^ unused lifetime parameter
@ -63,13 +69,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`
error[E0392]: type parameter `T` is never used
--> $DIR/deriving-smart-pointer-neg.rs:28:35
--> $DIR/deriving-smart-pointer-neg.rs:29:35
|
LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
| ^ unused type parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
error: aborting due to 9 previous errors
error: aborting due to 10 previous errors
For more information about this error, try `rustc --explain E0392`.