Skip to content

Commit b2c162c

Browse files
committed
Auto merge of #12556 - epage:serde, r=arlosi
fix(toml): Improve parse errors ### What does this PR try to resolve? When we adopted `toml_edit`, we got TOML syntax errors that showed the context for where the error occurred. However, the work was not done to extend this to semantic errors reported by serde. This updates `Cargo.toml` and `Cargo.lock` code to provide that context on semantic errors. `config.toml` is not done because the schema is decentralized. In theory, this will also improve performance because we aren't having to allocate a lot of intermediate data to then throw away for every `Cargo.toml` we read. ### How should we test and review this PR? Check by commit to see this change gradually. - The `package.cargo-features` change was made to drop out dependence on `toml::Table` so we could do the direct deserialization
2 parents 3b20907 + 53dcd2f commit b2c162c

File tree

12 files changed

+77
-80
lines changed

12 files changed

+77
-80
lines changed

src/cargo/ops/lockfile.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use std::io::prelude::*;
22

33
use crate::core::{resolver, Resolve, ResolveVersion, Workspace};
44
use crate::util::errors::CargoResult;
5-
use crate::util::toml as cargo_toml;
65
use crate::util::Filesystem;
76

87
use anyhow::Context as _;
@@ -20,8 +19,7 @@ pub fn load_pkg_lockfile(ws: &Workspace<'_>) -> CargoResult<Option<Resolve>> {
2019
.with_context(|| format!("failed to read file: {}", f.path().display()))?;
2120

2221
let resolve = (|| -> CargoResult<Option<Resolve>> {
23-
let resolve: toml::Table = cargo_toml::parse_document(&s, f.path(), ws.config())?;
24-
let v: resolver::EncodableResolve = resolve.try_into()?;
22+
let v: resolver::EncodableResolve = toml::from_str(&s)?;
2523
Ok(Some(v.into_resolve(&s, ws)?))
2624
})()
2725
.with_context(|| format!("failed to parse lock file at: {}", f.path().display()))?;

src/cargo/util/toml/mod.rs

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use cargo_util::paths;
1212
use itertools::Itertools;
1313
use lazycell::LazyCell;
1414
use semver::{self, VersionReq};
15-
use serde::de::IntoDeserializer as _;
1615
use serde::de::{self, Unexpected};
1716
use serde::ser;
1817
use serde::{Deserialize, Serialize};
@@ -99,26 +98,9 @@ fn read_manifest_from_str(
9998
) -> CargoResult<(EitherManifest, Vec<PathBuf>)> {
10099
let package_root = manifest_file.parent().unwrap();
101100

102-
let toml = {
103-
let pretty_filename = manifest_file
104-
.strip_prefix(config.cwd())
105-
.unwrap_or(manifest_file);
106-
parse_document(contents, pretty_filename, config)?
107-
};
108-
109-
// Provide a helpful error message for a common user error.
110-
if let Some(package) = toml.get("package").or_else(|| toml.get("project")) {
111-
if let Some(feats) = package.get("cargo-features") {
112-
bail!(
113-
"cargo-features = {} was found in the wrong location: it \
114-
should be set at the top of Cargo.toml before any tables",
115-
feats
116-
);
117-
}
118-
}
119-
120101
let mut unused = BTreeSet::new();
121-
let manifest: TomlManifest = serde_ignored::deserialize(toml.into_deserializer(), |path| {
102+
let deserializer = toml::de::Deserializer::new(contents);
103+
let manifest: TomlManifest = serde_ignored::deserialize(deserializer, |path| {
122104
let mut key = String::new();
123105
stringify(&mut key, &path);
124106
unused.insert(key);
@@ -194,8 +176,7 @@ fn read_manifest_from_str(
194176

195177
pub fn parse_document(toml: &str, _file: &Path, _config: &Config) -> CargoResult<toml::Table> {
196178
// At the moment, no compatibility checks are needed.
197-
toml.parse()
198-
.map_err(|e| anyhow::Error::from(e).context("could not parse input as TOML"))
179+
toml.parse().map_err(Into::into)
199180
}
200181

201182
/// Warn about paths that have been deprecated and may conflict.
@@ -1537,6 +1518,10 @@ pub struct TomlPackage {
15371518
repository: Option<MaybeWorkspaceString>,
15381519
resolver: Option<String>,
15391520

1521+
// Provide a helpful error message for a common user error.
1522+
#[serde(rename = "cargo-features", skip_serializing)]
1523+
_invalid_cargo_features: Option<InvalidCargoFeatures>,
1524+
15401525
// Note that this field must come last due to the way toml serialization
15411526
// works which requires tables to be emitted after all values.
15421527
metadata: Option<toml::Value>,
@@ -3547,3 +3532,20 @@ impl TomlLintLevel {
35473532
}
35483533
}
35493534
}
3535+
3536+
#[derive(Copy, Clone, Debug)]
3537+
#[non_exhaustive]
3538+
struct InvalidCargoFeatures {}
3539+
3540+
impl<'de> de::Deserialize<'de> for InvalidCargoFeatures {
3541+
fn deserialize<D>(_d: D) -> Result<Self, D::Error>
3542+
where
3543+
D: de::Deserializer<'de>,
3544+
{
3545+
use serde::de::Error as _;
3546+
3547+
Err(D::Error::custom(
3548+
"the field `cargo-features` should be set at the top of Cargo.toml before any tables",
3549+
))
3550+
}
3551+
}

tests/testsuite/bad_config.rs

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,6 @@ fn invalid_global_config() {
171171
Caused by:
172172
could not parse TOML configuration in `[..]`
173173
174-
Caused by:
175-
could not parse input as TOML
176-
177174
Caused by:
178175
TOML parse error at line 1, column 2
179176
|
@@ -199,8 +196,11 @@ fn bad_cargo_lock() {
199196
[ERROR] failed to parse lock file at: [..]Cargo.lock
200197
201198
Caused by:
199+
TOML parse error at line 1, column 1
200+
|
201+
1 | [[package]]
202+
| ^^^^^^^^^^^
202203
missing field `name`
203-
in `package`
204204
",
205205
)
206206
.run();
@@ -303,8 +303,11 @@ fn bad_source_in_cargo_lock() {
303303
[ERROR] failed to parse lock file at: [..]
304304
305305
Caused by:
306+
TOML parse error at line 12, column 26
307+
|
308+
12 | source = \"You shall not parse\"
309+
| ^^^^^^^^^^^^^^^^^^^^^
306310
invalid source `You shall not parse`
307-
in `package.source`
308311
",
309312
)
310313
.run();
@@ -448,9 +451,6 @@ fn malformed_override() {
448451
"\
449452
[ERROR] failed to parse manifest at `[..]`
450453
451-
Caused by:
452-
could not parse input as TOML
453-
454454
Caused by:
455455
TOML parse error at line 8, column 27
456456
|
@@ -803,9 +803,6 @@ error: could not load Cargo configuration
803803
Caused by:
804804
could not parse TOML configuration in `[..]`
805805
806-
Caused by:
807-
could not parse input as TOML
808-
809806
Caused by:
810807
TOML parse error at line 1, column 7
811808
|
@@ -1288,8 +1285,11 @@ fn bad_dependency() {
12881285
error: failed to parse manifest at `[..]`
12891286
12901287
Caused by:
1288+
TOML parse error at line 8, column 23
1289+
|
1290+
8 | bar = 3
1291+
| ^
12911292
invalid type: integer `3`, expected a version string like [..]
1292-
in `dependencies.bar`
12931293
",
12941294
)
12951295
.run();
@@ -1320,8 +1320,11 @@ fn bad_debuginfo() {
13201320
error: failed to parse manifest [..]
13211321
13221322
Caused by:
1323+
TOML parse error at line 8, column 25
1324+
|
1325+
8 | debug = 'a'
1326+
| ^^^
13231327
invalid value: string \"a\", expected a boolean, 0, 1, 2, \"line-tables-only\", or \"line-directives-only\"
1324-
in `profile.dev.debug`
13251328
",
13261329
)
13271330
.run();
@@ -1352,8 +1355,11 @@ fn bad_debuginfo2() {
13521355
error: failed to parse manifest at `[..]`
13531356
13541357
Caused by:
1358+
TOML parse error at line 8, column 25
1359+
|
1360+
8 | debug = 3.6
1361+
| ^^^
13551362
invalid type: floating point `3.6`, expected a boolean, 0, 1, 2, \"line-tables-only\", or \"line-directives-only\"
1356-
in `profile.dev.debug`
13571363
",
13581364
)
13591365
.run();
@@ -1382,8 +1388,11 @@ fn bad_opt_level() {
13821388
error: failed to parse manifest at `[..]`
13831389
13841390
Caused by:
1391+
TOML parse error at line 6, column 25
1392+
|
1393+
6 | build = 3
1394+
| ^
13851395
expected a boolean or a string
1386-
in `package.build`
13871396
",
13881397
)
13891398
.run();

tests/testsuite/build.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -258,9 +258,6 @@ fn cargo_compile_with_invalid_manifest2() {
258258
"\
259259
[ERROR] failed to parse manifest at `[..]`
260260
261-
Caused by:
262-
could not parse input as TOML
263-
264261
Caused by:
265262
TOML parse error at line 3, column 23
266263
|
@@ -283,9 +280,6 @@ fn cargo_compile_with_invalid_manifest3() {
283280
"\
284281
[ERROR] failed to parse manifest at `[..]`
285282
286-
Caused by:
287-
could not parse input as TOML
288-
289283
Caused by:
290284
TOML parse error at line 1, column 5
291285
|
@@ -346,8 +340,11 @@ fn cargo_compile_with_invalid_version() {
346340
[ERROR] failed to parse manifest at `[..]`
347341
348342
Caused by:
343+
TOML parse error at line 4, column 19
344+
|
345+
4 | version = \"1.0\"
346+
| ^^^^^
349347
unexpected end of input while parsing minor version number
350-
in `package.version`
351348
",
352349
)
353350
.run();
@@ -3035,9 +3032,6 @@ fn bad_cargo_config() {
30353032
Caused by:
30363033
could not parse TOML configuration in `[..]`
30373034
3038-
Caused by:
3039-
could not parse input as TOML
3040-
30413035
Caused by:
30423036
TOML parse error at line 1, column 6
30433037
|

tests/testsuite/cargo_add/invalid_manifest/stderr.log

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
error: failed to parse manifest at `[ROOT]/case/Cargo.toml`
22

3-
Caused by:
4-
could not parse input as TOML
5-
63
Caused by:
74
TOML parse error at line 8, column 7
85
|

tests/testsuite/cargo_alias_config.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ fn alias_malformed_config_string() {
5252
Caused by:
5353
could not parse TOML configuration in `[..]/config`
5454
55-
Caused by:
56-
[..]
57-
5855
Caused by:
5956
TOML parse error at line [..]
6057
|

tests/testsuite/cargo_features.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -676,8 +676,11 @@ fn wrong_position() {
676676
error: failed to parse manifest at [..]
677677
678678
Caused by:
679-
cargo-features = [\"test-dummy-unstable\"] was found in the wrong location: it \
680-
should be set at the top of Cargo.toml before any tables
679+
TOML parse error at line 5, column 34
680+
|
681+
5 | cargo-features = [\"test-dummy-unstable\"]
682+
| ^^^^^^^^^^^^^^^^^^^^^^^
683+
the field `cargo-features` should be set at the top of Cargo.toml before any tables
681684
",
682685
)
683686
.run();

tests/testsuite/config.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -721,9 +721,6 @@ could not load Cargo configuration
721721
Caused by:
722722
could not parse TOML configuration in `[..]/.cargo/config`
723723
724-
Caused by:
725-
could not parse input as TOML
726-
727724
Caused by:
728725
TOML parse error at line 1, column 5
729726
|
@@ -1090,9 +1087,6 @@ could not load Cargo configuration
10901087
Caused by:
10911088
could not parse TOML configuration in `[..]/.cargo/config`
10921089
1093-
Caused by:
1094-
could not parse input as TOML
1095-
10961090
Caused by:
10971091
TOML parse error at line 3, column 1
10981092
|

tests/testsuite/git.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2577,9 +2577,6 @@ Caused by:
25772577
Caused by:
25782578
failed to parse manifest at `[..]`
25792579
2580-
Caused by:
2581-
could not parse input as TOML
2582-
25832580
Caused by:
25842581
TOML parse error at line 8, column 21
25852582
|

tests/testsuite/inheritable_workspace_fields.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1234,8 +1234,11 @@ fn error_workspace_false() {
12341234
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`
12351235
12361236
Caused by:
1237+
TOML parse error at line 7, column 41
1238+
|
1239+
7 | description = { workspace = false }
1240+
| ^^^^^
12371241
`workspace` cannot be false
1238-
in `package.description.workspace`
12391242
",
12401243
)
12411244
.run();
@@ -1321,9 +1324,6 @@ fn error_malformed_workspace_root() {
13211324
"\
13221325
[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml`
13231326
1324-
Caused by:
1325-
[..]
1326-
13271327
Caused by:
13281328
[..]
13291329
|

tests/testsuite/metadata.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1821,8 +1821,11 @@ fn cargo_metadata_with_invalid_authors_field() {
18211821
r#"[ERROR] failed to parse manifest at `[..]`
18221822
18231823
Caused by:
1824-
invalid type: string "", expected a vector of strings or workspace
1825-
in `package.authors`"#,
1824+
TOML parse error at line 3, column 27
1825+
|
1826+
3 | authors = ""
1827+
| ^^
1828+
invalid type: string "", expected a vector of strings or workspace"#,
18261829
)
18271830
.run();
18281831
}
@@ -1846,8 +1849,11 @@ fn cargo_metadata_with_invalid_version_field() {
18461849
r#"[ERROR] failed to parse manifest at `[..]`
18471850
18481851
Caused by:
1849-
invalid type: integer `1`, expected SemVer version
1850-
in `package.version`"#,
1852+
TOML parse error at line 3, column 27
1853+
|
1854+
3 | version = 1
1855+
| ^
1856+
invalid type: integer `1`, expected SemVer version"#,
18511857
)
18521858
.run();
18531859
}
@@ -1871,8 +1877,11 @@ fn cargo_metadata_with_invalid_publish_field() {
18711877
r#"[ERROR] failed to parse manifest at `[..]`
18721878
18731879
Caused by:
1874-
invalid type: string "foo", expected a boolean, a vector of strings, or workspace
1875-
in `package.publish`"#,
1880+
TOML parse error at line 3, column 27
1881+
|
1882+
3 | publish = "foo"
1883+
| ^^^^^
1884+
invalid type: string "foo", expected a boolean, a vector of strings, or workspace"#,
18761885
)
18771886
.run();
18781887
}

tests/testsuite/workspaces.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,9 +1090,6 @@ fn new_warning_with_corrupt_ws() {
10901090
10911091
failed to parse manifest at `[..]foo/Cargo.toml`
10921092
1093-
Caused by:
1094-
could not parse input as TOML
1095-
10961093
Caused by:
10971094
TOML parse error at line 1, column 5
10981095
|

0 commit comments

Comments
 (0)