commit 9f62f8440e9e542f27d60c75be38ac51186c6c32
Author: Eric Huss <eric@huss.org>
Date:   Fri Dec 9 20:03:27 2022 -0800

    Add support for deserializing Vec<Value<String>> in config.
    
    This adds the ability to track the definition location of a string
    in a TOML array.

diff --git a/src/cargo/util/config/de.rs b/src/cargo/util/config/de.rs
index 6fddc7e71f..1408f15b57 100644
--- a/src/cargo/util/config/de.rs
+++ b/src/cargo/util/config/de.rs
@@ -384,7 +384,12 @@ impl<'de> de::SeqAccess<'de> for ConfigSeqAccess {
     {
         match self.list_iter.next() {
             // TODO: add `def` to error?
-            Some((value, _def)) => seed.deserialize(value.into_deserializer()).map(Some),
+            Some((value, def)) => {
+                // This might be a String or a Value<String>.
+                // ValueDeserializer will handle figuring out which one it is.
+                let maybe_value_de = ValueDeserializer::new_with_string(value, def);
+                seed.deserialize(maybe_value_de).map(Some)
+            }
             None => Ok(None),
         }
     }
@@ -400,7 +405,17 @@ impl<'de> de::SeqAccess<'de> for ConfigSeqAccess {
 struct ValueDeserializer<'config> {
     hits: u32,
     definition: Definition,
-    de: Deserializer<'config>,
+    /// The deserializer, used to actually deserialize a Value struct.
+    /// This is `None` if deserializing a string.
+    de: Option<Deserializer<'config>>,
+    /// A string value to deserialize.
+    ///
+    /// This is used for situations where you can't address a string via a
+    /// TOML key, such as a string inside an array. The `ConfigSeqAccess`
+    /// doesn't know if the type it should deserialize to is a `String` or
+    /// `Value<String>`, so `ValueDeserializer` needs to be able to handle
+    /// both.
+    str_value: Option<String>,
 }
 
 impl<'config> ValueDeserializer<'config> {
@@ -428,9 +443,19 @@ impl<'config> ValueDeserializer<'config> {
         Ok(ValueDeserializer {
             hits: 0,
             definition,
-            de,
+            de: Some(de),
+            str_value: None,
         })
     }
+
+    fn new_with_string(s: String, definition: Definition) -> ValueDeserializer<'config> {
+        ValueDeserializer {
+            hits: 0,
+            definition,
+            de: None,
+            str_value: Some(s),
+        }
+    }
 }
 
 impl<'de, 'config> de::MapAccess<'de> for ValueDeserializer<'config> {
@@ -459,9 +484,14 @@ impl<'de, 'config> de::MapAccess<'de> for ValueDeserializer<'config> {
         // If this is the first time around we deserialize the `value` field
         // which is the actual deserializer
         if self.hits == 1 {
-            return seed
-                .deserialize(self.de.clone())
-                .map_err(|e| e.with_key_context(&self.de.key, self.definition.clone()));
+            if let Some(de) = &self.de {
+                return seed
+                    .deserialize(de.clone())
+                    .map_err(|e| e.with_key_context(&de.key, self.definition.clone()));
+            } else {
+                return seed
+                    .deserialize(self.str_value.as_ref().unwrap().clone().into_deserializer());
+            }
         }
 
         // ... otherwise we're deserializing the `definition` field, so we need
@@ -484,6 +514,71 @@ impl<'de, 'config> de::MapAccess<'de> for ValueDeserializer<'config> {
     }
 }
 
+// Deserializer is only implemented to handle deserializing a String inside a
+// sequence (like `Vec<String>` or `Vec<Value<String>>`). `Value<String>` is
+// handled by deserialize_struct, and the plain `String` is handled by all the
+// other functions here.
+impl<'de, 'config> de::Deserializer<'de> for ValueDeserializer<'config> {
+    type Error = ConfigError;
+
+    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+    where
+        V: de::Visitor<'de>,
+    {
+        visitor.visit_str(&self.str_value.expect("string expected"))
+    }
+
+    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+    where
+        V: de::Visitor<'de>,
+    {
+        visitor.visit_string(self.str_value.expect("string expected"))
+    }
+
+    fn deserialize_struct<V>(
+        self,
+        name: &'static str,
+        fields: &'static [&'static str],
+        visitor: V,
+    ) -> Result<V::Value, Self::Error>
+    where
+        V: de::Visitor<'de>,
+    {
+        // Match on the magical struct name/field names that are passed in to
+        // detect when we're deserializing `Value<T>`.
+        //
+        // See more comments in `value.rs` for the protocol used here.
+        if name == value::NAME && fields == value::FIELDS {
+            return visitor.visit_map(self);
+        }
+        unimplemented!("only strings and Value can be deserialized from a sequence");
+    }
+
+    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+    where
+        V: de::Visitor<'de>,
+    {
+        visitor.visit_string(self.str_value.expect("string expected"))
+    }
+
+    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+    where
+        V: de::Visitor<'de>,
+    {
+        visitor.visit_unit()
+    }
+
+    serde::forward_to_deserialize_any! {
+        i8 i16 i32 i64
+        u8 u16 u32 u64
+        option
+        newtype_struct seq tuple tuple_struct map enum bool
+        f32 f64 char bytes
+        byte_buf unit unit_struct
+        identifier
+    }
+}
+
 /// A deserializer which takes two values and deserializes into a tuple of those
 /// two values. This is similar to types like `StrDeserializer` in upstream
 /// serde itself.
