Repository: toml-rs/toml (language: rust)

Issue:
Bad span when a root field is a map instead of a table
```rust
---
[dependencies]
toml = "*"
serde = { version = "*", features = ["derive"] }
---
use serde::Deserialize;

#[derive(Deserialize)]
struct Manifest {
    package: Package,
    bench: Vec<Bench>,
}

#[derive(Deserialize)]
struct Package {
}

#[derive(Deserialize)]
struct Bench {
}

fn main() {
    let raw = r#"
[package]
name = "foo"
version = "0.1.0"
edition = "2021"
[[bench.foo]]
"#;
    match toml::from_str::<Manifest>(raw) {
        Ok(manifest) => {},
        Err(err) => {
            println!("{err}");
        }
    }
}
```
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=cd6a70687d41e3341a4f7898e55583a9

```
TOML parse error at line 1, column 1
  |
1 | 
  | ^
invalid type: map, expected a sequence
```
(the span is empty)


Discussion / hints:

Fix patch:
diff --git a/crates/toml_edit/src/de/table.rs b/crates/toml_edit/src/de/table.rs
index 0b6183e0..33aa3970 100644
--- a/crates/toml_edit/src/de/table.rs
+++ b/crates/toml_edit/src/de/table.rs
@@ -118,7 +118,7 @@ impl crate::InlineTable {
 pub(crate) struct TableMapAccess {
     iter: indexmap::map::IntoIter<crate::InternalString, crate::table::TableKeyValue>,
     span: Option<std::ops::Range<usize>>,
-    value: Option<(crate::InternalString, crate::Item)>,
+    value: Option<(crate::Key, crate::Item)>,
 }
 
 impl TableMapAccess {
@@ -149,7 +149,7 @@ impl<'de> serde::de::MapAccess<'de> for TableMapAccess {
                         }
                         e
                     });
-                self.value = Some((v.key.into(), v.value));
+                self.value = Some((v.key, v.value));
                 ret
             }
             None => Ok(None),
@@ -162,13 +162,13 @@ impl<'de> serde::de::MapAccess<'de> for TableMapAccess {
     {
         match self.value.take() {
             Some((k, v)) => {
-                let span = v.span();
+                let span = v.span().or_else(|| k.span());
                 seed.deserialize(crate::de::ValueDeserializer::new(v))
                     .map_err(|mut e: Self::Error| {
                         if e.span().is_none() {
                             e.set_span(span);
                         }
-                        e.add_key(k.as_str().to_owned());
+                        e.add_key(k.get().to_owned());
                         e
                     })
             }


Test patch:
diff --git a/crates/toml/tests/testsuite/serde.rs b/crates/toml/tests/testsuite/serde.rs
index d9d7a6db..d7f8bc40 100644
--- a/crates/toml/tests/testsuite/serde.rs
+++ b/crates/toml/tests/testsuite/serde.rs
@@ -1346,3 +1346,32 @@ fn serialize_array_with_enum_of_optional_struct_field() {
     let raw = toml::to_string(&input).unwrap();
     snapbox::assert_eq(expected, raw);
 }
+
+#[test]
+fn span_for_sequence_as_map() {
+    #[allow(dead_code)]
+    #[derive(Deserialize)]
+    struct Manifest {
+        package: Package,
+        bench: Vec<Bench>,
+    }
+
+    #[derive(Deserialize)]
+    struct Package {}
+
+    #[derive(Deserialize)]
+    struct Bench {}
+
+    let raw = r#"
+[package]
+name = "foo"
+version = "0.1.0"
+edition = "2021"
+[[bench.foo]]
+"#;
+    let err = match toml::from_str::<Manifest>(raw) {
+        Ok(_) => panic!("should fail"),
+        Err(err) => err,
+    };
+    assert_eq!(err.span(), Some(61..66));
+}