rust-lang / rust-lang/rust-clippy

unsafe_derive_deserialize should ignore types that use #[serde(from)] or #[serde(try_from)]

Open
#9,304 0 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-bug I-false-positive
Dominant language
Rust
Stars
13.5k
Forks
2.2k
Avg merge
2d 10h
Merged PRs (30d)
32

Description

Summary

When deriving Deserialize for a type with #[serde(from)] or #[serde(try_from)], serde only generates wrapper code that invokes the safe interface of standard conversion traits. As such, there is no risk of it invalidating unsafe invariants, provided that the impls are correct.

Lint Name

unsafe_derive_deserialize

Reproducer

I tried this code:

#![deny(clippy::unsafe_derive_deserialize)]

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
#[serde(try_from = "bool")]
pub struct False;

#[derive(Debug)]
pub struct TrueError;

impl std::fmt::Display for TrueError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "bruh")
    }
}

impl TryFrom<bool> for False {
    type Error = TrueError;

    fn try_from(b: bool) -> Result<Self, TrueError> {
        if b {
            Err(TrueError)
        } else {
            Ok(False)
        }
    }
}

impl False {
    pub const unsafe fn new_unchecked(b: bool) -> Self {
        False
    }
}

I saw this happen:

error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe`
 --> src/lib.rs:5:21
  |
5 | #[derive(Serialize, Deserialize)]
  |                     ^^^^^^^^^^^
  |
note: the lint level is defined here
 --> src/lib.rs:1:9
  |
1 | #![deny(clippy::unsafe_derive_deserialize)]
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  = help: consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_derive_deserialize
  = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)

I expected to see this happen:

Code compiles.

Version
rustc 1.62.1 (e092d0b6b 2022-07-16)
binary: rustc
commit-hash: e092d0b6b43f2de967af0887873151bb1c0b18d3
commit-date: 2022-07-16
host: x86_64-unknown-linux-gnu
release: 1.62.1
LLVM version: 14.0.5
Additional Labels

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the implementation and tests for the unsafe_derive_deserialize lint, then inspect how serde(from) and serde(try_from) attributes are handled. Add regression coverage for both conversion attributes and verify that valid derives no longer produce the lint diagnostic.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
devtools
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.