Emit more specific diagnostics when enums fail to cast with as
This commit is contained in:
parent
384b02c082
commit
6e37f955e5
@ -448,13 +448,35 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx>, e: CastError) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let msg = "an `as` expression can only be used to convert between primitive \
|
|
||||||
types or to coerce to a specific trait object";
|
let (msg, note) = if let ty::Adt(adt, _) = self.expr_ty.kind()
|
||||||
|
&& adt.is_enum()
|
||||||
|
&& self.cast_ty.is_numeric()
|
||||||
|
{
|
||||||
|
(
|
||||||
|
"an `as` expression can be used to convert enum types to numeric \
|
||||||
|
types only if the enum type is unit-only or field-less",
|
||||||
|
Some(
|
||||||
|
"see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
"an `as` expression can only be used to convert between primitive \
|
||||||
|
types or to coerce to a specific trait object",
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
if label {
|
if label {
|
||||||
err.span_label(self.span, msg);
|
err.span_label(self.span, msg);
|
||||||
} else {
|
} else {
|
||||||
err.note(msg);
|
err.note(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(note) = note {
|
||||||
|
err.note(note);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err.span_label(self.span, "invalid cast");
|
err.span_label(self.span, "invalid cast");
|
||||||
}
|
}
|
||||||
|
46
tests/ui/cast/enum-to-numeric-cast.rs
Normal file
46
tests/ui/cast/enum-to-numeric-cast.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Tests that `as` casts from enums to numeric types succeed
|
||||||
|
// only if the enum type is "unit-only" or "fieldless" as
|
||||||
|
// described here: https://doc.rust-lang.org/reference/items/enumerations.html#casting
|
||||||
|
|
||||||
|
pub enum UnitOnly {
|
||||||
|
Foo,
|
||||||
|
Bar,
|
||||||
|
Baz,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Fieldless {
|
||||||
|
Tuple(),
|
||||||
|
Struct{},
|
||||||
|
Unit,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum NotUnitOnlyOrFieldless {
|
||||||
|
Foo,
|
||||||
|
Bar(u8),
|
||||||
|
Baz
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let unit_only = UnitOnly::Foo;
|
||||||
|
|
||||||
|
let _ = unit_only as isize;
|
||||||
|
let _ = unit_only as i32;
|
||||||
|
let _ = unit_only as usize;
|
||||||
|
let _ = unit_only as u32;
|
||||||
|
|
||||||
|
|
||||||
|
let fieldless = Fieldless::Struct{};
|
||||||
|
|
||||||
|
let _ = fieldless as isize;
|
||||||
|
let _ = fieldless as i32;
|
||||||
|
let _ = fieldless as usize;
|
||||||
|
let _ = fieldless as u32;
|
||||||
|
|
||||||
|
|
||||||
|
let not_unit_only_or_fieldless = NotUnitOnlyOrFieldless::Foo;
|
||||||
|
|
||||||
|
let _ = not_unit_only_or_fieldless as isize; //~ ERROR non-primitive cast: `NotUnitOnlyOrFieldless` as `isize`
|
||||||
|
let _ = not_unit_only_or_fieldless as i32; //~ ERROR non-primitive cast: `NotUnitOnlyOrFieldless` as `i32`
|
||||||
|
let _ = not_unit_only_or_fieldless as usize; //~ ERROR non-primitive cast: `NotUnitOnlyOrFieldless` as `usize`
|
||||||
|
let _ = not_unit_only_or_fieldless as u32; //~ ERROR non-primitive cast: `NotUnitOnlyOrFieldless` as `u32`
|
||||||
|
}
|
35
tests/ui/cast/enum-to-numeric-cast.stderr
Normal file
35
tests/ui/cast/enum-to-numeric-cast.stderr
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
error[E0605]: non-primitive cast: `NotUnitOnlyOrFieldless` as `isize`
|
||||||
|
--> $DIR/enum-to-numeric-cast.rs:42:13
|
||||||
|
|
|
||||||
|
LL | let _ = not_unit_only_or_fieldless as isize;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less
|
||||||
|
|
|
||||||
|
= note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information
|
||||||
|
|
||||||
|
error[E0605]: non-primitive cast: `NotUnitOnlyOrFieldless` as `i32`
|
||||||
|
--> $DIR/enum-to-numeric-cast.rs:43:13
|
||||||
|
|
|
||||||
|
LL | let _ = not_unit_only_or_fieldless as i32;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less
|
||||||
|
|
|
||||||
|
= note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information
|
||||||
|
|
||||||
|
error[E0605]: non-primitive cast: `NotUnitOnlyOrFieldless` as `usize`
|
||||||
|
--> $DIR/enum-to-numeric-cast.rs:44:13
|
||||||
|
|
|
||||||
|
LL | let _ = not_unit_only_or_fieldless as usize;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less
|
||||||
|
|
|
||||||
|
= note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information
|
||||||
|
|
||||||
|
error[E0605]: non-primitive cast: `NotUnitOnlyOrFieldless` as `u32`
|
||||||
|
--> $DIR/enum-to-numeric-cast.rs:45:13
|
||||||
|
|
|
||||||
|
LL | let _ = not_unit_only_or_fieldless as u32;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less
|
||||||
|
|
|
||||||
|
= note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0605`.
|
@ -2,7 +2,9 @@ error[E0605]: non-primitive cast: `Kind2` as `u8`
|
|||||||
--> $DIR/issue-88621.rs:9:13
|
--> $DIR/issue-88621.rs:9:13
|
||||||
|
|
|
|
||||||
LL | let _ = Kind2::Foo() as u8;
|
LL | let _ = Kind2::Foo() as u8;
|
||||||
| ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
| ^^^^^^^^^^^^^^^^^^ an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less
|
||||||
|
|
|
||||||
|
= note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
@ -4,7 +4,8 @@ error[E0605]: non-primitive cast: `NonNullary` as `isize`
|
|||||||
LL | let val = v as isize;
|
LL | let val = v as isize;
|
||||||
| ^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(v)`
|
| ^^^^^^^^^^ help: consider using the `From` trait instead: `isize::from(v)`
|
||||||
|
|
|
|
||||||
= note: an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
|
= note: an `as` expression can be used to convert enum types to numeric types only if the enum type is unit-only or field-less
|
||||||
|
= note: see https://doc.rust-lang.org/reference/items/enumerations.html#casting for more information
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user