Rollup merge of #137289 - compiler-errors:coerce-unsized-errors, r=oli-obk
Consolidate and improve error messaging for `CoerceUnsized` and `DispatchFromDyn` Firstly, this PR consolidates and reworks the error diagnostics for `CoercePointee` and `DispatchFromDyn`. There was a ton of duplication for no reason -- this reworks both the errors and also the error codes, since they can be shared between both traits since they report the same thing. Secondly, when encountering a struct with multiple fields that must be coerced, point out the field spans, rather than mentioning the fields by name. This makes the error message clearer, but also means that we don't mention the `__S` dummy parameter for `derive(CoercePointee)`. Thirdly, emit a custom error message when we encounter a trait error that comes from the recursive field `CoerceUnsized`/`DispatchFromDyn` trait check. **Note:** This is the only one I'm not too satisfied with -- I think it could use some more refinement, but ideally it explains that the field must be an unsize-able pointer... Feedback welcome. Finally, don't emit `DispatchFromDyn` validity errors if we detect `CoerceUnsized` validity errors from an impl of the same ADT. This is best reviewed per commit. r? `@oli-obk` perhaps? cc `@dingxiangfei2009` -- sorry for making my own attempt at this PR, but I wanted to see if I could implement a fix for #136796 in a less complicated way, since communicating over github review comments can be a bit slow. I'll leave comments inline to explain my thinking about the diagnostics changes.
This commit is contained in:
commit
0bb00e2085
22 changed files with 313 additions and 315 deletions
|
@ -1,5 +1,5 @@
|
|||
`CoerceUnsized` was implemented on a struct which does not contain a field with
|
||||
an unsized type.
|
||||
`CoerceUnsized` or `DispatchFromDyn` was implemented on a struct which does not
|
||||
contain a field that is being unsized.
|
||||
|
||||
Example of erroneous code:
|
||||
|
||||
|
@ -11,47 +11,20 @@ struct Foo<T: ?Sized> {
|
|||
a: i32,
|
||||
}
|
||||
|
||||
// error: Struct `Foo` has no unsized fields that need `CoerceUnsized`.
|
||||
// error: Struct `Foo` has no unsized fields that need to be coerced.
|
||||
impl<T, U> CoerceUnsized<Foo<U>> for Foo<T>
|
||||
where T: CoerceUnsized<U> {}
|
||||
```
|
||||
|
||||
An [unsized type][1] is any type where the compiler does not know the length or
|
||||
alignment of at compile time. Any struct containing an unsized type is also
|
||||
unsized.
|
||||
`CoerceUnsized` is used to coerce structs that have a field that can be unsized,
|
||||
like a custom `MyBox<T>` being unsized to `MyBox<dyn Trait>`. `DispatchFromDyn`
|
||||
is used to dispatch from `MyBox<dyn Trait>` to `MyBox<Self>` in a dyn-compatible
|
||||
trait.
|
||||
|
||||
[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
|
||||
If the struct doesn't have any fields of unsized types then there is no
|
||||
meaningful way to implement `CoerceUnsized` or `DispatchFromDyn`, since
|
||||
there is no coercion taking place.
|
||||
|
||||
`CoerceUnsized` is used to coerce one struct containing an unsized type
|
||||
into another struct containing a different unsized type. If the struct
|
||||
doesn't have any fields of unsized types then you don't need explicit
|
||||
coercion to get the types you want. To fix this you can either
|
||||
not try to implement `CoerceUnsized` or you can add a field that is
|
||||
unsized to the struct.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#![feature(coerce_unsized)]
|
||||
use std::ops::CoerceUnsized;
|
||||
|
||||
// We don't need to impl `CoerceUnsized` here.
|
||||
struct Foo {
|
||||
a: i32,
|
||||
}
|
||||
|
||||
// We add the unsized type field to the struct.
|
||||
struct Bar<T: ?Sized> {
|
||||
a: i32,
|
||||
b: T,
|
||||
}
|
||||
|
||||
// The struct has an unsized field so we can implement
|
||||
// `CoerceUnsized` for it.
|
||||
impl<T, U> CoerceUnsized<Bar<U>> for Bar<T>
|
||||
where T: CoerceUnsized<U> {}
|
||||
```
|
||||
|
||||
Note that `CoerceUnsized` is mainly used by smart pointers like `Box`, `Rc`
|
||||
and `Arc` to be able to mark that they can coerce unsized types that they
|
||||
are pointing at.
|
||||
Note that `CoerceUnsized` and `DispatchFromDyn` is mainly used by smart pointers
|
||||
like `Box`, `Rc` and `Arc` to be able to mark that they can coerce unsized types
|
||||
that they are pointing at.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
`CoerceUnsized` was implemented on a struct which contains more than one field
|
||||
with an unsized type.
|
||||
`CoerceUnsized` or `DispatchFromDyn` was implemented on a struct which contains
|
||||
more than one field that is being unsized.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
|
@ -17,39 +17,14 @@ struct Foo<T: ?Sized, U: ?Sized> {
|
|||
impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
|
||||
```
|
||||
|
||||
A struct with more than one field containing an unsized type cannot implement
|
||||
`CoerceUnsized`. This only occurs when you are trying to coerce one of the
|
||||
types in your struct to another type in the struct. In this case we try to
|
||||
impl `CoerceUnsized` from `T` to `U` which are both types that the struct
|
||||
takes. An [unsized type][1] is any type that the compiler doesn't know the
|
||||
length or alignment of at compile time. Any struct containing an unsized type
|
||||
is also unsized.
|
||||
`CoerceUnsized` is used to coerce structs that have a field that can be unsized,
|
||||
like a custom `MyBox<T>` being unsized to `MyBox<dyn Trait>`. `DispatchFromDyn`
|
||||
is used to dispatch from `MyBox<dyn Trait>` to `MyBox<Self>` in a dyn-compatible
|
||||
trait.
|
||||
|
||||
`CoerceUnsized` only allows for coercion from a structure with a single
|
||||
unsized type field to another struct with a single unsized type field.
|
||||
In fact Rust only allows for a struct to have one unsized type in a struct
|
||||
and that unsized type must be the last field in the struct. So having two
|
||||
unsized types in a single struct is not allowed by the compiler. To fix this
|
||||
use only one field containing an unsized type in the struct and then use
|
||||
multiple structs to manage each unsized type field you need.
|
||||
If the struct has multiple fields that must be unsized, then the compiler has no
|
||||
way to generate a valid implementation of `CoerceUnsized` or `DispatchFromDyn`.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#![feature(coerce_unsized)]
|
||||
use std::ops::CoerceUnsized;
|
||||
|
||||
struct Foo<T: ?Sized> {
|
||||
a: i32,
|
||||
b: T,
|
||||
}
|
||||
|
||||
impl <T, U> CoerceUnsized<Foo<U>> for Foo<T>
|
||||
where T: CoerceUnsized<U> {}
|
||||
|
||||
fn coerce_foo<T: CoerceUnsized<U>, U>(t: T) -> Foo<U> {
|
||||
Foo { a: 12i32, b: t } // we use coercion to get the `Foo<U>` type we need
|
||||
}
|
||||
```
|
||||
|
||||
[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
|
||||
Note that `CoerceUnsized` and `DispatchFromDyn` is mainly used by smart pointers
|
||||
like `Box`, `Rc` and `Arc` to be able to mark that they can coerce unsized types
|
||||
that they are pointing at.
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
`CoerceUnsized` was implemented on something that isn't a struct.
|
||||
#### Note: this error code is no longer emitted by the compiler.
|
||||
|
||||
`CoerceUnsized` or `DispatchFromDyn` was implemented between two types that
|
||||
are not structs.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0376
|
||||
```compile_fail,E0377
|
||||
#![feature(coerce_unsized)]
|
||||
use std::ops::CoerceUnsized;
|
||||
|
||||
|
@ -14,33 +17,4 @@ struct Foo<T: ?Sized> {
|
|||
impl<T, U> CoerceUnsized<U> for Foo<T> {}
|
||||
```
|
||||
|
||||
`CoerceUnsized` can only be implemented for a struct. Unsized types are
|
||||
already able to be coerced without an implementation of `CoerceUnsized`
|
||||
whereas a struct containing an unsized type needs to know the unsized type
|
||||
field it's containing is able to be coerced. An [unsized type][1]
|
||||
is any type that the compiler doesn't know the length or alignment of at
|
||||
compile time. Any struct containing an unsized type is also unsized.
|
||||
|
||||
[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait
|
||||
|
||||
The `CoerceUnsized` trait takes a struct type. Make sure the type you are
|
||||
providing to `CoerceUnsized` is a struct with only the last field containing an
|
||||
unsized type.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#![feature(coerce_unsized)]
|
||||
use std::ops::CoerceUnsized;
|
||||
|
||||
struct Foo<T> {
|
||||
a: T,
|
||||
}
|
||||
|
||||
// The `Foo<U>` is a struct so `CoerceUnsized` can be implemented
|
||||
impl<T, U> CoerceUnsized<Foo<U>> for Foo<T> where T: CoerceUnsized<U> {}
|
||||
```
|
||||
|
||||
Note that in Rust, structs can only contain an unsized type if the field
|
||||
containing the unsized type is the last and only unsized type field in the
|
||||
struct.
|
||||
`CoerceUnsized` or `DispatchFromDyn` can only be implemented between structs.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
The trait `CoerceUnsized` may only be implemented for a coercion between
|
||||
structures with the same definition.
|
||||
`CoerceUnsized` or `DispatchFromDyn` may only be implemented between structs
|
||||
of the same type.
|
||||
|
||||
Example of erroneous code:
|
||||
|
||||
|
@ -20,10 +20,15 @@ pub struct Bar<T: ?Sized> {
|
|||
impl<T, U> CoerceUnsized<Bar<U>> for Foo<T> where T: CoerceUnsized<U> {}
|
||||
```
|
||||
|
||||
When attempting to implement `CoerceUnsized`, the `impl` signature must look
|
||||
like: `impl CoerceUnsized<Type<U>> for Type<T> where T: CoerceUnsized<U>`;
|
||||
the *implementer* and *`CoerceUnsized` type parameter* must be the same
|
||||
type. In this example, `Bar` and `Foo` (even though structurally identical)
|
||||
are *not* the same type and are rejected. Learn more about the `CoerceUnsized`
|
||||
trait and DST coercion in
|
||||
[the `CoerceUnsized` docs](../std/ops/trait.CoerceUnsized.html).
|
||||
`CoerceUnsized` is used to coerce structs that have a field that can be unsized,
|
||||
like a custom `MyBox<T>` being unsized to `MyBox<dyn Trait>`. `DispatchFromDyn`
|
||||
is used to dispatch from `MyBox<dyn Trait>` to `MyBox<Self>` in a dyn-compatible
|
||||
trait.
|
||||
|
||||
The compiler cannot support coercions between structs of different types, so
|
||||
a valid implementation of `CoerceUnsized` or `DispatchFromDyn` should be
|
||||
implemented between the same struct with different generic parameters.
|
||||
|
||||
Note that `CoerceUnsized` and `DispatchFromDyn` is mainly used by smart pointers
|
||||
like `Box`, `Rc` and `Arc` to be able to mark that they can coerce unsized types
|
||||
that they are pointing at.
|
||||
|
|
|
@ -85,6 +85,10 @@ 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_multi = implementing `{$trait_name}` does not allow multiple fields to be coerced
|
||||
.note = the trait `{$trait_name}` may only be implemented when a single field is being coerced
|
||||
.label = these fields must be coerced for `{$trait_name}` to be valid
|
||||
|
||||
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
|
||||
|
@ -95,12 +99,12 @@ hir_analysis_coerce_pointee_not_struct = `derive(CoercePointee)` is only applica
|
|||
|
||||
hir_analysis_coerce_pointee_not_transparent = `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout
|
||||
|
||||
hir_analysis_coerce_unsized_field_validity = for `{$ty}` to have a valid implementation of `{$trait_name}`, it must be possible to coerce the field of type `{$field_ty}`
|
||||
.label = `{$field_ty}` must be a pointer, reference, or smart pointer that is allowed to be unsized
|
||||
|
||||
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
|
||||
.note = `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
|
||||
.coercions_note = currently, {$number} fields need coercions: {$coercions}
|
||||
.label = requires multiple coercions
|
||||
hir_analysis_coerce_zero = implementing `{$trait_name}` requires a field to be coerced
|
||||
|
||||
hir_analysis_coercion_between_struct_same_note = expected coercion between the same definition; expected `{$source_path}`, found `{$target_path}`
|
||||
|
||||
|
@ -139,10 +143,6 @@ hir_analysis_cross_crate_traits = cross-crate traits with a default impl, like `
|
|||
hir_analysis_cross_crate_traits_defined = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type defined in the current crate
|
||||
.label = can't implement cross-crate trait for type in another crate
|
||||
|
||||
hir_analysis_dispatch_from_dyn_multi = implementing the `DispatchFromDyn` trait requires multiple coercions
|
||||
.note = the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced
|
||||
.coercions_note = currently, {$number} fields need coercions: {$coercions}
|
||||
|
||||
hir_analysis_dispatch_from_dyn_repr = structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]`
|
||||
|
||||
hir_analysis_dispatch_from_dyn_zst = the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else
|
||||
|
|
|
@ -17,7 +17,7 @@ use rustc_middle::ty::print::PrintTraitRefExt as _;
|
|||
use rustc_middle::ty::{
|
||||
self, Ty, TyCtxt, TypeVisitableExt, TypingMode, suggest_constraining_type_params,
|
||||
};
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_span::{DUMMY_SP, Span, sym};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::traits::misc::{
|
||||
ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason,
|
||||
|
@ -195,8 +195,14 @@ fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), E
|
|||
// Just compute this for the side-effects, in particular reporting
|
||||
// errors; other parts of the code may demand it for the info of
|
||||
// course.
|
||||
let span = tcx.def_span(impl_did);
|
||||
tcx.at(span).ensure_ok().coerce_unsized_info(impl_did)
|
||||
tcx.ensure_ok().coerce_unsized_info(impl_did)
|
||||
}
|
||||
|
||||
fn is_from_coerce_pointee_derive(tcx: TyCtxt<'_>, span: Span) -> bool {
|
||||
span.ctxt()
|
||||
.outer_expn_data()
|
||||
.macro_def_id
|
||||
.is_some_and(|def_id| tcx.is_diagnostic_item(sym::CoercePointee, def_id))
|
||||
}
|
||||
|
||||
fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
|
||||
|
@ -206,17 +212,29 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
|
|||
debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did);
|
||||
|
||||
let span = tcx.def_span(impl_did);
|
||||
let trait_name = "DispatchFromDyn";
|
||||
|
||||
let dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span));
|
||||
|
||||
let source = trait_ref.self_ty();
|
||||
assert!(!source.has_escaping_bound_vars());
|
||||
let target = {
|
||||
assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
|
||||
|
||||
trait_ref.args.type_at(1)
|
||||
};
|
||||
|
||||
// Check `CoercePointee` impl is WF -- if not, then there's no reason to report
|
||||
// redundant errors for `DispatchFromDyn`. This is best effort, though.
|
||||
let mut res = Ok(());
|
||||
tcx.for_each_relevant_impl(
|
||||
tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)),
|
||||
source,
|
||||
|impl_def_id| {
|
||||
res = res.and(tcx.ensure_ok().coerce_unsized_info(impl_def_id));
|
||||
},
|
||||
);
|
||||
res?;
|
||||
|
||||
debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}", source, target);
|
||||
|
||||
let param_env = tcx.param_env(impl_did);
|
||||
|
@ -242,26 +260,25 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
|
|||
if def_a != def_b {
|
||||
let source_path = tcx.def_path_str(def_a.did());
|
||||
let target_path = tcx.def_path_str(def_b.did());
|
||||
|
||||
return Err(tcx.dcx().emit_err(errors::DispatchFromDynCoercion {
|
||||
return Err(tcx.dcx().emit_err(errors::CoerceSameStruct {
|
||||
span,
|
||||
trait_name: "DispatchFromDyn",
|
||||
trait_name,
|
||||
note: true,
|
||||
source_path,
|
||||
target_path,
|
||||
}));
|
||||
}
|
||||
|
||||
let mut res = Ok(());
|
||||
if def_a.repr().c() || def_a.repr().packed() {
|
||||
res = Err(tcx.dcx().emit_err(errors::DispatchFromDynRepr { span }));
|
||||
return Err(tcx.dcx().emit_err(errors::DispatchFromDynRepr { span }));
|
||||
}
|
||||
|
||||
let fields = &def_a.non_enum_variant().fields;
|
||||
|
||||
let mut res = Ok(());
|
||||
let coerced_fields = fields
|
||||
.iter()
|
||||
.filter(|field| {
|
||||
.iter_enumerated()
|
||||
.filter_map(|(i, field)| {
|
||||
// Ignore PhantomData fields
|
||||
let unnormalized_ty = tcx.type_of(field.did).instantiate_identity();
|
||||
if tcx
|
||||
|
@ -272,7 +289,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
|
|||
.unwrap_or(unnormalized_ty)
|
||||
.is_phantom_data()
|
||||
{
|
||||
return false;
|
||||
return None;
|
||||
}
|
||||
|
||||
let ty_a = field.ty(tcx, args_a);
|
||||
|
@ -290,7 +307,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
|
|||
&& !ty_a.has_non_region_param()
|
||||
{
|
||||
// ignore 1-ZST fields
|
||||
return false;
|
||||
return None;
|
||||
}
|
||||
|
||||
res = Err(tcx.dcx().emit_err(errors::DispatchFromDynZST {
|
||||
|
@ -299,64 +316,57 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
|
|||
ty: ty_a,
|
||||
}));
|
||||
|
||||
return false;
|
||||
None
|
||||
} else {
|
||||
Some((i, ty_a, ty_b, tcx.def_span(field.did)))
|
||||
}
|
||||
|
||||
true
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
res?;
|
||||
|
||||
if coerced_fields.is_empty() {
|
||||
res = Err(tcx.dcx().emit_err(errors::DispatchFromDynSingle {
|
||||
return Err(tcx.dcx().emit_err(errors::CoerceNoField {
|
||||
span,
|
||||
trait_name: "DispatchFromDyn",
|
||||
trait_name,
|
||||
note: true,
|
||||
}));
|
||||
} else if coerced_fields.len() > 1 {
|
||||
res = Err(tcx.dcx().emit_err(errors::DispatchFromDynMulti {
|
||||
span,
|
||||
coercions_note: true,
|
||||
number: coerced_fields.len(),
|
||||
coercions: coerced_fields
|
||||
.iter()
|
||||
.map(|field| {
|
||||
format!(
|
||||
"`{}` (`{}` to `{}`)",
|
||||
field.name,
|
||||
field.ty(tcx, args_a),
|
||||
field.ty(tcx, args_b),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
}));
|
||||
} else {
|
||||
} else if let &[(_, ty_a, ty_b, field_span)] = &coerced_fields[..] {
|
||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||
for field in coerced_fields {
|
||||
ocx.register_obligation(Obligation::new(
|
||||
tcx,
|
||||
cause.clone(),
|
||||
param_env,
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
dispatch_from_dyn_trait,
|
||||
[field.ty(tcx, args_a), field.ty(tcx, args_b)],
|
||||
),
|
||||
));
|
||||
}
|
||||
ocx.register_obligation(Obligation::new(
|
||||
tcx,
|
||||
cause.clone(),
|
||||
param_env,
|
||||
ty::TraitRef::new(tcx, dispatch_from_dyn_trait, [ty_a, ty_b]),
|
||||
));
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
res = Err(infcx.err_ctxt().report_fulfillment_errors(errors));
|
||||
if is_from_coerce_pointee_derive(tcx, span) {
|
||||
return Err(tcx.dcx().emit_err(errors::CoerceFieldValidity {
|
||||
span,
|
||||
trait_name,
|
||||
ty: trait_ref.self_ty(),
|
||||
field_span,
|
||||
field_ty: ty_a,
|
||||
}));
|
||||
} else {
|
||||
return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, resolve all regions.
|
||||
res = res.and(ocx.resolve_regions_and_report_errors(impl_did, param_env, []));
|
||||
ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?;
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
return Err(tcx.dcx().emit_err(errors::CoerceMulti {
|
||||
span,
|
||||
trait_name,
|
||||
number: coerced_fields.len(),
|
||||
fields: coerced_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(),
|
||||
}));
|
||||
}
|
||||
res
|
||||
}
|
||||
_ => Err(tcx
|
||||
.dcx()
|
||||
.emit_err(errors::CoerceUnsizedMay { span, trait_name: "DispatchFromDyn" })),
|
||||
_ => Err(tcx.dcx().emit_err(errors::CoerceUnsizedNonStruct { span, trait_name })),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,13 +376,14 @@ pub(crate) fn coerce_unsized_info<'tcx>(
|
|||
) -> Result<CoerceUnsizedInfo, ErrorGuaranteed> {
|
||||
debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
|
||||
let span = tcx.def_span(impl_did);
|
||||
let trait_name = "CoerceUnsized";
|
||||
|
||||
let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
|
||||
|
||||
let unsize_trait = tcx.require_lang_item(LangItem::Unsize, Some(span));
|
||||
|
||||
let source = tcx.type_of(impl_did).instantiate_identity();
|
||||
let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().instantiate_identity();
|
||||
|
||||
assert_eq!(trait_ref.def_id, coerce_unsized_trait);
|
||||
let target = trait_ref.args.type_at(1);
|
||||
debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target);
|
||||
|
@ -399,9 +410,9 @@ pub(crate) fn coerce_unsized_info<'tcx>(
|
|||
)
|
||||
.emit();
|
||||
}
|
||||
(mt_a.ty, mt_b.ty, unsize_trait, None)
|
||||
(mt_a.ty, mt_b.ty, unsize_trait, None, span)
|
||||
};
|
||||
let (source, target, trait_def_id, kind) = match (source.kind(), target.kind()) {
|
||||
let (source, target, trait_def_id, kind, field_span) = match (source.kind(), target.kind()) {
|
||||
(&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
|
||||
infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a);
|
||||
let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
|
||||
|
@ -422,9 +433,9 @@ pub(crate) fn coerce_unsized_info<'tcx>(
|
|||
if def_a != def_b {
|
||||
let source_path = tcx.def_path_str(def_a.did());
|
||||
let target_path = tcx.def_path_str(def_b.did());
|
||||
return Err(tcx.dcx().emit_err(errors::DispatchFromDynSame {
|
||||
return Err(tcx.dcx().emit_err(errors::CoerceSameStruct {
|
||||
span,
|
||||
trait_name: "CoerceUnsized",
|
||||
trait_name,
|
||||
note: true,
|
||||
source_path,
|
||||
target_path,
|
||||
|
@ -504,14 +515,14 @@ pub(crate) fn coerce_unsized_info<'tcx>(
|
|||
|
||||
// Collect up all fields that were significantly changed
|
||||
// i.e., those that contain T in coerce_unsized T -> U
|
||||
Some((i, a, b))
|
||||
Some((i, a, b, tcx.def_span(f.did)))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if diff_fields.is_empty() {
|
||||
return Err(tcx.dcx().emit_err(errors::CoerceUnsizedOneField {
|
||||
return Err(tcx.dcx().emit_err(errors::CoerceNoField {
|
||||
span,
|
||||
trait_name: "CoerceUnsized",
|
||||
trait_name,
|
||||
note: true,
|
||||
}));
|
||||
} else if diff_fields.len() > 1 {
|
||||
|
@ -522,27 +533,21 @@ pub(crate) fn coerce_unsized_info<'tcx>(
|
|||
tcx.def_span(impl_did)
|
||||
};
|
||||
|
||||
return Err(tcx.dcx().emit_err(errors::CoerceUnsizedMulti {
|
||||
return Err(tcx.dcx().emit_err(errors::CoerceMulti {
|
||||
span,
|
||||
coercions_note: true,
|
||||
trait_name,
|
||||
number: diff_fields.len(),
|
||||
coercions: diff_fields
|
||||
.iter()
|
||||
.map(|&(i, a, b)| format!("`{}` (`{}` to `{}`)", fields[i].name, a, b))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
fields: diff_fields.iter().map(|(_, _, _, s)| *s).collect::<Vec<_>>().into(),
|
||||
}));
|
||||
}
|
||||
|
||||
let (i, a, b) = diff_fields[0];
|
||||
let (i, a, b, field_span) = diff_fields[0];
|
||||
let kind = ty::adjustment::CustomCoerceUnsized::Struct(i);
|
||||
(a, b, coerce_unsized_trait, Some(kind))
|
||||
(a, b, coerce_unsized_trait, Some(kind), field_span)
|
||||
}
|
||||
|
||||
_ => {
|
||||
return Err(tcx
|
||||
.dcx()
|
||||
.emit_err(errors::DispatchFromDynStruct { span, trait_name: "CoerceUnsized" }));
|
||||
return Err(tcx.dcx().emit_err(errors::CoerceUnsizedNonStruct { span, trait_name }));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -557,12 +562,23 @@ pub(crate) fn coerce_unsized_info<'tcx>(
|
|||
);
|
||||
ocx.register_obligation(obligation);
|
||||
let errors = ocx.select_all_or_error();
|
||||
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(errors);
|
||||
if is_from_coerce_pointee_derive(tcx, span) {
|
||||
return Err(tcx.dcx().emit_err(errors::CoerceFieldValidity {
|
||||
span,
|
||||
trait_name,
|
||||
ty: trait_ref.self_ty(),
|
||||
field_span,
|
||||
field_ty: source,
|
||||
}));
|
||||
} else {
|
||||
return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, resolve all regions.
|
||||
let _ = ocx.resolve_regions_and_report_errors(impl_did, param_env, []);
|
||||
ocx.resolve_regions_and_report_errors(impl_did, param_env, [])?;
|
||||
|
||||
Ok(CoerceUnsizedInfo { custom_kind: kind })
|
||||
}
|
||||
|
|
|
@ -1164,18 +1164,6 @@ pub(crate) struct InherentTyOutside {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_coerce_unsized_may, code = E0378)]
|
||||
pub(crate) struct DispatchFromDynCoercion<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub trait_name: &'a str,
|
||||
#[note(hir_analysis_coercion_between_struct_same_note)]
|
||||
pub note: bool,
|
||||
pub source_path: String,
|
||||
pub target_path: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_dispatch_from_dyn_repr, code = E0378)]
|
||||
pub(crate) struct DispatchFromDynRepr {
|
||||
|
@ -1293,41 +1281,40 @@ pub(crate) struct DispatchFromDynZST<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_coerce_unsized_may, code = E0378)]
|
||||
pub(crate) struct DispatchFromDynSingle<'a> {
|
||||
#[diag(hir_analysis_coerce_zero, code = E0374)]
|
||||
pub(crate) struct CoerceNoField {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub trait_name: &'a str,
|
||||
pub trait_name: &'static str,
|
||||
#[note(hir_analysis_coercion_between_struct_single_note)]
|
||||
pub note: bool,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_dispatch_from_dyn_multi, code = E0378)]
|
||||
#[note]
|
||||
pub(crate) struct DispatchFromDynMulti {
|
||||
#[diag(hir_analysis_coerce_multi, code = E0375)]
|
||||
pub(crate) struct CoerceMulti {
|
||||
pub trait_name: &'static str,
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[note(hir_analysis_coercions_note)]
|
||||
pub coercions_note: bool,
|
||||
pub number: usize,
|
||||
pub coercions: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_coerce_unsized_may, code = E0376)]
|
||||
pub(crate) struct DispatchFromDynStruct<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub trait_name: &'a str,
|
||||
#[note]
|
||||
pub fields: MultiSpan,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_coerce_unsized_may, code = E0377)]
|
||||
pub(crate) struct DispatchFromDynSame<'a> {
|
||||
pub(crate) struct CoerceUnsizedNonStruct {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub trait_name: &'a str,
|
||||
pub trait_name: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_coerce_unsized_may, code = E0377)]
|
||||
pub(crate) struct CoerceSameStruct {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub trait_name: &'static str,
|
||||
#[note(hir_analysis_coercion_between_struct_same_note)]
|
||||
pub note: bool,
|
||||
pub source_path: String,
|
||||
|
@ -1335,34 +1322,15 @@ pub(crate) struct DispatchFromDynSame<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_coerce_unsized_may, code = E0374)]
|
||||
pub(crate) struct CoerceUnsizedOneField<'a> {
|
||||
#[diag(hir_analysis_coerce_unsized_field_validity)]
|
||||
pub(crate) struct CoerceFieldValidity<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub trait_name: &'a str,
|
||||
#[note(hir_analysis_coercion_between_struct_single_note)]
|
||||
pub note: bool,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_coerce_unsized_multi, code = E0375)]
|
||||
#[note]
|
||||
pub(crate) struct CoerceUnsizedMulti {
|
||||
#[primary_span]
|
||||
pub ty: Ty<'tcx>,
|
||||
pub trait_name: &'static str,
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[note(hir_analysis_coercions_note)]
|
||||
pub coercions_note: bool,
|
||||
pub number: usize,
|
||||
pub coercions: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_coerce_unsized_may, code = E0378)]
|
||||
pub(crate) struct CoerceUnsizedMay<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub trait_name: &'a str,
|
||||
pub field_span: Span,
|
||||
pub field_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
@ -1302,6 +1302,7 @@ pub trait FnPtr: Copy + Clone {
|
|||
/// ```
|
||||
#[rustc_builtin_macro(CoercePointee, attributes(pointee))]
|
||||
#[allow_internal_unstable(dispatch_from_dyn, coerce_unsized, unsize, coerce_pointee_validated)]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "CoercePointee")]
|
||||
#[unstable(feature = "derive_coerce_pointee", issue = "123430")]
|
||||
pub macro CoercePointee($item:item) {
|
||||
/* compiler built-in */
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions
|
||||
error[E0375]: implementing `CoerceUnsized` does not allow multiple fields to be coerced
|
||||
--> $DIR/issue-26905.rs:16:40
|
||||
|
|
||||
LL | impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<MyRc<U>> for MyRc<T>{ }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
|
||||
= note: currently, 2 fields need coercions: `_ptr` (`*const T` to `*const U`), `_boo` (`NotPhantomData<T>` to `NotPhantomData<U>`)
|
||||
note: the trait `CoerceUnsized` may only be implemented when a single field is being coerced
|
||||
--> $DIR/issue-26905.rs:12:5
|
||||
|
|
||||
LL | _ptr: *const T,
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | _boo: NotPhantomData<T>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -142,4 +142,27 @@ struct TryToWipeRepr<'a, #[pointee] T: ?Sized> {
|
|||
ptr: &'a T,
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(CoercePointee)]
|
||||
//~^ ERROR for `RcWithId<T>` to have a valid implementation of `CoerceUnsized`, it must be possible to coerce the field of type `Rc<(i32, Box<T>)>`
|
||||
struct RcWithId<T: ?Sized> {
|
||||
inner: std::rc::Rc<(i32, Box<T>)>,
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(CoercePointee)]
|
||||
//~^ ERROR implementing `CoerceUnsized` does not allow multiple fields to be coerced
|
||||
struct MoreThanOneField<T: ?Sized> {
|
||||
//~^ ERROR transparent struct needs at most one field with non-trivial size or alignment, but has 2
|
||||
inner1: Box<T>,
|
||||
inner2: Box<T>,
|
||||
}
|
||||
|
||||
struct NotCoercePointeeData<T: ?Sized>(T);
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(CoercePointee)]
|
||||
//~^ ERROR for `UsingNonCoercePointeeData<T>` to have a valid implementation of `CoerceUnsized`, it must be possible to coerce the field of type `NotCoercePointeeData<T>`
|
||||
struct UsingNonCoercePointeeData<T: ?Sized>(NotCoercePointeeData<T>);
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -118,7 +118,55 @@ error[E0802]: `derive(CoercePointee)` is only applicable to `struct` with `repr(
|
|||
LL | struct TryToWipeRepr<'a, #[pointee] T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 17 previous errors
|
||||
error: for `RcWithId<T>` to have a valid implementation of `CoerceUnsized`, it must be possible to coerce the field of type `Rc<(i32, Box<T>)>`
|
||||
--> $DIR/deriving-coerce-pointee-neg.rs:146:10
|
||||
|
|
||||
LL | #[derive(CoercePointee)]
|
||||
| ^^^^^^^^^^^^^
|
||||
...
|
||||
LL | inner: std::rc::Rc<(i32, Box<T>)>,
|
||||
| --------------------------------- `Rc<(i32, Box<T>)>` must be a pointer, reference, or smart pointer that is allowed to be unsized
|
||||
|
|
||||
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
Some errors have detailed explanations: E0392, E0802.
|
||||
For more information about an error, try `rustc --explain E0392`.
|
||||
error[E0375]: implementing `CoerceUnsized` does not allow multiple fields to be coerced
|
||||
--> $DIR/deriving-coerce-pointee-neg.rs:153:10
|
||||
|
|
||||
LL | #[derive(CoercePointee)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
note: the trait `CoerceUnsized` may only be implemented when a single field is being coerced
|
||||
--> $DIR/deriving-coerce-pointee-neg.rs:157:5
|
||||
|
|
||||
LL | inner1: Box<T>,
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | inner2: Box<T>,
|
||||
| ^^^^^^^^^^^^^^
|
||||
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: for `UsingNonCoercePointeeData<T>` to have a valid implementation of `CoerceUnsized`, it must be possible to coerce the field of type `NotCoercePointeeData<T>`
|
||||
--> $DIR/deriving-coerce-pointee-neg.rs:164:10
|
||||
|
|
||||
LL | #[derive(CoercePointee)]
|
||||
| ^^^^^^^^^^^^^
|
||||
LL |
|
||||
LL | struct UsingNonCoercePointeeData<T: ?Sized>(NotCoercePointeeData<T>);
|
||||
| ----------------------- `NotCoercePointeeData<T>` must be a pointer, reference, or smart pointer that is allowed to be unsized
|
||||
|
|
||||
= note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0690]: transparent struct needs at most one field with non-trivial size or alignment, but has 2
|
||||
--> $DIR/deriving-coerce-pointee-neg.rs:155:1
|
||||
|
|
||||
LL | struct MoreThanOneField<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ needs at most one field with non-trivial size or alignment, but has 2
|
||||
LL |
|
||||
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 21 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0375, E0392, E0690, E0802.
|
||||
For more information about an error, try `rustc --explain E0375`.
|
||||
|
|
|
@ -6,7 +6,7 @@ LL | struct Foo<T: ?Sized> {
|
|||
|
|
||||
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
|
||||
|
||||
error[E0374]: the trait `CoerceUnsized` may only be implemented for a coercion between structures
|
||||
error[E0374]: implementing `CoerceUnsized` requires a field to be coerced
|
||||
--> $DIR/E0374.rs:8:1
|
||||
|
|
||||
LL | / impl<T, U> CoerceUnsized<Foo<U>> for Foo<T>
|
||||
|
|
|
@ -23,14 +23,19 @@ help: the `Box` type always has a statically known size and allocates its conten
|
|||
LL | b: Box<T>,
|
||||
| ++++ +
|
||||
|
||||
error[E0375]: implementing the trait `CoerceUnsized` requires multiple coercions
|
||||
error[E0375]: implementing `CoerceUnsized` does not allow multiple fields to be coerced
|
||||
--> $DIR/E0375.rs:10:12
|
||||
|
|
||||
LL | impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ requires multiple coercions
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `CoerceUnsized` may only be implemented for a coercion between structures with one field being coerced
|
||||
= note: currently, 2 fields need coercions: `b` (`T` to `U`), `c` (`U` to `T`)
|
||||
note: the trait `CoerceUnsized` may only be implemented when a single field is being coerced
|
||||
--> $DIR/E0375.rs:6:5
|
||||
|
|
||||
LL | b: T,
|
||||
| ^^^^
|
||||
LL | c: U,
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
#![feature(coerce_unsized)]
|
||||
use std::ops::CoerceUnsized;
|
||||
|
||||
struct Foo<T: ?Sized> {
|
||||
a: T,
|
||||
}
|
||||
|
||||
impl<T, U> CoerceUnsized<U> for Foo<T> {} //~ ERROR E0376
|
||||
|
||||
fn main() {}
|
|
@ -1,9 +0,0 @@
|
|||
error[E0376]: the trait `CoerceUnsized` may only be implemented for a coercion between structures
|
||||
--> $DIR/E0376.rs:8:1
|
||||
|
|
||||
LL | impl<T, U> CoerceUnsized<U> for Foo<T> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0376`.
|
|
@ -8,9 +8,10 @@ use std::{
|
|||
struct WrapperWithExtraField<T>(T, i32);
|
||||
|
||||
impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
|
||||
//~^ ERROR [E0378]
|
||||
where
|
||||
T: DispatchFromDyn<U>,
|
||||
{} //~^^^ ERROR [E0378]
|
||||
{}
|
||||
|
||||
|
||||
struct MultiplePointers<T: ?Sized>{
|
||||
|
@ -19,9 +20,10 @@ struct MultiplePointers<T: ?Sized>{
|
|||
}
|
||||
|
||||
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T>
|
||||
//~^ implementing `DispatchFromDyn` does not allow multiple fields to be coerced
|
||||
where
|
||||
T: Unsize<U>,
|
||||
{} //~^^^ ERROR [E0378]
|
||||
{}
|
||||
|
||||
|
||||
struct NothingToCoerce<T: ?Sized> {
|
||||
|
@ -29,23 +31,25 @@ struct NothingToCoerce<T: ?Sized> {
|
|||
}
|
||||
|
||||
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {}
|
||||
//~^ ERROR [E0378]
|
||||
//~^ ERROR implementing `DispatchFromDyn` requires a field to be coerced
|
||||
|
||||
#[repr(C)]
|
||||
struct HasReprC<T: ?Sized>(Box<T>);
|
||||
|
||||
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<HasReprC<U>> for HasReprC<T>
|
||||
//~^ ERROR [E0378]
|
||||
where
|
||||
T: Unsize<U>,
|
||||
{} //~^^^ ERROR [E0378]
|
||||
{}
|
||||
|
||||
#[repr(align(64))]
|
||||
struct OverAlignedZst;
|
||||
struct OverAligned<T: ?Sized>(Box<T>, OverAlignedZst);
|
||||
|
||||
impl<T: ?Sized, U: ?Sized> DispatchFromDyn<OverAligned<U>> for OverAligned<T>
|
||||
//~^ ERROR [E0378]
|
||||
where
|
||||
T: Unsize<U>,
|
||||
{} //~^^^ ERROR [E0378]
|
||||
{}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -2,25 +2,32 @@ error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs co
|
|||
--> $DIR/invalid_dispatch_from_dyn_impls.rs:10:1
|
||||
|
|
||||
LL | / impl<T, U> DispatchFromDyn<WrapperWithExtraField<U>> for WrapperWithExtraField<T>
|
||||
LL | |
|
||||
LL | | where
|
||||
LL | | T: DispatchFromDyn<U>,
|
||||
| |__________________________^
|
||||
|
|
||||
= note: extra field `1` of type `i32` is not allowed
|
||||
|
||||
error[E0378]: implementing the `DispatchFromDyn` trait requires multiple coercions
|
||||
--> $DIR/invalid_dispatch_from_dyn_impls.rs:21:1
|
||||
error[E0375]: implementing `DispatchFromDyn` does not allow multiple fields to be coerced
|
||||
--> $DIR/invalid_dispatch_from_dyn_impls.rs:22:1
|
||||
|
|
||||
LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<MultiplePointers<U>> for MultiplePointers<T>
|
||||
LL | |
|
||||
LL | | where
|
||||
LL | | T: Unsize<U>,
|
||||
| |_________________^
|
||||
|
|
||||
= note: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced
|
||||
= note: currently, 2 fields need coercions: `ptr1` (`*const T` to `*const U`), `ptr2` (`*const T` to `*const U`)
|
||||
note: the trait `DispatchFromDyn` may only be implemented when a single field is being coerced
|
||||
--> $DIR/invalid_dispatch_from_dyn_impls.rs:18:5
|
||||
|
|
||||
LL | ptr1: *const T,
|
||||
| ^^^^^^^^^^^^^^
|
||||
LL | ptr2: *const T,
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
|
||||
--> $DIR/invalid_dispatch_from_dyn_impls.rs:31:1
|
||||
error[E0374]: implementing `DispatchFromDyn` requires a field to be coerced
|
||||
--> $DIR/invalid_dispatch_from_dyn_impls.rs:33:1
|
||||
|
|
||||
LL | impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingToCoerce<U> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -28,17 +35,19 @@ LL | impl<T: ?Sized, U: ?Sized> DispatchFromDyn<NothingToCoerce<T>> for NothingT
|
|||
= note: expected a single field to be coerced, none found
|
||||
|
||||
error[E0378]: structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]`
|
||||
--> $DIR/invalid_dispatch_from_dyn_impls.rs:37:1
|
||||
--> $DIR/invalid_dispatch_from_dyn_impls.rs:39:1
|
||||
|
|
||||
LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<HasReprC<U>> for HasReprC<T>
|
||||
LL | |
|
||||
LL | | where
|
||||
LL | | T: Unsize<U>,
|
||||
| |_________________^
|
||||
|
||||
error[E0378]: the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else
|
||||
--> $DIR/invalid_dispatch_from_dyn_impls.rs:46:1
|
||||
--> $DIR/invalid_dispatch_from_dyn_impls.rs:49:1
|
||||
|
|
||||
LL | / impl<T: ?Sized, U: ?Sized> DispatchFromDyn<OverAligned<U>> for OverAligned<T>
|
||||
LL | |
|
||||
LL | | where
|
||||
LL | | T: Unsize<U>,
|
||||
| |_____________________^
|
||||
|
@ -47,4 +56,5 @@ LL | | T: Unsize<U>,
|
|||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0378`.
|
||||
Some errors have detailed explanations: E0374, E0375, E0378.
|
||||
For more information about an error, try `rustc --explain E0374`.
|
||||
|
|
|
@ -15,7 +15,7 @@ struct Dispatchable<T: ?Sized, Z> {
|
|||
}
|
||||
|
||||
impl<T, U> DispatchFromDyn<Dispatchable<U, i32>> for Dispatchable<T, ()>
|
||||
//~^ ERROR implementing the `DispatchFromDyn` trait requires multiple coercions
|
||||
//~^ ERROR implementing `DispatchFromDyn` does not allow multiple fields to be coerced
|
||||
where
|
||||
T: Unsize<U> + ?Sized,
|
||||
U: ?Sized,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0378]: implementing the `DispatchFromDyn` trait requires multiple coercions
|
||||
error[E0375]: implementing `DispatchFromDyn` does not allow multiple fields to be coerced
|
||||
--> $DIR/dispatch-from-dyn-zst-transmute-zst-nonzst.rs:17:1
|
||||
|
|
||||
LL | / impl<T, U> DispatchFromDyn<Dispatchable<U, i32>> for Dispatchable<T, ()>
|
||||
|
@ -8,9 +8,14 @@ LL | | T: Unsize<U> + ?Sized,
|
|||
LL | | U: ?Sized,
|
||||
| |______________^
|
||||
|
|
||||
= note: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced
|
||||
= note: currently, 2 fields need coercions: `_ptr` (`Box<T>` to `Box<U>`), `z` (`()` to `i32`)
|
||||
note: the trait `DispatchFromDyn` may only be implemented when a single field is being coerced
|
||||
--> $DIR/dispatch-from-dyn-zst-transmute-zst-nonzst.rs:13:5
|
||||
|
|
||||
LL | _ptr: Box<T>,
|
||||
| ^^^^^^^^^^^^
|
||||
LL | z: Z,
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0378`.
|
||||
For more information about this error, try `rustc --explain E0375`.
|
||||
|
|
|
@ -15,7 +15,7 @@ struct Foo<'a, U: ?Sized> {
|
|||
}
|
||||
|
||||
impl<'a, T, U> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T>
|
||||
//~^ ERROR implementing the `DispatchFromDyn` trait requires multiple coercions
|
||||
//~^ ERROR implementing `DispatchFromDyn` does not allow multiple fields to be coerced
|
||||
where
|
||||
T: Unsize<U> + ?Sized,
|
||||
U: ?Sized {}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0378]: implementing the `DispatchFromDyn` trait requires multiple coercions
|
||||
error[E0375]: implementing `DispatchFromDyn` does not allow multiple fields to be coerced
|
||||
--> $DIR/dispatch-from-dyn-zst-transmute.rs:17:1
|
||||
|
|
||||
LL | / impl<'a, T, U> DispatchFromDyn<Foo<'a, U>> for Foo<'a, T>
|
||||
|
@ -8,9 +8,14 @@ LL | | T: Unsize<U> + ?Sized,
|
|||
LL | | U: ?Sized {}
|
||||
| |_____________^
|
||||
|
|
||||
= note: the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced
|
||||
= note: currently, 2 fields need coercions: `token` (`IsSendToken<T>` to `IsSendToken<U>`), `ptr` (`&'a T` to `&'a U`)
|
||||
note: the trait `DispatchFromDyn` may only be implemented when a single field is being coerced
|
||||
--> $DIR/dispatch-from-dyn-zst-transmute.rs:13:5
|
||||
|
|
||||
LL | token: IsSendToken<U>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
LL | ptr: &'a U,
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0378`.
|
||||
For more information about this error, try `rustc --explain E0375`.
|
||||
|
|
|
@ -65,7 +65,7 @@ LL | fn foo(self: Smaht<Self, T>);
|
|||
= note: type of `self` must be `Self` or a type that dereferences to it
|
||||
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
|
||||
|
||||
error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
|
||||
error[E0377]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
|
||||
--> $DIR/issue-78372.rs:3:1
|
||||
|
|
||||
LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
|
||||
|
@ -73,5 +73,5 @@ LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
|
|||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0307, E0378, E0412, E0658.
|
||||
Some errors have detailed explanations: E0307, E0377, E0412, E0658.
|
||||
For more information about an error, try `rustc --explain E0307`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue