Skip to content

Commit

Permalink
fix(manifest): Provide unused key warnings for lints table
Browse files Browse the repository at this point in the history
The use of `flatten` was getting in the way of `serde_ignored`.
A common workaround is to add our own `unused` tracking but that would
cause duplicates with `workspace.lints` (or we'd just ignore it).

Since the manual deserializer was relatively simple, I went that route.

Fixes rust-lang#12917
  • Loading branch information
epage committed Jan 8, 2024
1 parent 51dedd6 commit 309abcc
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 13 deletions.
62 changes: 49 additions & 13 deletions crates/cargo-util-schemas/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -437,15 +437,6 @@ impl Default for TomlInheritedField {
}
}

fn bool_no_false<'de, D: de::Deserializer<'de>>(deserializer: D) -> Result<bool, D::Error> {
let b: bool = Deserialize::deserialize(deserializer)?;
if b {
Ok(b)
} else {
Err(de::Error::custom("`workspace` cannot be false"))
}
}

#[derive(Deserialize, Serialize, Copy, Clone, Debug)]
#[serde(try_from = "bool")]
#[serde(into = "bool")]
Expand Down Expand Up @@ -1269,12 +1260,9 @@ impl TomlPlatform {
}
}

#[derive(Deserialize, Serialize, Debug, Clone)]
#[serde(expecting = "a lints table")]
#[serde(rename_all = "kebab-case")]
#[derive(Serialize, Debug, Clone)]
pub struct InheritableLints {
#[serde(skip_serializing_if = "is_false")]
#[serde(deserialize_with = "bool_no_false", default)]
pub workspace: bool,
#[serde(flatten)]
pub lints: TomlLints,
Expand All @@ -1284,6 +1272,54 @@ fn is_false(b: &bool) -> bool {
!b
}

impl<'de> Deserialize<'de> for InheritableLints {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct InheritableLintsVisitor;

impl<'de> de::Visitor<'de> for InheritableLintsVisitor {
// The type that our Visitor is going to produce.
type Value = InheritableLints;

// Format a message stating what data this Visitor expects to receive.
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a lints table")
}

// Deserialize MyMap from an abstract "map" provided by the
// Deserializer. The MapAccess input is a callback provided by
// the Deserializer to let us see each entry in the map.
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
where
M: de::MapAccess<'de>,
{
let mut lints = TomlLints::new();
let mut workspace = false;

// While there are entries remaining in the input, add them
// into our map.
while let Some(key) = access.next_key()? {
if key == "workspace" {
workspace = match access.next_value()? {
Some(WorkspaceValue) => true,
None => false,
};
} else {
let value = access.next_value()?;
lints.insert(key, value);
}
}

Ok(InheritableLints { workspace, lints })
}
}

deserializer.deserialize_map(InheritableLintsVisitor)
}
}

pub type TomlLints = BTreeMap<String, TomlToolLints>;

pub type TomlToolLints = BTreeMap<String, TomlLint>;
Expand Down
1 change: 1 addition & 0 deletions tests/testsuite/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ fn warn_on_unused_key() {
foo.cargo("check")
.with_stderr(
"\
[WARNING] [CWD]/Cargo.toml: unused manifest key: lints.rust.rust-2018-idioms.unused
[WARNING] [CWD]/Cargo.toml: unused manifest key: workspace.lints.rust.rust-2018-idioms.unused
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]s
Expand Down

0 comments on commit 309abcc

Please sign in to comment.