mirror of
https://github.com/rust-lang/rust.git
synced 2025-11-17 05:36:23 +00:00
Avoid using () in derive(From) output.
Using an error type instead of `()` avoids the duplicated errors
on `struct SUnsizedField` in `deriving-from-wrong-target.rs`. It also
improves the expanded output from this:
```
struct S2(u32, u32);
impl ::core::convert::From<()> for S2 {
#[inline]
fn from(value: ()) -> S2 { (/*ERROR*/) }
}
```
to this:
```
struct S2(u32, u32);
impl ::core::convert::From<(/*ERROR*/)> for S2 {
#[inline]
fn from(value: (/*ERROR*/)) -> S2 { (/*ERROR*/) }
}
```
The new code also only matchs on `item.kind` once.
This commit is contained in:
parent
8365fcb2b8
commit
ebfac4ecaf
@ -27,21 +27,39 @@ pub(crate) fn expand_deriving_from(
|
||||
cx.dcx().bug("derive(From) used on something else than an item");
|
||||
};
|
||||
|
||||
// #[derive(From)] is currently usable only on structs with exactly one field.
|
||||
let field = if let ItemKind::Struct(_, _, data) = &item.kind
|
||||
&& let [field] = data.fields()
|
||||
{
|
||||
Some(field.clone())
|
||||
} else {
|
||||
None
|
||||
let err_span = || {
|
||||
let item_span = item.kind.ident().map(|ident| ident.span).unwrap_or(item.span);
|
||||
MultiSpan::from_spans(vec![span, item_span])
|
||||
};
|
||||
|
||||
let from_type = match &field {
|
||||
Some(field) => Ty::AstTy(field.ty.clone()),
|
||||
// We don't have a type to put into From<...> if we don't have a single field, so just put
|
||||
// unit there.
|
||||
None => Ty::Unit,
|
||||
// `#[derive(From)]` is currently usable only on structs with exactly one field.
|
||||
let field = match &item.kind {
|
||||
ItemKind::Struct(_, _, data) => {
|
||||
if let [field] = data.fields() {
|
||||
Ok(field.clone())
|
||||
} else {
|
||||
let guar = cx.dcx().emit_err(errors::DeriveFromWrongFieldCount {
|
||||
span: err_span(),
|
||||
multiple_fields: data.fields().len() > 1,
|
||||
});
|
||||
Err(guar)
|
||||
}
|
||||
}
|
||||
ItemKind::Enum(_, _, _) | ItemKind::Union(_, _, _) => {
|
||||
let guar = cx.dcx().emit_err(errors::DeriveFromWrongTarget {
|
||||
span: err_span(),
|
||||
kind: &format!("{} {}", item.kind.article(), item.kind.descr()),
|
||||
});
|
||||
Err(guar)
|
||||
}
|
||||
_ => cx.dcx().bug("Invalid derive(From) ADT input"),
|
||||
};
|
||||
|
||||
let from_type = Ty::AstTy(match field {
|
||||
Ok(ref field) => field.ty.clone(),
|
||||
Err(guar) => cx.ty(span, ast::TyKind::Err(guar)),
|
||||
});
|
||||
|
||||
let path =
|
||||
Path::new_(pathvec_std!(convert::From), vec![Box::new(from_type.clone())], PathKind::Std);
|
||||
|
||||
@ -71,34 +89,17 @@ pub(crate) fn expand_deriving_from(
|
||||
attributes: thin_vec![cx.attr_word(sym::inline, span)],
|
||||
fieldless_variants_strategy: FieldlessVariantsStrategy::Default,
|
||||
combine_substructure: combine_substructure(Box::new(|cx, span, substructure| {
|
||||
let Some(field) = &field else {
|
||||
let item_span = item.kind.ident().map(|ident| ident.span).unwrap_or(item.span);
|
||||
let err_span = MultiSpan::from_spans(vec![span, item_span]);
|
||||
let error = match &item.kind {
|
||||
ItemKind::Struct(_, _, data) => {
|
||||
cx.dcx().emit_err(errors::DeriveFromWrongFieldCount {
|
||||
span: err_span,
|
||||
multiple_fields: data.fields().len() > 1,
|
||||
})
|
||||
}
|
||||
ItemKind::Enum(_, _, _) | ItemKind::Union(_, _, _) => {
|
||||
cx.dcx().emit_err(errors::DeriveFromWrongTarget {
|
||||
span: err_span,
|
||||
kind: &format!("{} {}", item.kind.article(), item.kind.descr()),
|
||||
})
|
||||
}
|
||||
_ => cx.dcx().bug("Invalid derive(From) ADT input"),
|
||||
};
|
||||
|
||||
return BlockOrExpr::new_expr(DummyResult::raw_expr(span, Some(error)));
|
||||
let field = match field {
|
||||
Ok(ref field) => field,
|
||||
Err(guar) => {
|
||||
return BlockOrExpr::new_expr(DummyResult::raw_expr(span, Some(guar)));
|
||||
}
|
||||
};
|
||||
|
||||
let self_kw = Ident::new(kw::SelfUpper, span);
|
||||
let expr: Box<ast::Expr> = match substructure.fields {
|
||||
SubstructureFields::StaticStruct(variant, _) => match variant {
|
||||
// Self {
|
||||
// field: value
|
||||
// }
|
||||
// Self { field: value }
|
||||
VariantData::Struct { .. } => cx.expr_struct_ident(
|
||||
span,
|
||||
self_kw,
|
||||
|
||||
@ -29,8 +29,6 @@ struct S4 {
|
||||
enum E1 {}
|
||||
|
||||
#[derive(From)]
|
||||
//~^ ERROR the size for values of type `T` cannot be known at compilation time [E0277]
|
||||
//~| ERROR the size for values of type `T` cannot be known at compilation time [E0277]
|
||||
struct SUnsizedField<T: ?Sized> {
|
||||
last: T,
|
||||
//~^ ERROR the size for values of type `T` cannot be known at compilation time [E0277]
|
||||
|
||||
@ -54,45 +54,7 @@ LL | enum E1 {}
|
||||
= note: `#[derive(From)]` can only be used on structs with exactly one field
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/deriving-from-wrong-target.rs:31:10
|
||||
|
|
||||
LL | #[derive(From)]
|
||||
| ^^^^ doesn't have a size known at compile-time
|
||||
...
|
||||
LL | struct SUnsizedField<T: ?Sized> {
|
||||
| - this type parameter needs to be `Sized`
|
||||
|
|
||||
note: required by an implicit `Sized` bound in `From`
|
||||
--> $SRC_DIR/core/src/convert/mod.rs:LL:COL
|
||||
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
||||
|
|
||||
LL - struct SUnsizedField<T: ?Sized> {
|
||||
LL + struct SUnsizedField<T> {
|
||||
|
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/deriving-from-wrong-target.rs:31:10
|
||||
|
|
||||
LL | #[derive(From)]
|
||||
| ^^^^ doesn't have a size known at compile-time
|
||||
...
|
||||
LL | struct SUnsizedField<T: ?Sized> {
|
||||
| - this type parameter needs to be `Sized`
|
||||
|
|
||||
note: required because it appears within the type `SUnsizedField<T>`
|
||||
--> $DIR/deriving-from-wrong-target.rs:34:8
|
||||
|
|
||||
LL | struct SUnsizedField<T: ?Sized> {
|
||||
| ^^^^^^^^^^^^^
|
||||
= note: the return type of a function must have a statically known size
|
||||
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
||||
|
|
||||
LL - struct SUnsizedField<T: ?Sized> {
|
||||
LL + struct SUnsizedField<T> {
|
||||
|
|
||||
|
||||
error[E0277]: the size for values of type `T` cannot be known at compilation time
|
||||
--> $DIR/deriving-from-wrong-target.rs:35:11
|
||||
--> $DIR/deriving-from-wrong-target.rs:33:11
|
||||
|
|
||||
LL | struct SUnsizedField<T: ?Sized> {
|
||||
| - this type parameter needs to be `Sized`
|
||||
@ -110,6 +72,6 @@ help: function arguments must have a statically known size, borrowed types alway
|
||||
LL | last: &T,
|
||||
| +
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user