Auto merge of #83908 - Flying-Toast:master, r=davidtwco
Add enum_intrinsics_non_enums lint There is a clippy lint to prevent calling [`mem::discriminant`](https://doc.rust-lang.org/std/mem/fn.discriminant.html) with a non-enum type. I think the lint is worthy of being included in rustc, given that `discriminant::<T>()` where `T` is a non-enum has an unspecified return value, and there are no valid use cases where you'd actually want this. I've also made the lint check [variant_count](https://doc.rust-lang.org/core/mem/fn.variant_count.html) (#73662). closes #83899
This commit is contained in:
commit
5b210643eb
22 changed files with 292 additions and 315 deletions
|
|
@ -1,5 +1,5 @@
|
|||
// run-pass
|
||||
#![allow(dead_code)]
|
||||
#![allow(dead_code, enum_intrinsics_non_enums)]
|
||||
#![feature(variant_count)]
|
||||
#![feature(never_type)]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
// run-pass
|
||||
|
||||
#![allow(enum_intrinsics_non_enums)]
|
||||
|
||||
use std::mem;
|
||||
|
||||
enum ADT {
|
||||
|
|
|
|||
67
src/test/ui/lint/lint-enum-intrinsics-non-enums.rs
Normal file
67
src/test/ui/lint/lint-enum-intrinsics-non-enums.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
// Test the enum_intrinsics_non_enums lint.
|
||||
|
||||
#![feature(variant_count)]
|
||||
|
||||
use std::mem::{discriminant, variant_count};
|
||||
|
||||
enum SomeEnum {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
|
||||
struct SomeStruct;
|
||||
|
||||
fn generic_discriminant<T>(v: &T) {
|
||||
discriminant::<T>(v);
|
||||
}
|
||||
|
||||
fn generic_variant_count<T>() -> usize {
|
||||
variant_count::<T>()
|
||||
}
|
||||
|
||||
fn test_discriminant() {
|
||||
discriminant(&SomeEnum::A);
|
||||
generic_discriminant(&SomeEnum::B);
|
||||
|
||||
discriminant(&());
|
||||
//~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
|
||||
discriminant(&&SomeEnum::B);
|
||||
//~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
|
||||
discriminant(&SomeStruct);
|
||||
//~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
|
||||
discriminant(&123u32);
|
||||
//~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
|
||||
discriminant(&&123i8);
|
||||
//~^ error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
}
|
||||
|
||||
fn test_variant_count() {
|
||||
variant_count::<SomeEnum>();
|
||||
generic_variant_count::<SomeEnum>();
|
||||
|
||||
variant_count::<&str>();
|
||||
//~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type
|
||||
|
||||
variant_count::<*const u8>();
|
||||
//~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type
|
||||
|
||||
variant_count::<()>();
|
||||
//~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type
|
||||
|
||||
variant_count::<&SomeEnum>();
|
||||
//~^ error: the return value of `mem::variant_count` is unspecified when called with a non-enum type
|
||||
}
|
||||
|
||||
fn main() {
|
||||
test_discriminant();
|
||||
test_variant_count();
|
||||
|
||||
// The lint ignores cases where the type is generic, so these should be
|
||||
// allowed even though their return values are unspecified
|
||||
generic_variant_count::<SomeStruct>();
|
||||
generic_discriminant::<SomeStruct>(&SomeStruct);
|
||||
}
|
||||
95
src/test/ui/lint/lint-enum-intrinsics-non-enums.stderr
Normal file
95
src/test/ui/lint/lint-enum-intrinsics-non-enums.stderr
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-enum-intrinsics-non-enums.rs:26:5
|
||||
|
|
||||
LL | discriminant(&());
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `#[deny(enum_intrinsics_non_enums)]` on by default
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `()`, which is not an enum.
|
||||
--> $DIR/lint-enum-intrinsics-non-enums.rs:26:18
|
||||
|
|
||||
LL | discriminant(&());
|
||||
| ^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-enum-intrinsics-non-enums.rs:29:5
|
||||
|
|
||||
LL | discriminant(&&SomeEnum::B);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `&SomeEnum`, which is not an enum.
|
||||
--> $DIR/lint-enum-intrinsics-non-enums.rs:29:18
|
||||
|
|
||||
LL | discriminant(&&SomeEnum::B);
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-enum-intrinsics-non-enums.rs:32:5
|
||||
|
|
||||
LL | discriminant(&SomeStruct);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `SomeStruct`, which is not an enum.
|
||||
--> $DIR/lint-enum-intrinsics-non-enums.rs:32:18
|
||||
|
|
||||
LL | discriminant(&SomeStruct);
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-enum-intrinsics-non-enums.rs:35:5
|
||||
|
|
||||
LL | discriminant(&123u32);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `u32`, which is not an enum.
|
||||
--> $DIR/lint-enum-intrinsics-non-enums.rs:35:18
|
||||
|
|
||||
LL | discriminant(&123u32);
|
||||
| ^^^^^^^
|
||||
|
||||
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-enum-intrinsics-non-enums.rs:38:5
|
||||
|
|
||||
LL | discriminant(&&123i8);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `&i8`, which is not an enum.
|
||||
--> $DIR/lint-enum-intrinsics-non-enums.rs:38:18
|
||||
|
|
||||
LL | discriminant(&&123i8);
|
||||
| ^^^^^^^
|
||||
|
||||
error: the return value of `mem::variant_count` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-enum-intrinsics-non-enums.rs:46:5
|
||||
|
|
||||
LL | variant_count::<&str>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `&str`, which is not an enum.
|
||||
|
||||
error: the return value of `mem::variant_count` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-enum-intrinsics-non-enums.rs:49:5
|
||||
|
|
||||
LL | variant_count::<*const u8>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `*const u8`, which is not an enum.
|
||||
|
||||
error: the return value of `mem::variant_count` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-enum-intrinsics-non-enums.rs:52:5
|
||||
|
|
||||
LL | variant_count::<()>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `()`, which is not an enum.
|
||||
|
||||
error: the return value of `mem::variant_count` is unspecified when called with a non-enum type
|
||||
--> $DIR/lint-enum-intrinsics-non-enums.rs:55:5
|
||||
|
|
||||
LL | variant_count::<&SomeEnum>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the type parameter of `variant_count` should be an enum, but it was instantiated with the type `&SomeEnum`, which is not an enum.
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue