1
Fork 0

Rollup merge of #136107 - dingxiangfei2009:coerce-pointee-wellformed, r=compiler-errors

Introduce CoercePointeeWellformed for coherence checks at typeck stage

Fix #135206

This is the first PR to introduce the "wellformedness" check for `derive(CoercePointee)`.

This patch introduces a new error code to cover all the prerequisites of the said macro. The checks that is enforced with this patch is whether the data is indeed `struct` and whether the layout is set to `repr(transparent)`.

A following series of patch will arrive later to address the following concern.
1. #135217 so that we would only admit one single coercion on one type parameter, and leave the rest for future consideration in tandem of development of other coercion rules.
1. Enforcement of data field requirements.

**An open question** is whether there is a good schema to encode the `#[pointee]` as well, so that we could also check if the `#[pointee]` type parameter is indeed `?Sized`.

``@rustbot`` label F-derive_coerce_pointee
This commit is contained in:
Matthias Krüger 2025-02-11 02:53:42 +01:00 committed by GitHub
commit af3c51d849
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 385 additions and 54 deletions

View file

@ -3,11 +3,11 @@ use ast::ptr::P;
use rustc_ast::mut_visit::MutVisitor;
use rustc_ast::visit::BoundKind;
use rustc_ast::{
self as ast, GenericArg, GenericBound, GenericParamKind, ItemKind, MetaItem,
self as ast, GenericArg, GenericBound, GenericParamKind, Generics, ItemKind, MetaItem,
TraitBoundModifiers, VariantData, WherePredicate,
};
use rustc_attr_parsing as attr;
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_errors::E0802;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_macros::Diagnostic;
use rustc_span::{Ident, Span, Symbol, sym};
@ -32,15 +32,6 @@ pub(crate) fn expand_deriving_coerce_pointee(
let (name_ident, generics) = if let Annotatable::Item(aitem) = item
&& let ItemKind::Struct(struct_data, g) = &aitem.kind
{
let is_transparent = aitem.attrs.iter().any(|attr| {
attr::find_repr_attrs(cx.sess, attr)
.into_iter()
.any(|r| matches!(r, attr::ReprTransparent))
});
if !is_transparent {
cx.dcx().emit_err(RequireTransparent { span });
return;
}
if !matches!(
struct_data,
VariantData::Struct { fields, recovered: _ } | VariantData::Tuple(fields, _)
@ -88,8 +79,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
} else {
let mut pointees = type_params
.iter()
.filter_map(|&(idx, span, is_pointee)| is_pointee.then_some((idx, span)))
.fuse();
.filter_map(|&(idx, span, is_pointee)| is_pointee.then_some((idx, span)));
match (pointees.next(), pointees.next()) {
(Some((idx, _span)), None) => idx,
(None, _) => {
@ -110,6 +100,52 @@ pub(crate) fn expand_deriving_coerce_pointee(
// Declare helper function that adds implementation blocks.
// FIXME(dingxiangfei2009): Investigate the set of attributes on target struct to be propagated to impls
let attrs = thin_vec![cx.attr_word(sym::automatically_derived, span),];
// # Validity assertion which will be checked later in `rustc_hir_analysis::coherence::builtins`.
{
let trait_path =
cx.path_all(span, true, path!(span, core::marker::CoercePointeeValidated), vec![]);
let trait_ref = cx.trait_ref(trait_path);
push(Annotatable::Item(
cx.item(
span,
Ident::empty(),
attrs.clone(),
ast::ItemKind::Impl(Box::new(ast::Impl {
safety: ast::Safety::Default,
polarity: ast::ImplPolarity::Positive,
defaultness: ast::Defaultness::Final,
constness: ast::Const::No,
generics: Generics {
params: generics
.params
.iter()
.map(|p| match &p.kind {
GenericParamKind::Lifetime => {
cx.lifetime_param(p.span(), p.ident, p.bounds.clone())
}
GenericParamKind::Type { default: _ } => {
cx.typaram(p.span(), p.ident, p.bounds.clone(), None)
}
GenericParamKind::Const { ty, kw_span: _, default: _ } => cx
.const_param(
p.span(),
p.ident,
p.bounds.clone(),
ty.clone(),
None,
),
})
.collect(),
where_clause: generics.where_clause.clone(),
span: generics.span,
},
of_trait: Some(trait_ref),
self_ty: self_type.clone(),
items: ThinVec::new(),
})),
),
));
}
let mut add_impl_block = |generics, trait_symbol, trait_args| {
let mut parts = path!(span, core::ops);
parts.push(Ident::new(trait_symbol, span));
@ -430,35 +466,35 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for AlwaysErrorOnGenericParam<'a, 'b>
}
#[derive(Diagnostic)]
#[diag(builtin_macros_coerce_pointee_requires_transparent)]
#[diag(builtin_macros_coerce_pointee_requires_transparent, code = E0802)]
struct RequireTransparent {
#[primary_span]
span: Span,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_coerce_pointee_requires_one_field)]
#[diag(builtin_macros_coerce_pointee_requires_one_field, code = E0802)]
struct RequireOneField {
#[primary_span]
span: Span,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_coerce_pointee_requires_one_generic)]
#[diag(builtin_macros_coerce_pointee_requires_one_generic, code = E0802)]
struct RequireOneGeneric {
#[primary_span]
span: Span,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_coerce_pointee_requires_one_pointee)]
#[diag(builtin_macros_coerce_pointee_requires_one_pointee, code = E0802)]
struct RequireOnePointee {
#[primary_span]
span: Span,
}
#[derive(Diagnostic)]
#[diag(builtin_macros_coerce_pointee_too_many_pointees)]
#[diag(builtin_macros_coerce_pointee_too_many_pointees, code = E0802)]
struct TooManyPointees {
#[primary_span]
one: Span,
@ -467,7 +503,7 @@ struct TooManyPointees {
}
#[derive(Diagnostic)]
#[diag(builtin_macros_coerce_pointee_requires_maybe_sized)]
#[diag(builtin_macros_coerce_pointee_requires_maybe_sized, code = E0802)]
struct RequiresMaybeSized {
#[primary_span]
span: Span,

View file

@ -0,0 +1,94 @@
The target of `derive(CoercePointee)` macro has inadmissible specification for
a meaningful use.
Erroneous code examples:
The target data is not a `struct`.
```compile_fail,E0802
#![feature(coerce_pointee)]
use std::marker::CoercePointee;
#[derive(CoercePointee)]
enum NotStruct<'a, T: ?Sized> {
Variant(&'a T),
}
```
The target data has a layout that is not transparent, or `repr(transparent)`
in other words.
```compile_fail,E0802
#![feature(coerce_pointee)]
use std::marker::CoercePointee;
#[derive(CoercePointee)]
struct NotTransparent<'a, #[pointee] T: ?Sized> {
ptr: &'a T,
}
```
The target data has no data field.
```compile_fail,E0802
#![feature(coerce_pointee)]
use std::marker::CoercePointee;
#[derive(CoercePointee)]
#[repr(transparent)]
struct NoField<'a, #[pointee] T: ?Sized> {}
```
The target data is not generic over any data, or has no generic type parameter.
```compile_fail,E0802
#![feature(coerce_pointee)]
use std::marker::CoercePointee;
#[derive(CoercePointee)]
#[repr(transparent)]
struct NoGeneric<'a>(&'a u8);
```
The target data has multiple generic type parameters, but none is designated as
a pointee for coercion.
```compile_fail,E0802
#![feature(coerce_pointee)]
use std::marker::CoercePointee;
#[derive(CoercePointee)]
#[repr(transparent)]
struct AmbiguousPointee<'a, T1: ?Sized, T2: ?Sized> {
a: (&'a T1, &'a T2),
}
```
The target data has multiple generic type parameters that are designated as
pointees for coercion.
```compile_fail,E0802
#![feature(coerce_pointee)]
use std::marker::CoercePointee;
#[derive(CoercePointee)]
#[repr(transparent)]
struct TooManyPointees<
'a,
#[pointee] A: ?Sized,
#[pointee] B: ?Sized>
((&'a A, &'a B));
```
The type parameter that is designated as a pointee is not marked `?Sized`.
```compile_fail,E0802
#![feature(coerce_pointee)]
use std::marker::CoercePointee;
#[derive(CoercePointee)]
#[repr(transparent)]
struct NoMaybeSized<'a, #[pointee] T> {
ptr: &'a T,
}
```
In summary, the `CoercePointee` macro demands the type to be a `struct` that is
generic over at least one type or over more types, one of which is marked with
`#[pointee]`, and has at least one data field and adopts a `repr(transparent)`
layout.
The only generic type or the type marked with `#[pointee]` has to be also
marked as `?Sized`.

View file

@ -545,6 +545,7 @@ E0798: 0798,
E0799: 0799,
E0800: 0800,
E0801: 0801,
E0802: 0802,
);
)
}

View file

@ -1,7 +1,8 @@
use rustc_ast::ptr::P;
use rustc_ast::util::literal;
use rustc_ast::{
self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, UnOp, attr, token,
self as ast, AnonConst, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, UnOp,
attr, token,
};
use rustc_span::source_map::Spanned;
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
@ -138,6 +139,42 @@ impl<'a> ExtCtxt<'a> {
}
}
pub fn lifetime_param(
&self,
span: Span,
ident: Ident,
bounds: ast::GenericBounds,
) -> ast::GenericParam {
ast::GenericParam {
id: ast::DUMMY_NODE_ID,
ident: ident.with_span_pos(span),
attrs: AttrVec::new(),
bounds,
is_placeholder: false,
kind: ast::GenericParamKind::Lifetime,
colon_span: None,
}
}
pub fn const_param(
&self,
span: Span,
ident: Ident,
bounds: ast::GenericBounds,
ty: P<ast::Ty>,
default: Option<AnonConst>,
) -> ast::GenericParam {
ast::GenericParam {
id: ast::DUMMY_NODE_ID,
ident: ident.with_span_pos(span),
attrs: AttrVec::new(),
bounds,
is_placeholder: false,
kind: ast::GenericParamKind::Const { ty, kw_span: DUMMY_SP, default },
colon_span: None,
}
}
pub fn trait_ref(&self, path: ast::Path) -> ast::TraitRef {
ast::TraitRef { path, ref_id: ast::DUMMY_NODE_ID }
}

View file

@ -370,6 +370,8 @@ language_item_table! {
PointerLike, sym::pointer_like, pointer_like, Target::Trait, GenericRequirement::Exact(0);
CoercePointeeValidated, sym::coerce_pointee_validated, coerce_pointee_validated_trait, Target::Trait, GenericRequirement::Exact(0);
ConstParamTy, sym::const_param_ty, const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0);
UnsizedConstParamTy, sym::unsized_const_param_ty, unsized_const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0);
@ -429,9 +431,13 @@ language_item_table! {
ContractCheckRequires, sym::contract_check_requires, contract_check_requires_fn, Target::Fn, GenericRequirement::None;
}
/// The requirement imposed on the generics of a lang item
pub enum GenericRequirement {
/// No restriction on the generics
None,
/// A minimum number of generics that is demanded on a lang item
Minimum(usize),
/// The number of generics must match precisely as stipulated
Exact(usize),
}

View file

@ -85,6 +85,16 @@ hir_analysis_cmse_output_stack_spill =
.note1 = functions with the `"{$abi_name}"` ABI must pass their result via the available return registers
.note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
hir_analysis_coerce_pointee_no_field = `CoercePointee` can only be derived on `struct`s with at least one field
hir_analysis_coerce_pointee_no_user_validity_assertion = asserting applicability of `derive(CoercePointee)` on a target data is forbidden
hir_analysis_coerce_pointee_not_concrete_ty = `derive(CoercePointee)` is only applicable to `struct`
hir_analysis_coerce_pointee_not_struct = `derive(CoercePointee)` is only applicable to `struct`, instead of `{$kind}`
hir_analysis_coerce_pointee_not_transparent = `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout
hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures
hir_analysis_coerce_unsized_multi = implementing the trait `CoerceUnsized` requires multiple coercions

View file

@ -48,6 +48,10 @@ pub(super) fn check_trait<'tcx>(
checker
.check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn)?;
checker.check(lang_items.pointer_like(), visit_implementation_of_pointer_like)?;
checker.check(
lang_items.coerce_pointee_validated_trait(),
visit_implementation_of_coerce_pointee_validity,
)?;
Ok(())
}
@ -783,3 +787,32 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
.with_note(why_disqualified)
.emit())
}
fn visit_implementation_of_coerce_pointee_validity(
checker: &Checker<'_>,
) -> Result<(), ErrorGuaranteed> {
let tcx = checker.tcx;
let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty();
let span = tcx.def_span(checker.impl_def_id);
if !tcx.is_builtin_derived(checker.impl_def_id.into()) {
return Err(tcx.dcx().emit_err(errors::CoercePointeeNoUserValidityAssertion { span }));
}
let ty::Adt(def, _args) = self_ty.kind() else {
return Err(tcx.dcx().emit_err(errors::CoercePointeeNotConcreteType { span }));
};
let did = def.did();
// Now get a more precise span of the `struct`.
let span = tcx.def_span(did);
if !def.is_struct() {
return Err(tcx
.dcx()
.emit_err(errors::CoercePointeeNotStruct { span, kind: def.descr().into() }));
}
if !def.repr().transparent() {
return Err(tcx.dcx().emit_err(errors::CoercePointeeNotTransparent { span }));
}
if def.all_fields().next().is_none() {
return Err(tcx.dcx().emit_err(errors::CoercePointeeNoField { span }));
}
Ok(())
}

View file

@ -1180,6 +1180,42 @@ pub(crate) struct DispatchFromDynRepr {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_pointee_not_struct, code = E0802)]
pub(crate) struct CoercePointeeNotStruct {
#[primary_span]
pub span: Span,
pub kind: String,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_pointee_not_concrete_ty, code = E0802)]
pub(crate) struct CoercePointeeNotConcreteType {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_pointee_no_user_validity_assertion, code = E0802)]
pub(crate) struct CoercePointeeNoUserValidityAssertion {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_pointee_not_transparent, code = E0802)]
pub(crate) struct CoercePointeeNotTransparent {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_pointee_no_field, code = E0802)]
pub(crate) struct CoercePointeeNoField {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)]
#[help]

View file

@ -193,6 +193,7 @@ symbols! {
Cleanup,
Clone,
CoercePointee,
CoercePointeeValidated,
CoerceUnsized,
Command,
ConstParamTy,
@ -619,6 +620,7 @@ symbols! {
cmp_partialord_lt,
cmpxchg16b_target_feature,
cmse_nonsecure_entry,
coerce_pointee_validated,
coerce_unsized,
cold,
cold_path,

View file

@ -1284,8 +1284,22 @@ pub trait FnPtr: Copy + Clone {
/// }
/// ```
#[rustc_builtin_macro(CoercePointee, attributes(pointee))]
#[allow_internal_unstable(dispatch_from_dyn, coerce_unsized, unsize)]
#[allow_internal_unstable(dispatch_from_dyn, coerce_unsized, unsize, coerce_pointee_validated)]
#[unstable(feature = "derive_coerce_pointee", issue = "123430")]
pub macro CoercePointee($item:item) {
/* compiler built-in */
}
/// A trait that is implemented for ADTs with `derive(CoercePointee)` so that
/// the compiler can enforce the derive impls are valid post-expansion, since
/// the derive has stricter requirements than if the impls were written by hand.
///
/// This trait is not intended to be implemented by users or used other than
/// validation, so it should never be stabilized.
#[cfg(not(bootstrap))]
#[lang = "coerce_pointee_validated"]
#[unstable(feature = "coerce_pointee_validated", issue = "none")]
#[doc(hidden)]
pub trait CoercePointeeValidated {
/* compiler built-in */
}

View file

@ -0,0 +1,31 @@
#![feature(let_chains)]
extern crate proc_macro;
use proc_macro::{Delimiter, TokenStream, TokenTree};
#[proc_macro_attribute]
pub fn norepr(_: TokenStream, input: TokenStream) -> TokenStream {
let mut tokens = vec![];
let mut tts = input.into_iter().fuse().peekable();
loop {
let Some(token) = tts.next() else { break };
if let TokenTree::Punct(punct) = &token
&& punct.as_char() == '#'
{
if let Some(TokenTree::Group(group)) = tts.peek()
&& let Delimiter::Bracket = group.delimiter()
&& let Some(TokenTree::Ident(ident)) = group.stream().into_iter().next()
&& ident.to_string() == "repr"
{
let _ = tts.next();
// skip '#' and '[repr(..)]
} else {
tokens.push(token);
}
} else {
tokens.push(token);
}
}
tokens.into_iter().collect()
}

View file

@ -20,6 +20,8 @@ pub struct Ptr<'a, #[pointee] T: ?Sized> {
data: &'a mut T,
}
#[automatically_derived]
impl<'a, T: ?Sized> ::core::marker::CoercePointeeValidated for Ptr<'a, T> { }
#[automatically_derived]
impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized>
::core::ops::DispatchFromDyn<Ptr<'a, __S>> for Ptr<'a, T> {
}

