diff options
| author | llogiq <bogusandre@gmail.com> | 2025-05-13 15:36:57 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-13 15:36:57 +0000 |
| commit | 17f2a87c0cdade23b20ea5b3004235d8c1db8eb5 (patch) | |
| tree | ad52c802a48b6707b92d83b5085989d73119fd97 /tests | |
| parent | 7bac114c8645d40291502c0d8028ffd16c7e8c01 (diff) | |
| parent | 9f4ecea24269f6a6c7cd54b4648a1ccd23a58d90 (diff) | |
| download | rust-17f2a87c0cdade23b20ea5b3004235d8c1db8eb5.tar.gz rust-17f2a87c0cdade23b20ea5b3004235d8c1db8eb5.zip | |
Add internal lint `derive_deserialize_allowing_unknown` (#14360)
Adds an internal lint to check for `#[derive(serde::Deserialize)]`
without
[`#[serde(deny_unknown_fields)]`](https://serde.rs/container-attrs.html#deny_unknown_fields).
Today, if you run Clippy with the following clippy.toml, Clippy will
produce a warning, but there will be no accompanying note:
```toml
# In the following configuration, "recommendation" should be "reason" or "replacement".
disallowed-macros = [
{ path = "std::panic", recommendation = "return a `std::result::Result::Error` instead" },
]
```
```sh
$ cargo clippy
Checking a v0.1.0 (/home/smoelius/tmp/a)
warning: use of a disallowed macro `std::panic`
--> src/lib.rs:2:5
|
2 | panic!();
| ^^^^^^^^
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros
= note: `#[warn(clippy::disallowed_macros)]` on by default
```
The underlying problem is: the enum that derives `serde::Deserialize`
([`DisallowedPathEnum`](https://github.com/rust-lang/rust-clippy/blob/81643e297cf44ce3c7648b8443fc4d6592fa81eb/clippy_config/src/types.rs#L47))
does not have the attribute `#[serde(deny_unknown_fields)]`.
This lint identifies such problems by checking trait `impl`s. An
alternative I considered was to walk `clippy_config::conf::Conf`
directly. However, that would not catch the `DisallowedPathEnum` case
because it [is not used in `Conf`
directly](https://github.com/rust-lang/rust-clippy/blob/81643e297cf44ce3c7648b8443fc4d6592fa81eb/clippy_config/src/types.rs#L31).
Just to be clear, no one asked for this. So I hope the maintainers do
not mind.
changelog: none
Diffstat (limited to 'tests')
5 files changed, 100 insertions, 0 deletions
diff --git a/tests/ui-internal/derive_deserialize_allowing_unknown.rs b/tests/ui-internal/derive_deserialize_allowing_unknown.rs new file mode 100644 index 00000000000..9dc8e9e8f4c --- /dev/null +++ b/tests/ui-internal/derive_deserialize_allowing_unknown.rs @@ -0,0 +1,60 @@ +#![deny(clippy::derive_deserialize_allowing_unknown)] + +use serde::{Deserialize, Deserializer}; + +#[derive(Deserialize)] //~ derive_deserialize_allowing_unknown +struct Struct { + flag: bool, + limit: u64, +} + +#[derive(Deserialize)] //~ derive_deserialize_allowing_unknown +enum Enum { + A(bool), + B { limit: u64 }, +} + +// negative tests + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct StructWithDenyUnknownFields { + flag: bool, + limit: u64, +} + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +enum EnumWithDenyUnknownFields { + A(bool), + B { limit: u64 }, +} + +#[derive(Deserialize)] +#[serde(untagged, deny_unknown_fields)] +enum MultipleSerdeAttributes { + A(bool), + B { limit: u64 }, +} + +#[derive(Deserialize)] +struct TupleStruct(u64, bool); + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +enum EnumWithOnlyTupleVariants { + A(bool), + B(u64), +} + +struct ManualSerdeImplementation; + +impl<'de> Deserialize<'de> for ManualSerdeImplementation { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + let () = <() as Deserialize>::deserialize(deserializer)?; + Ok(ManualSerdeImplementation) + } +} diff --git a/tests/ui-internal/derive_deserialize_allowing_unknown.stderr b/tests/ui-internal/derive_deserialize_allowing_unknown.stderr new file mode 100644 index 00000000000..93d64826c99 --- /dev/null +++ b/tests/ui-internal/derive_deserialize_allowing_unknown.stderr @@ -0,0 +1,23 @@ +error: `#[derive(serde::Deserialize)]` without `#[serde(deny_unknown_fields)]` + --> tests/ui-internal/derive_deserialize_allowing_unknown.rs:5:10 + | +LL | #[derive(Deserialize)] + | ^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui-internal/derive_deserialize_allowing_unknown.rs:1:9 + | +LL | #![deny(clippy::derive_deserialize_allowing_unknown)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: `#[derive(serde::Deserialize)]` without `#[serde(deny_unknown_fields)]` + --> tests/ui-internal/derive_deserialize_allowing_unknown.rs:11:10 + | +LL | #[derive(Deserialize)] + | ^^^^^^^^^^^ + | + = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors + diff --git a/tests/ui-toml/toml_unknown_config_struct_field/clippy.toml b/tests/ui-toml/toml_unknown_config_struct_field/clippy.toml new file mode 100644 index 00000000000..82560cfd5e2 --- /dev/null +++ b/tests/ui-toml/toml_unknown_config_struct_field/clippy.toml @@ -0,0 +1,4 @@ +# In the following configuration, "recommendation" should be "reason" or "replacement". +disallowed-macros = [ + { path = "std::panic", recommendation = "return a `std::result::Result::Error` instead" }, +] diff --git a/tests/ui-toml/toml_unknown_config_struct_field/toml_unknown_config_struct_field.rs b/tests/ui-toml/toml_unknown_config_struct_field/toml_unknown_config_struct_field.rs new file mode 100644 index 00000000000..9c770c31f6f --- /dev/null +++ b/tests/ui-toml/toml_unknown_config_struct_field/toml_unknown_config_struct_field.rs @@ -0,0 +1,5 @@ +#[rustfmt::skip] +//@error-in-other-file: error reading Clippy's configuration file: data did not match any variant of untagged enum DisallowedPathEnum +fn main() { + panic!(); +} diff --git a/tests/ui-toml/toml_unknown_config_struct_field/toml_unknown_config_struct_field.stderr b/tests/ui-toml/toml_unknown_config_struct_field/toml_unknown_config_struct_field.stderr new file mode 100644 index 00000000000..b564709721d --- /dev/null +++ b/tests/ui-toml/toml_unknown_config_struct_field/toml_unknown_config_struct_field.stderr @@ -0,0 +1,8 @@ +error: error reading Clippy's configuration file: data did not match any variant of untagged enum DisallowedPathEnum + --> $DIR/tests/ui-toml/toml_unknown_config_struct_field/clippy.toml:3:5 + | +LL | { path = "std::panic", recommendation = "return a `std::result::Result::Error` instead" }, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + |
