Skip to content

Redact CoercePointee target type #136796

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
@@ -85,6 +85,23 @@ hir_analysis_cmse_output_stack_spill =
.note1 = functions with the `{$abi}` 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_cannot_coerce_unsized = `{$ty}` cannot be coerced to an unsized type
.note = `derive(CoercePointee)` demands that `{$ty}` can be coerced to an unsized type
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This note is not exercised by any test, I think?

Copy link
Contributor Author

@dingxiangfei2009 dingxiangfei2009 Feb 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realised that the note cannot be exercised because the span falls within the macro expansion.

Instead it is overwritten by this message.

note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)

This happens still after adding the missing #[note] and #[help] attributes to the diagnostics.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I need to switch to the span of the ADT definition.

.help = the standard pointers such as `Arc`, `Rc`, `Box`, and other types with `derive(CoercePointee)` can be coerced to their corresponding unsized types
hir_analysis_coerce_pointee_cannot_dispatch_from_dyn = `{$ty}` cannot be coerced to an unsized type, to which `dyn` methods can be dispatched
.note = `derive(CoercePointee)` demands that `dyn` methods can be dispatched when `{$ty}` can be coerced to an unsized type
.help = `dyn` methods can be dispatched to the standard pointers such as `Arc`, `Rc`, `Box`, and other types with `derive(CoercePointee)`
hir_analysis_coerce_pointee_cannot_unsize = `{$ty}` cannot be coerced to an unsized value
.note = `derive(CoercePointee)` demands that `{$ty}` can be coerced to an unsized type
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar, this note is not exercised by any test?

.help = `derive(CoercePointee)` requires exactly one copy of `#[pointee]` type at the end of the `struct` definition, without any further pointer or reference indirection
hir_analysis_coerce_pointee_multiple_targets = `derive(CoercePointee)` only admits exactly one data field, {$diag_trait ->
[DispatchFromDyn] to which `dyn` methods shall be dispatched
*[CoerceUnsized] on which unsize coercion shall be performed
}
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
446 changes: 270 additions & 176 deletions compiler/rustc_hir_analysis/src/coherence/builtin.rs

Large diffs are not rendered by default.

108 changes: 108 additions & 0 deletions compiler/rustc_hir_analysis/src/coherence/builtin/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use rustc_hir::LangItem;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::{
self, GenericParamDefKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
use rustc_span::{Span, sym};
use rustc_trait_selection::traits::FulfillmentError;
use tracing::instrument;

use crate::errors;

#[instrument(level = "debug", skip(tcx), ret)]
pub(super) fn extract_coerce_pointee_data<'tcx>(
tcx: TyCtxt<'tcx>,
adt_did: DefId,
) -> Option<usize> {
// It is decided that a query to cache these results is not necessary
// for error reporting.
// We can afford to recompute it on-demand.
if tcx.lang_items().get(LangItem::CoercePointeeValidated).map_or(false, |did| {
tcx.trait_impls_of(did).non_blanket_impls().contains_key(&SimplifiedType::Adt(adt_did))
}) {
// Search for the `#[pointee]`
enum Pointee {
None,
First(usize),
Ambiguous,
}
let mut first_type = Pointee::None;
for (idx, param) in tcx.generics_of(adt_did).own_params.iter().enumerate() {
if let GenericParamDefKind::Type { .. } = param.kind {
match first_type {
Pointee::None => {
first_type = Pointee::First(idx);
}
Pointee::First(_) => first_type = Pointee::Ambiguous,
Pointee::Ambiguous => {}
}
}
if tcx.has_attr(param.def_id, sym::pointee) {
return Some(idx);
}
}
if let Pointee::First(idx) = first_type {
return Some(idx);
}
}
None
}

fn contains_coerce_pointee_target_pointee<'tcx>(ty: Ty<'tcx>, target_pointee_ty: Ty<'tcx>) -> bool {
struct Search<'tcx> {
pointee: Ty<'tcx>,
found: bool,
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for Search<'tcx> {
fn visit_ty(&mut self, t: Ty<'tcx>) {
if t == self.pointee {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this implementation "micro-optimized"? It shouldn't matter to override all these functions, and it makes the visitor much larger than it needs to be.

self.found = true;
} else {
t.super_visit_with(self)
}
}
}
let mut search = Search { pointee: target_pointee_ty, found: false };
ty.visit_with(&mut search);
search.found
}

#[instrument(level = "debug", skip(tcx))]
pub(super) fn redact_fulfillment_err_for_coerce_pointee<'tcx>(
tcx: TyCtxt<'tcx>,
err: FulfillmentError<'tcx>,
target_pointee_ty: Ty<'tcx>,
span: Span,
) -> Option<FulfillmentError<'tcx>> {
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
err.obligation.predicate.kind().skip_binder()
{
let mentions_pointee = || {
contains_coerce_pointee_target_pointee(
pred.trait_ref.args.type_at(1),
target_pointee_ty,
)
};
let source = pred.trait_ref.self_ty();
if tcx.is_lang_item(pred.def_id(), LangItem::DispatchFromDyn) && mentions_pointee() {
tcx.dcx().emit_err(errors::CoercePointeeCannotDispatchFromDyn {
ty: source.to_string(),
span,
});
return None;
}
if tcx.is_lang_item(pred.def_id(), LangItem::Unsize) && mentions_pointee() {
// We should redact it
tcx.dcx().emit_err(errors::CoercePointeeCannotUnsize { ty: source.to_string(), span });
return None;
}
if tcx.is_lang_item(pred.def_id(), LangItem::CoerceUnsized) && mentions_pointee() {
// We should redact it
tcx.dcx()
.emit_err(errors::CoercePointeeCannotCoerceUnsize { ty: source.to_string(), span });
return None;
}
}
Some(err)
}
38 changes: 38 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1219,6 +1219,44 @@ pub(crate) struct CoercePointeeNoField {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_pointee_multiple_targets, code = E0802)]
pub(crate) struct CoercePointeeMultipleTargets {
#[primary_span]
pub spans: Vec<Span>,
pub diag_trait: &'static str,
}

#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_pointee_cannot_unsize, code = E0802)]
#[note]
#[help]
pub(crate) struct CoercePointeeCannotUnsize {
#[primary_span]
pub span: Span,
pub ty: String,
}

#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_pointee_cannot_coerce_unsized, code = E0802)]
#[note]
#[help]
pub(crate) struct CoercePointeeCannotCoerceUnsize {
#[primary_span]
pub span: Span,
pub ty: String,
}

#[derive(Diagnostic)]
#[diag(hir_analysis_coerce_pointee_cannot_dispatch_from_dyn, code = E0802)]
#[note]
#[help]
pub(crate) struct CoercePointeeCannotDispatchFromDyn {
#[primary_span]
pub span: Span,
pub ty: String,
}

#[derive(Diagnostic)]
#[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)]
#[help]
59 changes: 53 additions & 6 deletions tests/ui/deriving/deriving-coerce-pointee-neg.rs
Original file line number Diff line number Diff line change
@@ -8,31 +8,38 @@ use std::marker::CoercePointee;

#[derive(CoercePointee)]
//~^ ERROR: `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
//~| NOTE: in this expansion of #[derive(CoercePointee)]
enum NotStruct<'a, T: ?Sized> {
Variant(&'a T),
}

#[derive(CoercePointee)]
//~^ ERROR: `CoercePointee` can only be derived on `struct`s with at least one field
//~| NOTE: in this expansion of #[derive(CoercePointee)]
#[repr(transparent)]
struct NoField<'a, #[pointee] T: ?Sized> {}
//~^ ERROR: lifetime parameter `'a` is never used
//~| ERROR: type parameter `T` is never used
struct NoField<#[pointee] T: ?Sized> {}
//~^ ERROR: type parameter `T` is never used
//~| NOTE: unused type parameter
//~| HELP: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`

#[derive(CoercePointee)]
//~^ ERROR: `CoercePointee` can only be derived on `struct`s with at least one field
//~| NOTE: in this expansion of #[derive(CoercePointee)]
#[repr(transparent)]
struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
//~^ ERROR: lifetime parameter `'a` is never used
//~| ERROR: type parameter `T` is never used
struct NoFieldUnit<#[pointee] T: ?Sized>();
//~^ ERROR: type parameter `T` is never used
//~| NOTE: unused type parameter
//~| HELP: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`

#[derive(CoercePointee)]
//~^ ERROR: `CoercePointee` can only be derived on `struct`s that are generic over at least one type
//~| NOTE: in this expansion of #[derive(CoercePointee)]
#[repr(transparent)]
struct NoGeneric<'a>(&'a u8);

#[derive(CoercePointee)]
//~^ ERROR: exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits
//~| NOTE: in this expansion of #[derive(CoercePointee)]
#[repr(transparent)]
struct AmbiguousPointee<'a, T1: ?Sized, T2: ?Sized> {
a: (&'a T1, &'a T2),
@@ -42,6 +49,7 @@ struct AmbiguousPointee<'a, T1: ?Sized, T2: ?Sized> {
#[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 `CoercePointee` traits
//~| NOTE: here another type parameter is marked as `#[pointee]`

#[derive(CoercePointee)]
struct NotTransparent<'a, #[pointee] T: ?Sized> {
@@ -142,4 +150,43 @@ struct TryToWipeRepr<'a, #[pointee] T: ?Sized> {
ptr: &'a T,
}

#[repr(transparent)]
#[derive(CoercePointee)]
struct RcWithId<T: ?Sized> {
inner: std::rc::Rc<(i32, Box<T>)>,
//~^ ERROR: `Box<T>` cannot be coerced to an unsized value [E0802]
//~| NOTE: `derive(CoercePointee)` demands that `Box<T>` can be coerced to an unsized type
//~| HELP: `derive(CoercePointee)` requires exactly one copy of `#[pointee]` type at the end of the `struct` definition, without any further pointer or reference indirection
//~| ERROR: `Box<T>` cannot be coerced to an unsized value [E0802]
//~| NOTE: `derive(CoercePointee)` demands that `Box<T>` can be coerced to an unsized type
//~| HELP: `derive(CoercePointee)` requires exactly one copy of `#[pointee]` type at the end of the `struct` definition, without any further pointer or reference indirection
//~| NOTE: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
}

#[repr(transparent)]
#[derive(CoercePointee)]
struct MoreThanOneField<T: ?Sized> {
//~^ ERROR: transparent struct needs at most one field with non-trivial size or alignment, but has 2 [E0690]
//~| NOTE: needs at most one field with non-trivial size or alignment, but has 2
inner1: Box<T>,
//~^ ERROR: `derive(CoercePointee)` only admits exactly one data field, to which `dyn` methods shall be dispatched [E0802]
//~| ERROR: `derive(CoercePointee)` only admits exactly one data field, on which unsize coercion shall be performed [E0802]
//~| NOTE: this field has non-zero size or requires alignment
inner2: Box<T>,
//~^ NOTE: this field has non-zero size or requires alignment
}

struct NotCoercePointeeData<T: ?Sized>(T);

#[repr(transparent)]
#[derive(CoercePointee)]
struct UsingNonCoercePointeeData<T: ?Sized>(NotCoercePointeeData<T>);
//~^ ERROR: `NotCoercePointeeData<T>` cannot be coerced to an unsized type [E0802]
//~| NOTE: `derive(CoercePointee)` demands that `NotCoercePointeeData<T>` can be coerced to an unsized type
//~| HELP: the standard pointers such as `Arc`, `Rc`, `Box`, and other types with `derive(CoercePointee)` can be coerced to their corresponding unsized types
//~| ERROR: `NotCoercePointeeData<T>` cannot be coerced to an unsized type, to which `dyn` methods can be dispatched [E0802]
//~| NOTE: `derive(CoercePointee)` demands that `dyn` methods can be dispatched when `NotCoercePointeeData<T>` can be coerced to an unsized type
//~| HELP: `dyn` methods can be dispatched to the standard pointers such as `Arc`, `Rc`, `Box`, and other types with `derive(CoercePointee)`


fn main() {}
123 changes: 87 additions & 36 deletions tests/ui/deriving/deriving-coerce-pointee-neg.stderr
Original file line number Diff line number Diff line change
@@ -7,118 +7,169 @@ LL | #[derive(CoercePointee)]
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0802]: `CoercePointee` can only be derived on `struct`s with at least one field
--> $DIR/deriving-coerce-pointee-neg.rs:15:10
--> $DIR/deriving-coerce-pointee-neg.rs:16: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[E0802]: `CoercePointee` can only be derived on `struct`s with at least one field
--> $DIR/deriving-coerce-pointee-neg.rs:22:10
--> $DIR/deriving-coerce-pointee-neg.rs:25: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[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
--> $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[E0802]: exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits
--> $DIR/deriving-coerce-pointee-neg.rs:34:10
--> $DIR/deriving-coerce-pointee-neg.rs:40: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[E0802]: only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits
--> $DIR/deriving-coerce-pointee-neg.rs:43:39
--> $DIR/deriving-coerce-pointee-neg.rs:50:39
|
LL | struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &'a B));
| ^ - here another type parameter is marked as `#[pointee]`

error[E0802]: `derive(CoercePointee)` requires `T` to be marked `?Sized`
--> $DIR/deriving-coerce-pointee-neg.rs:54:36
--> $DIR/deriving-coerce-pointee-neg.rs:62:36
|
LL | struct NoMaybeSized<'a, #[pointee] T> {
| ^

error: the `#[pointee]` attribute may only be used on generic parameters
--> $DIR/deriving-coerce-pointee-neg.rs:62:5
--> $DIR/deriving-coerce-pointee-neg.rs:70:5
|
LL | #[pointee]
| ^^^^^^^^^^

error: the `#[pointee]` attribute may only be used on generic parameters
--> $DIR/deriving-coerce-pointee-neg.rs:72:33
--> $DIR/deriving-coerce-pointee-neg.rs:80:33
|
LL | struct UhOh<#[pointee] T>(T);
| ^^^^^^^^^^

error: the `#[pointee]` attribute may only be used on generic parameters
--> $DIR/deriving-coerce-pointee-neg.rs:86:21
--> $DIR/deriving-coerce-pointee-neg.rs:94:21
|
LL | struct UhOh<#[pointee] T>(T);
| ^^^^^^^^^^

error: the `#[pointee]` attribute may only be used on generic parameters
--> $DIR/deriving-coerce-pointee-neg.rs:101:25
--> $DIR/deriving-coerce-pointee-neg.rs:109:25
|
LL | struct UhOh<#[pointee] T>(T);
| ^^^^^^^^^^

error[E0392]: lifetime parameter `'a` is never used
--> $DIR/deriving-coerce-pointee-neg.rs:18:16
|
LL | struct NoField<'a, #[pointee] T: ?Sized> {}
| ^^ unused lifetime parameter
|
= 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:18:31
--> $DIR/deriving-coerce-pointee-neg.rs:20:27
|
LL | struct NoField<'a, #[pointee] T: ?Sized> {}
| ^ unused type parameter
LL | struct NoField<#[pointee] T: ?Sized> {}
| ^ unused type parameter
|
= 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:25:20
|
LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
| ^^ unused lifetime parameter
|
= 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:25:35
--> $DIR/deriving-coerce-pointee-neg.rs:29:31
|
LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
| ^ unused type parameter
LL | struct NoFieldUnit<#[pointee] T: ?Sized>();
| ^ unused type parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`

error[E0802]: `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout
--> $DIR/deriving-coerce-pointee-neg.rs:47:1
--> $DIR/deriving-coerce-pointee-neg.rs:55:1
|
LL | struct NotTransparent<'a, #[pointee] T: ?Sized> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0802]: `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout
--> $DIR/deriving-coerce-pointee-neg.rs:140:1
--> $DIR/deriving-coerce-pointee-neg.rs:148:1
|
LL | struct TryToWipeRepr<'a, #[pointee] T: ?Sized> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 17 previous errors
error[E0802]: `Box<T>` cannot be coerced to an unsized value
--> $DIR/deriving-coerce-pointee-neg.rs:156:5
|
LL | inner: std::rc::Rc<(i32, Box<T>)>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `derive(CoercePointee)` demands that `Box<T>` can be coerced to an unsized type
= help: `derive(CoercePointee)` requires exactly one copy of `#[pointee]` type at the end of the `struct` definition, without any further pointer or reference indirection

error[E0802]: `derive(CoercePointee)` only admits exactly one data field, to which `dyn` methods shall be dispatched
--> $DIR/deriving-coerce-pointee-neg.rs:171:5
|
LL | inner1: Box<T>,
| ^^^^^^^^^^^^^^
...
LL | inner2: Box<T>,
| ^^^^^^^^^^^^^^

error[E0802]: `NotCoercePointeeData<T>` cannot be coerced to an unsized type, to which `dyn` methods can be dispatched
--> $DIR/deriving-coerce-pointee-neg.rs:183:45
|
LL | struct UsingNonCoercePointeeData<T: ?Sized>(NotCoercePointeeData<T>);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `derive(CoercePointee)` demands that `dyn` methods can be dispatched when `NotCoercePointeeData<T>` can be coerced to an unsized type
= help: `dyn` methods can be dispatched to the standard pointers such as `Arc`, `Rc`, `Box`, and other types with `derive(CoercePointee)`

error[E0802]: `Box<T>` cannot be coerced to an unsized value
--> $DIR/deriving-coerce-pointee-neg.rs:156:5
|
LL | inner: std::rc::Rc<(i32, Box<T>)>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `derive(CoercePointee)` demands that `Box<T>` can be coerced to an unsized type
= help: `derive(CoercePointee)` requires exactly one copy of `#[pointee]` type at the end of the `struct` definition, without any further pointer or reference indirection
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0802]: `derive(CoercePointee)` only admits exactly one data field, on which unsize coercion shall be performed
--> $DIR/deriving-coerce-pointee-neg.rs:171:5
|
LL | inner1: Box<T>,
| ^^^^^^^^^^^^^^
...
LL | inner2: Box<T>,
| ^^^^^^^^^^^^^^

error[E0802]: `NotCoercePointeeData<T>` cannot be coerced to an unsized type
--> $DIR/deriving-coerce-pointee-neg.rs:183:45
|
LL | struct UsingNonCoercePointeeData<T: ?Sized>(NotCoercePointeeData<T>);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `derive(CoercePointee)` demands that `NotCoercePointeeData<T>` can be coerced to an unsized type
= help: the standard pointers such as `Arc`, `Rc`, `Box`, and other types with `derive(CoercePointee)` can be coerced to their corresponding unsized types

error[E0690]: transparent struct needs at most one field with non-trivial size or alignment, but has 2
--> $DIR/deriving-coerce-pointee-neg.rs:168:1
|
LL | struct MoreThanOneField<T: ?Sized> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs at most one field with non-trivial size or alignment, but has 2
...
LL | inner1: Box<T>,
| -------------- this field has non-zero size or requires alignment
...
LL | inner2: Box<T>,
| -------------- this field has non-zero size or requires alignment

error: aborting due to 22 previous errors

Some errors have detailed explanations: E0392, E0802.
Some errors have detailed explanations: E0392, E0690, E0802.
For more information about an error, try `rustc --explain E0392`.