Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose manifest error chain in CargoErrors #6157

Merged
merged 3 commits into from
Oct 13, 2018

Conversation

alexheretic
Copy link
Member

Adds new ManifestErrors to the CargoError causal chain. These errors pass on their display, but provide more detail on which manifests are at fault when failing to build a Workspace. This is useful for lib users, in particular rls, allowing lookup of a particular manifest file that caused the error. See #6144.

For example a workspace foo where a member bar has an invalid toml manifest would have the error chain:

  • failed to parse manifest at /home/alex/project/foo/bar/Cargo.toml
    ManifestError: /home/alex/project/foo/Cargo.toml
  • failed to parse manifest at /home/alex/project/foo/bar/Cargo.toml
    ManifestError: /home/alex/project/foo/bar/Cargo.toml
  • failed to parse manifest at /home/alex/project/foo/bar/Cargo.toml
  • could not parse input as TOML
  • expected a value, found an equals at line 8

This will allow rls to point to a particular workspace member's manifest file when that manifest fails to deserialize, has invalid paths, etc.

This change should not affect binary use.

@rust-highfive
Copy link

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @matklad (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@alexcrichton
Copy link
Member

Thanks for the PR! I wonder though if the filtering of "don't wrap I/O errors" can happen in a different location? Ideally we'd deterministically wrap an error in a manifest error after a certain point instead of filtering after-the-fact (which seems like it could be lossy)

@alexheretic
Copy link
Member Author

Yes i think that probably can be removed, it'll mean finding the correct manifest to plonk the error on will be a little harder.

But it also makes it simpler.

@alexcrichton
Copy link
Member

Looks like some tests are failing, but is this also the best place perhaps? I would have expected error wrapping like this to happen somewhere within src/cargo/util/toml/*.rs as that's where all our various toml-parsing utilities are

@alexheretic
Copy link
Member Author

Simply wrapping in read_manifest would only wrap the root cause I think, rather than produce a chain of manifest errors. The chain is important so I can pick the nearest manifest inside the project for highlighting.

However, the initial manifest error could come from there. I'll see if that works.

@alexcrichton
Copy link
Member

Thanks! I'm not really sure what the displayable part is doing now though, was that necessary to keep the tests passing? (it's also ok to just update the output of the tests)

@alexheretic
Copy link
Member Author

alexheretic commented Oct 11, 2018

Well these errors provide a chain of info to lib users, they don't add any "displayable" info for the message / bin users. Because of this I thought it made sense to filter them out of the text output, plus having them in caused a bunch of tests to fail as some error messages became duplicated.

I added the trait to make the meaning clearer, rather than filtering ManifestErrors directly. This'll make it easier to add another such error chain to other areas, which I'd like to do with the compile errors.

@alexcrichton
Copy link
Member

I think we have at least one or two instances of "marker errors" in Cargo, and I think those strategies could be used to avoid duplication of error messages? I think the internal constructor is an example of one which flags an error as internal but doesn't affect the backtrace of displayed errors that show up

@alexheretic
Copy link
Member Author

The difference here though is that I'm intending to change the backtrace. The backtrace is added to in order to trace the manifests involved in an error.

@alexcrichton
Copy link
Member

Yes it should be possible to have type-level markers in the backtrace which don't affect how it's printed (without the addition of a new method). I believe that's how internal errors work in Cargo today (although they're specifically used to change printing, but only because it's special cased)

@alexheretic
Copy link
Member Author

The wrapped error indeed doesn't affect the display. The filtering is used when we're printing each cause in the chain. ManifestErrors will have the same display as their cause, so if you just print the chain you get a bunch of duplication.

  • failed to parse manifest at /home/alex/project/foo/bar/Cargo.toml
  • could not parse input as TOML
  • expected a value, found an equals at line 8

becomes

  • failed to parse manifest at /home/alex/project/foo/bar/Cargo.toml
  • failed to parse manifest at /home/alex/project/foo/bar/Cargo.toml
  • failed to parse manifest at /home/alex/project/foo/bar/Cargo.toml
  • could not parse input as TOML
  • expected a value, found an equals at line 8

When printing out the displays this isn't useful, hence the filtering. Yet I do want this "duplication", because each extra link has extra info. In particular which manifest inside a project is "nearest" to the error.

I guess I'm doing a bad job at explaining this. I feel like I'm dancing around the same points and probably missing what you're after.

@alexcrichton
Copy link
Member

@alexheretic er sorry well my point is that displayable probably does not need to be added to this PR. That's some extra infrastructure being added in this PR which is going to be difficult to maintain going forward. I think you can instead remove DisplayableError and fix the problem with duplicate outputs of errors in the error chain printing elsewhere.

I would recommend looking at Internal, which is a type-level marker for an error which doesn't affect the output display chain.

@alexheretic
Copy link
Member Author

As I'm currently using the cause-chain to get the manifests involved I don't think Internal will work for this, it doesn't affect the display chain because it takes the place of it's cause and doesn't allow adding potentially lots of links.

Perhaps I could provide a different chain of ManifestErrors outside of the cause-chain. I'll give it a try anyway.

@alexheretic alexheretic force-pushed the member-manifest-error branch from 3549788 to 25b7ad2 Compare October 12, 2018 19:55
@alexheretic
Copy link
Member Author

Ok maybe this is what you're after, now lower impact outside of the intended usage as a new method ManifestError::manifest_causes returns the ManifestError chain I need, but general cause chain acts the same way as Internal as you suggested.

@alexcrichton
Copy link
Member

@bors: r+

Ah yeah that looks good to me, thanks so much!

@bors
Copy link
Contributor

bors commented Oct 13, 2018

📌 Commit 25b7ad2 has been approved by alexcrichton

@bors
Copy link
Contributor

bors commented Oct 13, 2018

⌛ Testing commit 25b7ad2 with merge 04c689ebf17be091e7a173034422e4fee5a0a208...

@bors
Copy link
Contributor

bors commented Oct 13, 2018

💔 Test failed - status-appveyor

@alexcrichton
Copy link
Member

@bors: retry

@bors
Copy link
Contributor

bors commented Oct 13, 2018

⌛ Testing commit 25b7ad2 with merge 6d4be78...

bors added a commit that referenced this pull request Oct 13, 2018
Expose manifest error chain in CargoErrors

Adds new `ManifestError`s to the `CargoError` causal chain. These errors pass on their display, but provide more detail on which manifests are at fault when failing to build a `Workspace`. This is useful for lib users, in particular rls, allowing lookup of a particular manifest file that caused the error. See #6144.

For example a workspace _foo_ where a member _bar_ has an invalid toml manifest would have the error chain:
- failed to parse manifest at `/home/alex/project/foo/bar/Cargo.toml`
  _ManifestError: /home/alex/project/foo/Cargo.toml_
- failed to parse manifest at `/home/alex/project/foo/bar/Cargo.toml`
  _ManifestError: /home/alex/project/foo/bar/Cargo.toml_
- failed to parse manifest at `/home/alex/project/foo/bar/Cargo.toml`
- could not parse input as TOML
- expected a value, found an equals at line 8

This will allow rls to point to a particular workspace member's manifest file when that manifest fails to deserialize, has invalid paths, etc.

This change should not affect binary use.
@alexheretic
Copy link
Member Author

@alexcrichton thanks for patiently reviewing this!

@bors
Copy link
Contributor

bors commented Oct 13, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: alexcrichton
Pushing 6d4be78 to master...

@bors bors merged commit 25b7ad2 into rust-lang:master Oct 13, 2018
@alexheretic alexheretic deleted the member-manifest-error branch October 13, 2018 02:30
bors added a commit that referenced this pull request Oct 17, 2018
Add PackageError wrappers for activation errors

Similarly to #6157 this wraps compile errors with `PackageId` info to allow lib users, in this case rls, to discern where something went wrong.

In particular if a dependency has a dodgy version or doesn't exist the error chain will now contain a <s>PackageError that provides the package id</s> `ResolveError` that provides the package path from error-parent -> root. From this I figure out if the error better relates to a workspace member, and target that manifest for diagnostics.
bors added a commit that referenced this pull request Oct 17, 2018
Add PackageError wrappers for activation errors

Similarly to #6157 this wraps compile errors with `PackageId` info to allow lib users, in this case rls, to discern where something went wrong.

In particular if a dependency has a dodgy version or doesn't exist the error chain will now contain a <s>PackageError that provides the package id</s> `ResolveError` that provides the package path from error-parent -> root. From this I figure out if the error better relates to a workspace member, and target that manifest for diagnostics.
@ehuss ehuss added this to the 1.31.0 milestone Feb 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants