1
Fork 0

introduce CoercePointeeWellformed for coherence checks at typeck stage

This commit is contained in:
Ding Xiang Fei 2025-01-27 06:06:06 +08:00
parent 43ca9d18e3
commit de405dcb8f
No known key found for this signature in database
GPG key ID: 3CD748647EEF6359
15 changed files with 337 additions and 36 deletions

View file

@ -3,11 +3,12 @@ use ast::ptr::P;
use rustc_ast::mut_visit::MutVisitor; use rustc_ast::mut_visit::MutVisitor;
use rustc_ast::visit::BoundKind; use rustc_ast::visit::BoundKind;
use rustc_ast::{ use rustc_ast::{
self as ast, GenericArg, GenericBound, GenericParamKind, ItemKind, MetaItem, self as ast, GenericArg, GenericBound, GenericParamKind, Generics, ItemKind, MetaItem,
TraitBoundModifiers, VariantData, WherePredicate, TraitBoundModifiers, VariantData, WherePredicate,
}; };
use rustc_attr_parsing as attr; use rustc_attr_parsing as attr;
use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_errors::E0802;
use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_macros::Diagnostic; use rustc_macros::Diagnostic;
use rustc_span::{Ident, Span, Symbol, sym}; use rustc_span::{Ident, Span, Symbol, sym};
@ -88,8 +89,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
} else { } else {
let mut pointees = type_params let mut pointees = type_params
.iter() .iter()
.filter_map(|&(idx, span, is_pointee)| is_pointee.then_some((idx, span))) .filter_map(|&(idx, span, is_pointee)| is_pointee.then_some((idx, span)));
.fuse();
match (pointees.next(), pointees.next()) { match (pointees.next(), pointees.next()) {
(Some((idx, _span)), None) => idx, (Some((idx, _span)), None) => idx,
(None, _) => { (None, _) => {
@ -110,6 +110,52 @@ pub(crate) fn expand_deriving_coerce_pointee(
// Declare helper function that adds implementation blocks. // Declare helper function that adds implementation blocks.
// FIXME(dingxiangfei2009): Investigate the set of attributes on target struct to be propagated to impls // 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),]; let attrs = thin_vec![cx.attr_word(sym::automatically_derived, span),];
// # Wellformed-ness assertion
{
let trait_path =
cx.path_all(span, true, path!(span, core::marker::CoercePointeeWellformed), 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 add_impl_block = |generics, trait_symbol, trait_args| {
let mut parts = path!(span, core::ops); let mut parts = path!(span, core::ops);
parts.push(Ident::new(trait_symbol, span)); parts.push(Ident::new(trait_symbol, span));
@ -430,35 +476,35 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for AlwaysErrorOnGenericParam<'a, 'b>
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(builtin_macros_coerce_pointee_requires_transparent)] #[diag(builtin_macros_coerce_pointee_requires_transparent, code = E0802)]
struct RequireTransparent { struct RequireTransparent {
#[primary_span] #[primary_span]
span: Span, span: Span,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(builtin_macros_coerce_pointee_requires_one_field)] #[diag(builtin_macros_coerce_pointee_requires_one_field, code = E0802)]
struct RequireOneField { struct RequireOneField {
#[primary_span] #[primary_span]
span: Span, span: Span,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(builtin_macros_coerce_pointee_requires_one_generic)] #[diag(builtin_macros_coerce_pointee_requires_one_generic, code = E0802)]
struct RequireOneGeneric { struct RequireOneGeneric {
#[primary_span] #[primary_span]
span: Span, span: Span,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(builtin_macros_coerce_pointee_requires_one_pointee)] #[diag(builtin_macros_coerce_pointee_requires_one_pointee, code = E0802)]
struct RequireOnePointee { struct RequireOnePointee {
#[primary_span] #[primary_span]
span: Span, span: Span,
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(builtin_macros_coerce_pointee_too_many_pointees)] #[diag(builtin_macros_coerce_pointee_too_many_pointees, code = E0802)]
struct TooManyPointees { struct TooManyPointees {
#[primary_span] #[primary_span]
one: Span, one: Span,
@ -467,7 +513,7 @@ struct TooManyPointees {
} }
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(builtin_macros_coerce_pointee_requires_maybe_sized)] #[diag(builtin_macros_coerce_pointee_requires_maybe_sized, code = E0802)]
struct RequiresMaybeSized { struct RequiresMaybeSized {
#[primary_span] #[primary_span]
span: Span, span: Span,

View file

@ -0,0 +1,80 @@
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
#[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
#[derive(CoercePointee)]
struct NotTransparent<'a, #[pointee] T: ?Sized> {
ptr: &'a T,
}
```
The target data has no data field.
```compile_fail,E0802
#[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
#[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
#[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
#[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
#[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, E0799: 0799,
E0800: 0800, E0800: 0800,
E0801: 0801, E0801: 0801,
E0802: 0802,
); );
) )
} }

View file

@ -1,7 +1,8 @@
use rustc_ast::ptr::P; use rustc_ast::ptr::P;
use rustc_ast::util::literal; use rustc_ast::util::literal;
use rustc_ast::{ 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::source_map::Spanned;
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; 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 { pub fn trait_ref(&self, path: ast::Path) -> ast::TraitRef {
ast::TraitRef { path, ref_id: ast::DUMMY_NODE_ID } 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); PointerLike, sym::pointer_like, pointer_like, Target::Trait, GenericRequirement::Exact(0);
CoercePointeeWellformed, sym::coerce_pointee_wellformed, coerce_pointee_wellformed_trait, Target::Trait, GenericRequirement::Exact(0);
ConstParamTy, sym::const_param_ty, const_param_ty_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); 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; 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 { pub enum GenericRequirement {
/// No restriction on the generics
None, None,
/// A minimum number of generics that is demanded on a lang item
Minimum(usize), Minimum(usize),
/// The number of generics must match precisely as stipulated
Exact(usize), Exact(usize),
} }

View file

@ -85,6 +85,12 @@ hir_analysis_cmse_output_stack_spill =
.note1 = functions with the `"{$abi_name}"` ABI must pass their result via the available return registers .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 .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_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_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 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 checker
.check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn)?; .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.pointer_like(), visit_implementation_of_pointer_like)?;
checker.check(
lang_items.coerce_pointee_wellformed_trait(),
visit_implementation_of_coerce_pointee_wellformed,
)?;
Ok(()) Ok(())
} }
@ -782,3 +786,27 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
.with_note(why_disqualified) .with_note(why_disqualified)
.emit()) .emit())
} }
fn visit_implementation_of_coerce_pointee_wellformed(
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 ty::Adt(def, _args) = self_ty.kind() else {
return Err(tcx.dcx().emit_err(errors::CoercePointeeNotConcreteType {
span: tcx.def_span(checker.impl_def_id),
}));
};
let did = def.did();
let span =
if let Some(local) = did.as_local() { tcx.source_span(local) } else { 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 }));
}
Ok(())
}

View file

@ -1180,6 +1180,28 @@ pub(crate) struct DispatchFromDynRepr {
pub span: Span, 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_not_transparent, code = E0802)]
pub(crate) struct CoercePointeeNotTransparent {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)] #[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)]
#[help] #[help]

View file

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

View file

@ -1289,3 +1289,9 @@ pub trait FnPtr: Copy + Clone {
pub macro CoercePointee($item:item) { pub macro CoercePointee($item:item) {
/* compiler built-in */ /* compiler built-in */
} }
#[cfg(not(bootstrap))]
#[lang = "coerce_pointee_wellformed"]
#[unstable(feature = "derive_coerce_pointee", issue = "123430")]
#[doc(hidden)]
pub trait CoercePointeeWellformed {}

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, data: &'a mut T,
} }
#[automatically_derived] #[automatically_derived]
impl<'a, T: ?Sized> ::core::marker::CoercePointeeWellformed for Ptr<'a, T> { }
#[automatically_derived]
impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized>
::core::ops::DispatchFromDyn<Ptr<'a, __S>> for Ptr<'a, T> { ::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, ptr: &'a T,
} }
#[automatically_derived] #[automatically_derived]
impl<'a, T: ?Sized> ::core::marker::CoercePointeeWellformed for
MyPointer<'a, T> {
}
#[automatically_derived]
impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized>
::core::ops::DispatchFromDyn<MyPointer<'a, __S>> for MyPointer<'a, T> { ::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>, x: core::marker::PhantomData<X>,
} }
#[automatically_derived] #[automatically_derived]
impl<'a, Y, Z: MyTrait<T>, T: ?Sized + MyTrait<T>, X: MyTrait<T>>
::core::marker::CoercePointeeWellformed 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> + impl<'a, Y, Z: MyTrait<T> + MyTrait<__S>, T: ?Sized + MyTrait<T> +
::core::marker::Unsize<__S>, __S: ?Sized + MyTrait<__S>, X: MyTrait<T> + ::core::marker::Unsize<__S>, __S: ?Sized + MyTrait<__S>, X: MyTrait<T> +
MyTrait<__S>> ::core::ops::DispatchFromDyn<MyPointer2<'a, Y, Z, __S, X>> MyTrait<__S>> ::core::ops::DispatchFromDyn<MyPointer2<'a, Y, Z, __S, X>>
@ -48,6 +57,10 @@ struct MyPointerWithoutPointee<'a, T: ?Sized> {
ptr: &'a T, ptr: &'a T,
} }
#[automatically_derived] #[automatically_derived]
impl<'a, T: ?Sized> ::core::marker::CoercePointeeWellformed for
MyPointerWithoutPointee<'a, T> {
}
#[automatically_derived]
impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized> impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized>
::core::ops::DispatchFromDyn<MyPointerWithoutPointee<'a, __S>> for ::core::ops::DispatchFromDyn<MyPointerWithoutPointee<'a, __S>> for
MyPointerWithoutPointee<'a, T> { MyPointerWithoutPointee<'a, T> {

View file

@ -1,6 +1,9 @@
//@ proc-macro: malicious-macro.rs
#![feature(derive_coerce_pointee, arbitrary_self_types)] #![feature(derive_coerce_pointee, arbitrary_self_types)]
extern crate core; extern crate core;
extern crate malicious_macro;
use std::marker::CoercePointee; use std::marker::CoercePointee;
#[derive(CoercePointee)] #[derive(CoercePointee)]
@ -131,4 +134,12 @@ struct GlobalCoreSized<'a, #[pointee] T: ?::core::marker::Sized> {
ptr: &'a T, 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() {} fn main() {}

View file

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