View file

@ -16,6 +16,10 @@ struct MyPointer<'a, #[pointee] T: ?Sized> {
ptr: &'a T,
}
#[automatically_derived]
impl<'a, T: ?Sized> ::core::marker::CoercePointeeValidated for
MyPointer<'a, T> {
}
#[automatically_derived]
impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized>
::core::ops::DispatchFromDyn<MyPointer<'a, __S>> for MyPointer<'a, T> {
}
@ -31,6 +35,11 @@ pub struct MyPointer2<'a, Y, Z: MyTrait<T>, #[pointee] T: ?Sized + MyTrait<T>,
x: core::marker::PhantomData<X>,
}
#[automatically_derived]
impl<'a, Y, Z: MyTrait<T>, T: ?Sized + MyTrait<T>, X: MyTrait<T>>
::core::marker::CoercePointeeValidated for MyPointer2<'a, Y, Z, T, X>
where Y: MyTrait<T> {
}
#[automatically_derived]
impl<'a, Y, Z: MyTrait<T> + MyTrait<__S>, T: ?Sized + MyTrait<T> +
::core::marker::Unsize<__S>, __S: ?Sized + MyTrait<__S>, X: MyTrait<T> +
MyTrait<__S>> ::core::ops::DispatchFromDyn<MyPointer2<'a, Y, Z, __S, X>>
@ -48,6 +57,10 @@ struct MyPointerWithoutPointee<'a, T: ?Sized> {
ptr: &'a T,
}
#[automatically_derived]
impl<'a, T: ?Sized> ::core::marker::CoercePointeeValidated for
MyPointerWithoutPointee<'a, T> {
}
#[automatically_derived]
impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized>
::core::ops::DispatchFromDyn<MyPointerWithoutPointee<'a, __S>> for
MyPointerWithoutPointee<'a, T> {

View file

@ -1,6 +1,9 @@
//@ proc-macro: malicious-macro.rs
#![feature(derive_coerce_pointee, arbitrary_self_types)]
extern crate core;
extern crate malicious_macro;
use std::marker::CoercePointee;
#[derive(CoercePointee)]
@ -41,8 +44,8 @@ struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &
//~^ ERROR: only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits
#[derive(CoercePointee)]
//~^ ERROR: `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
struct NotTransparent<'a, #[pointee] T: ?Sized> {
//~^ ERROR: `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout
ptr: &'a T,
}
@ -131,4 +134,12 @@ struct GlobalCoreSized<'a, #[pointee] T: ?::core::marker::Sized> {
ptr: &'a T,
}
#[derive(CoercePointee)]
#[malicious_macro::norepr]
#[repr(transparent)]
struct TryToWipeRepr<'a, #[pointee] T: ?Sized> {
//~^ ERROR: `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout [E0802]
ptr: &'a T,
}
fn main() {}

View file

@ -1,89 +1,81 @@
error: `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
--> $DIR/deriving-coerce-pointee-neg.rs:6:10
error[E0802]: `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
--> $DIR/deriving-coerce-pointee-neg.rs:9:10
|
LL | #[derive(CoercePointee)]
| ^^^^^^^^^^^^^
|
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `CoercePointee` can only be derived on `struct`s with at least one field
--> $DIR/deriving-coerce-pointee-neg.rs:12:10
error[E0802]: `CoercePointee` can only be derived on `struct`s with at least one field
--> $DIR/deriving-coerce-pointee-neg.rs:15:10
|
LL | #[derive(CoercePointee)]
| ^^^^^^^^^^^^^
|
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `CoercePointee` can only be derived on `struct`s with at least one field
--> $DIR/deriving-coerce-pointee-neg.rs:19:10
error[E0802]: `CoercePointee` can only be derived on `struct`s with at least one field
--> $DIR/deriving-coerce-pointee-neg.rs:22:10
|
LL | #[derive(CoercePointee)]
| ^^^^^^^^^^^^^
|
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `CoercePointee` can only be derived on `struct`s that are generic over at least one type
--> $DIR/deriving-coerce-pointee-neg.rs:26:10
error[E0802]: `CoercePointee` can only be derived on `struct`s that are generic over at least one type
--> $DIR/deriving-coerce-pointee-neg.rs:29:10
|
LL | #[derive(CoercePointee)]
| ^^^^^^^^^^^^^
|
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
error: exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits
--> $DIR/deriving-coerce-pointee-neg.rs:31:10
error[E0802]: exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits
--> $DIR/deriving-coerce-pointee-neg.rs:34:10
|
LL | #[derive(CoercePointee)]
| ^^^^^^^^^^^^^
|
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
error: only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits
--> $DIR/deriving-coerce-pointee-neg.rs:40:39
error[E0802]: only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits
--> $DIR/deriving-coerce-pointee-neg.rs:43:39
|
LL | struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &'a B));
| ^ - here another type parameter is marked as `#[pointee]`
error: `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
--> $DIR/deriving-coerce-pointee-neg.rs:43:10
|
LL | #[derive(CoercePointee)]
| ^^^^^^^^^^^^^
|
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `derive(CoercePointee)` requires `T` to be marked `?Sized`
--> $DIR/deriving-coerce-pointee-neg.rs:51:36
error[E0802]: `derive(CoercePointee)` requires `T` to be marked `?Sized`
--> $DIR/deriving-coerce-pointee-neg.rs:54:36
|
LL | struct NoMaybeSized<'a, #[pointee] T> {
| ^
error: the `#[pointee]` attribute may only be used on generic parameters
--> $DIR/deriving-coerce-pointee-neg.rs:59:5
--> $DIR/deriving-coerce-pointee-neg.rs:62:5
|
LL | #[pointee]
| ^^^^^^^^^^
error: the `#[pointee]` attribute may only be used on generic parameters
--> $DIR/deriving-coerce-pointee-neg.rs:69:33
--> $DIR/deriving-coerce-pointee-neg.rs:72:33
|
LL | struct UhOh<#[pointee] T>(T);
| ^^^^^^^^^^
error: the `#[pointee]` attribute may only be used on generic parameters
--> $DIR/deriving-coerce-pointee-neg.rs:83:21
--> $DIR/deriving-coerce-pointee-neg.rs:86:21
|
LL | struct UhOh<#[pointee] T>(T);
| ^^^^^^^^^^
error: the `#[pointee]` attribute may only be used on generic parameters
--> $DIR/deriving-coerce-pointee-neg.rs:98:25
--> $DIR/deriving-coerce-pointee-neg.rs:101:25
|
LL | struct UhOh<#[pointee] T>(T);
| ^^^^^^^^^^
error[E0392]: lifetime parameter `'a` is never used
--> $DIR/deriving-coerce-pointee-neg.rs:15:16
--> $DIR/deriving-coerce-pointee-neg.rs:18:16
|
LL | struct NoField<'a, #[pointee] T: ?Sized> {}
| ^^ unused lifetime parameter
@ -91,7 +83,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-coerce-pointee-neg.rs:15:31
--> $DIR/deriving-coerce-pointee-neg.rs:18:31
|
LL | struct NoField<'a, #[pointee] T: ?Sized> {}
| ^ unused type parameter
@ -99,7 +91,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-coerce-pointee-neg.rs:22:20
--> $DIR/deriving-coerce-pointee-neg.rs:25:20
|
LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
| ^^ unused lifetime parameter
@ -107,13 +99,26 @@ 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-coerce-pointee-neg.rs:22:35
--> $DIR/deriving-coerce-pointee-neg.rs:25: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 16 previous errors
error[E0802]: `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout
--> $DIR/deriving-coerce-pointee-neg.rs:47:1
|
LL | struct NotTransparent<'a, #[pointee] T: ?Sized> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0392`.
error[E0802]: `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout
--> $DIR/deriving-coerce-pointee-neg.rs:140:1
|
LL | struct TryToWipeRepr<'a, #[pointee] T: ?Sized> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 17 previous errors
Some errors have detailed explanations: E0392, E0802.
For more information about an error, try `rustc --explain E0392`.