diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 12529102a637..4b9585cb614d 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -1171,195 +1171,84 @@ type MaybeWorkspaceSemverVersion = MaybeWorkspace; impl<'de> de::Deserialize<'de> for MaybeWorkspaceString { - fn deserialize(d: D) -> Result + fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de>, { - struct Visitor; - - impl<'de> de::Visitor<'de> for Visitor { - type Value = MaybeWorkspaceString; - - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - f.write_str("a string or workspace") - } - - fn visit_string(self, value: String) -> Result - where - E: de::Error, - { - Ok(MaybeWorkspaceString::Defined(value)) - } - - fn visit_map(self, map: V) -> Result - where - V: de::MapAccess<'de>, - { - let mvd = de::value::MapAccessDeserializer::new(map); - TomlWorkspaceField::deserialize(mvd).map(MaybeWorkspace::Workspace) - } - } - - d.deserialize_any(Visitor) + UntaggedEnumVisitor::new() + .expecting("a string or workspace") + .string(|value| Ok(MaybeWorkspace::Defined(value.to_owned()))) + .map(|value| value.deserialize().map(MaybeWorkspace::Workspace)) + .deserialize(deserializer) } } type MaybeWorkspacePartialVersion = MaybeWorkspace; impl<'de> de::Deserialize<'de> for MaybeWorkspacePartialVersion { - fn deserialize(d: D) -> Result + fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de>, { - struct Visitor; - - impl<'de> de::Visitor<'de> for Visitor { - type Value = MaybeWorkspacePartialVersion; - - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - f.write_str("a semver or workspace") - } - - fn visit_string(self, value: String) -> Result - where - E: de::Error, - { - let value = value.parse::().map_err(|e| E::custom(e))?; - Ok(MaybeWorkspacePartialVersion::Defined(value)) - } - - fn visit_map(self, map: V) -> Result - where - V: de::MapAccess<'de>, - { - let mvd = de::value::MapAccessDeserializer::new(map); - TomlWorkspaceField::deserialize(mvd).map(MaybeWorkspace::Workspace) - } - } - - d.deserialize_any(Visitor) + use serde::de::Error as _; + UntaggedEnumVisitor::new() + .expecting("a SemVer version or workspace") + .string(|value| { + let value = value + .parse::() + .map_err(|e| serde_untagged::de::Error::custom(e))?; + Ok(MaybeWorkspace::Defined(value)) + }) + .map(|value| value.deserialize().map(MaybeWorkspace::Workspace)) + .deserialize(deserializer) } } type MaybeWorkspaceVecString = MaybeWorkspace, TomlWorkspaceField>; impl<'de> de::Deserialize<'de> for MaybeWorkspaceVecString { - fn deserialize(d: D) -> Result + fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de>, { - struct Visitor; - - impl<'de> de::Visitor<'de> for Visitor { - type Value = MaybeWorkspaceVecString; - - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - f.write_str("a vector of strings or workspace") - } - fn visit_seq(self, v: A) -> Result - where - A: de::SeqAccess<'de>, - { - let seq = de::value::SeqAccessDeserializer::new(v); - Vec::deserialize(seq).map(MaybeWorkspace::Defined) - } - - fn visit_map(self, map: V) -> Result - where - V: de::MapAccess<'de>, - { - let mvd = de::value::MapAccessDeserializer::new(map); - TomlWorkspaceField::deserialize(mvd).map(MaybeWorkspace::Workspace) - } - } - - d.deserialize_any(Visitor) + UntaggedEnumVisitor::new() + .expecting("a vector of strings or workspace") + .seq(|value| value.deserialize().map(MaybeWorkspace::Defined)) + .map(|value| value.deserialize().map(MaybeWorkspace::Workspace)) + .deserialize(deserializer) } } type MaybeWorkspaceStringOrBool = MaybeWorkspace; impl<'de> de::Deserialize<'de> for MaybeWorkspaceStringOrBool { - fn deserialize(d: D) -> Result + fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de>, { - struct Visitor; - - impl<'de> de::Visitor<'de> for Visitor { - type Value = MaybeWorkspaceStringOrBool; - - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - f.write_str("a string, a bool, or workspace") - } - - fn visit_bool(self, v: bool) -> Result - where - E: de::Error, - { - let b = de::value::BoolDeserializer::new(v); - StringOrBool::deserialize(b).map(MaybeWorkspace::Defined) - } - - fn visit_string(self, v: String) -> Result - where - E: de::Error, - { - let string = de::value::StringDeserializer::new(v); - StringOrBool::deserialize(string).map(MaybeWorkspace::Defined) - } - - fn visit_map(self, map: V) -> Result - where - V: de::MapAccess<'de>, - { - let mvd = de::value::MapAccessDeserializer::new(map); - TomlWorkspaceField::deserialize(mvd).map(MaybeWorkspace::Workspace) - } - } - - d.deserialize_any(Visitor) + UntaggedEnumVisitor::new() + .expecting("a string, a bool, or workspace") + .bool(|b| Ok(StringOrBool::Bool(b)).map(MaybeWorkspace::Defined)) + .string(|s| Ok(StringOrBool::String(s.to_owned())).map(MaybeWorkspace::Defined)) + .map(|value| value.deserialize().map(MaybeWorkspace::Workspace)) + .deserialize(deserializer) } } type MaybeWorkspaceVecStringOrBool = MaybeWorkspace; impl<'de> de::Deserialize<'de> for MaybeWorkspaceVecStringOrBool { - fn deserialize(d: D) -> Result + fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de>, { - struct Visitor; - - impl<'de> de::Visitor<'de> for Visitor { - type Value = MaybeWorkspaceVecStringOrBool; - - fn expecting(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - f.write_str("a boolean, a vector of strings, or workspace") - } - - fn visit_bool(self, v: bool) -> Result - where - E: de::Error, - { - let b = de::value::BoolDeserializer::new(v); - VecStringOrBool::deserialize(b).map(MaybeWorkspace::Defined) - } - - fn visit_seq(self, v: A) -> Result - where - A: de::SeqAccess<'de>, - { - let seq = de::value::SeqAccessDeserializer::new(v); - VecStringOrBool::deserialize(seq).map(MaybeWorkspace::Defined) - } - - fn visit_map(self, map: V) -> Result - where - V: de::MapAccess<'de>, - { - let mvd = de::value::MapAccessDeserializer::new(map); - TomlWorkspaceField::deserialize(mvd).map(MaybeWorkspace::Workspace) - } - } - - d.deserialize_any(Visitor) + UntaggedEnumVisitor::new() + .expecting("a boolean, a vector of strings, or workspace") + .bool(|value| Ok(VecStringOrBool::Bool(value)).map(MaybeWorkspace::Defined)) + .seq(|value| { + value + .deserialize() + .map(VecStringOrBool::VecString) + .map(MaybeWorkspace::Defined) + }) + .map(|value| value.deserialize().map(MaybeWorkspace::Workspace)) + .deserialize(deserializer) } } diff --git a/tests/testsuite/inheritable_workspace_fields.rs b/tests/testsuite/inheritable_workspace_fields.rs index 47437102a596..6a200af3556f 100644 --- a/tests/testsuite/inheritable_workspace_fields.rs +++ b/tests/testsuite/inheritable_workspace_fields.rs @@ -1234,11 +1234,13 @@ fn error_workspace_false() { [ERROR] failed to parse manifest at `[CWD]/Cargo.toml` Caused by: - TOML parse error at line 7, column 41 + TOML parse error at line 7, column 27 | 7 | description = { workspace = false } - | ^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ `workspace` cannot be false + in `workspace` + ", ) .run();