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

Fixed toolchain version drift, improved error handling, config loading and refactoring. #217

Merged
merged 1 commit into from
Aug 18, 2023

Conversation

nitkach
Copy link
Contributor

@nitkach nitkach commented Aug 11, 2023

This PR solves several problems

Problem 1

After resolving this issue #188, this problem was revealed.
I didn't create an issue, I just fixed it in this PR.

When cargo of the new version tries to call rustc of the old version and pass it arguments that it does not support, the program breaks.
This happens when executing a command in cargo_metadata_command().

Description of the situation in the diagram:

toolchain-fiasco

Inside MetadataCommand::new() creates cargo metadata which calls rustc.
It, in turn, takes the toolchain from PATH="~/.rustup/toolchains/1.65.0-*"

Problem 2

Also in repository with 1.65.0 in rust-toolchain file the following error occurs:

$ cargo marker

Compiling Lints:
error: the `-Z` flag is only accepted on the nightly channel of Cargo, but this is the `stable` channel
See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information about Rust release channels.
Error: LintCrateBuildFail

Diagram of command calls and environment variables:

toolchain-unstable

The command cargo build ... -Z unstable-options ... uses a stable toolchain, despite the specified RUSTUP_TOOLCHAIN=nightly-2023-07-03.

Then rustc is called, the stable toolchain is taken from PATH and a command execution error occurs.
Cannot use the arguments available on the nightly version of cargo in the stable channel.


To fix this, I changed the cargo_command() of Toolchain.
Now the

rustup run {toolchain} cargo

is being created.
This makes rustup a proxy for cargo, guaranteed to call cargo with the specified toolchain.


Cargo workspace manifest location

Now the location of the workspace manifest file is obtained by executing the cargo_locate_project method on the Cargo type.
The rustup run {toolchain} cargo locate-project --workspace command is executed.


Error handling

I have plan to refactor error handling in future PR.
I have removed the error codes from ExitStatus, as they do not work as I assume. In the terminal, it always shows that (exit code: 1) is returned.

https://github.com/nitkach/marker/blob/b95435d77065210bbe38e6995f35bd165f280612/cargo-marker/src/exit.rs#L81-L83
Adding the Fatal variant with a description and the source of the error makes creating errors easier.


Parsing TOML as strongly typed data structures

For parsing toml, I added the use of rust types, which deserializes the document into a structure with fields.


Display error for toml file while parsing

I also noticed that it is possible to output errors in more readable way

Debug:

Can't parse config: Error { inner: Error { inner: TomlError { message: "data did not match any variant of untagged enum LintDependency", original: Some("[workspace]\nmembers = [\n  \"cargo-marker\",\n  \"marker_adapter\",\n  \"marker_api\",\n  \"marker_rustc_driver\",\n  \"marker_utils\",\n  \"marker_lints\",\n  \"marker_uitest\",\n  \"marker_uilints\",\n]\nresolver = \"2\"\n\n[workspace.metadata.marker.lints]\nmarker_lints = { foo = \"./marker_lints\" }\n"), keys: ["workspace", "metadata", "marker", "lints", "marker_lints"], span: Some(245..271) } } }

Display:

Can't parse config: TOML parse error at line 15, column 16
   |
15 | marker_lints = { foo = "./marker_lints" }
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
data did not match any variant of untagged enum LintDependency

Some code changes

I'm learning how to use iterators. Where the mut variable and the for loop were used, I replaced that with iterators.
In some places, an immutable Vec<T> was created, which I changed to an [T].

@xFrednet xFrednet self-assigned this Aug 12, 2023
@xFrednet xFrednet added C-enhancement Category: New feature or request A-marker-cargo Area: All things connected to `cargo_marker` S-waiting-on-review Status: Awaiting review labels Aug 12, 2023
@xFrednet xFrednet added this to the v0.2.0 milestone Aug 12, 2023
Copy link
Member

@xFrednet xFrednet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @nitkach, thank you for the PR and welcome to the project!

Could you explain how you tested this PR? I have a lab project, with a toolchain.toml file setting the channel to 1.65.0 (like explained in your images) and cargo marker passes just fine without the drift (or at least without any errors).

Then a general note, with the last PR touching this whole toolchain thing, I contemplated if it would be better to invoke cargo marker again with the right toolchain. I have the feeling it would make the code a bit cleaner, but also add a layer of complexity. This might also not help with the version drift, since the old toolchain version would still be in the PATH variable. I thought it was still worth mentioning, since you seem to have a good understanding of the toolchain magic now ^^

Please reach out, if anything is unclear or you would like some support :)

cargo-marker/src/backend/cargo.rs Show resolved Hide resolved
cargo-marker/src/backend/cargo.rs Show resolved Hide resolved
cargo-marker/src/cli.rs Outdated Show resolved Hide resolved
cargo-marker/src/backend/cargo.rs Show resolved Hide resolved
cargo-marker/src/backend/lints/build.rs Outdated Show resolved Hide resolved
cargo-marker/src/backend/toolchain.rs Show resolved Hide resolved
@Veetaha
Copy link
Contributor

Veetaha commented Aug 12, 2023

Could you explain how you tested this PR?

I am really surprised to see the difference in behavior of rustup between unix and windows here, because this bug doesn't reproduce for me on my Linux devbox as well, we assumed it did, and didn't verify it on linux, but it is windows-specific, in fact. The difference is that the rustup proxy prepends the toolchain directory to Path when invoking the tool on windows, but it doesn't do this on Linux. Thankfully, @nitkach works on windows, so he found this bug.

If you log the PATH (or Path on windows) just before the cargo metadata command is called you will see the difference.

let mut command = MetadataCommand::new();

Here is a cross-platform nushell script. You can run it with nu 0.83.1 interpreter (pre-built binaries) to reproduce this but it reproduces only on windows.

# Replace this with your path to marker git repo
let marker_repo = "D:/dev/marker"
let sandbox_dir = "D:/junk/sandbox"

# Add master build of marker to Path
$env.Path = (
    $env.Path
    | split row (char esep)
    | prepend $"($marker_repo)/target/debug"
)

cd $marker_repo
cargo build

rm -rf $sandbox_dir
mkdir $sandbox_dir
cd $sandbox_dir

cargo new version-drift-repro
cd version-drift-repro

"1.65.0" | save rust-toolchain

$"[workspace.metadata.marker.lints]
marker_lints = { path = '0.1.1' }" | save --append Cargo.toml

cargo marker setup --auto-install-toolchain
cargo marker

There are a couple of problems caused by this. First of all the cargo marker setup --auto-install-toolchain fails.

Details
D:/dev/marker > nu ./dbg.nu                                                                                                    08/12/2023 05:39:55 PM
    Finished dev [unoptimized + debuginfo] target(s) in 0.13s
     Created binary (application) `version-drift-repro` package
info: syncing channel updates for 'nightly-2023-07-13-x86_64-pc-windows-msvc'
info: latest update on 2023-07-13, rust version 1.73.0-nightly (33a2c2487 2023-07-12)
info: component 'llvm-tools' for target 'x86_64-pc-windows-msvc' is up to date
info: component 'rustc-dev' for target 'x86_64-pc-windows-msvc' is up to date

  nightly-2023-07-13-x86_64-pc-windows-msvc unchanged - rustc 1.73.0-nightly (33a2c2487 2023-07-12)

info: checking for self-update
Compiling rustc driver v0.1.1 with nightly-2023-07-13
    Updating crates.io index
  Installing marker_rustc_driver v0.1.1
   Compiling proc-macro2 v1.0.66
   Compiling unicode-ident v1.0.11
   Compiling windows_x86_64_msvc v0.48.0
   Compiling syn v1.0.109
   Compiling rustc_tools_util v0.3.0
   Compiling cfg-if v1.0.0
   Compiling bumpalo v3.13.0
   Compiling marker_rustc_driver v0.1.1                                                                                                              
   Compiling windows-targets v0.48.1                                                                                                                 
   Compiling windows-sys v0.48.0
   Compiling quote v1.0.32
   Compiling libloading v0.8.0
   Compiling visibility v0.0.1
   Compiling marker_api v0.1.1
error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants
   --> C:\Users\gerzo\.cargo\registry\src\git.luolix.top-1ecc6299db9ec823\marker_api-0.1.1\src\ast\expr.rs:159:11
    |
159 |     Lit = 0x1400_0000,
    |           ^^^^^^^^^^^ disallowed custom discriminant
160 |     Block = 0x1400_0001,
    |             ^^^^^^^^^^^ disallowed custom discriminant
161 |     Ctor = 0x1400_0002,
    |            ^^^^^^^^^^^ disallowed custom discriminant
162 |     Assign = 0x1400_0003,
    |              ^^^^^^^^^^^ disallowed custom discriminant
163 |     For = 0x1400_0004,
    |           ^^^^^^^^^^^ disallowed custom discriminant
164 |     Loop = 0x1400_0005,
    |            ^^^^^^^^^^^ disallowed custom discriminant
165 |     While = 0x1400_0006,
    |             ^^^^^^^^^^^ disallowed custom discriminant
166 |
167 |     Path = 0x1300_0000,
    |            ^^^^^^^^^^^ disallowed custom discriminant
168 |
169 |     Method = 0x1200_0000,
    |              ^^^^^^^^^^^ disallowed custom discriminant
170 |     Call = 0x1200_0001,
    |            ^^^^^^^^^^^ disallowed custom discriminant
171 |     // These three are just a guess, as they're not listed in the precedence table
172 |     If = 0x1200_0002,
    |          ^^^^^^^^^^^ disallowed custom discriminant
173 |     Let = 0x1200_0003,
    |           ^^^^^^^^^^^ disallowed custom discriminant
174 |     Match = 0x1200_0004,
    |             ^^^^^^^^^^^ disallowed custom discriminant
175 |
176 |     Field = 0x1100_0000,
    |             ^^^^^^^^^^^ disallowed custom discriminant
177 |
178 |     Fn = 0x1000_0000,
    |          ^^^^^^^^^^^ disallowed custom discriminant
179 |     Index = 0x1000_0001,
    |             ^^^^^^^^^^^ disallowed custom discriminant
180 |
181 |     QuestionMark = 0x0F00_0000,
    |                    ^^^^^^^^^^^ disallowed custom discriminant
...
184 |     Neg = 0x0E00_0000,
    |           ^^^^^^^^^^^ disallowed custom discriminant
185 |     /// The `!` operator
186 |     Not = 0x0E00_0001,
    |           ^^^^^^^^^^^ disallowed custom discriminant
187 |     /// The unary `*` operator
188 |     Deref = 0x0E00_0002,
    |             ^^^^^^^^^^^ disallowed custom discriminant
189 |     /// The unary `&` operator
190 |     Ref = 0x0E00_0003,
    |           ^^^^^^^^^^^ disallowed custom discriminant
191 |
192 |     As = 0x0D00_0000,
    |          ^^^^^^^^^^^ disallowed custom discriminant
...
195 |     Mul = 0x0C00_0000,
    |           ^^^^^^^^^^^ disallowed custom discriminant
196 |     /// The `/` operator
197 |     Div = 0x0C00_0001,
    |           ^^^^^^^^^^^ disallowed custom discriminant
198 |     /// The `%` operator
199 |     Rem = 0x0C00_0002,
    |           ^^^^^^^^^^^ disallowed custom discriminant
...
202 |     Add = 0x0B00_0000,
    |           ^^^^^^^^^^^ disallowed custom discriminant
203 |     /// The binary `-` operator
204 |     Sub = 0x0B00_0001,
    |           ^^^^^^^^^^^ disallowed custom discriminant
...
207 |     Shr = 0x0A00_0000,
    |           ^^^^^^^^^^^ disallowed custom discriminant
208 |     /// The `<<` operator
209 |     Shl = 0x0A00_0001,
    |           ^^^^^^^^^^^ disallowed custom discriminant
...
212 |     BitAnd = 0x0900_0000,
    |              ^^^^^^^^^^^ disallowed custom discriminant
...
215 |     BitXor = 0x0800_0000,
    |              ^^^^^^^^^^^ disallowed custom discriminant
...
218 |     BitOr = 0x0700_0000,
    |             ^^^^^^^^^^^ disallowed custom discriminant
...
221 |     Comparison = 0x0600_0000,
    |                  ^^^^^^^^^^^ disallowed custom discriminant
...
224 |     And = 0x0500_0000,
    |           ^^^^^^^^^^^ disallowed custom discriminant
...
227 |     Or = 0x0400_0000,
    |          ^^^^^^^^^^^ disallowed custom discriminant
...
230 |     Range = 0x0300_0000,
    |             ^^^^^^^^^^^ disallowed custom discriminant
...
234 |     AssignOp = 0x0200_0000,
    |                ^^^^^^^^^^^ disallowed custom discriminant
235 |
236 |     Closure = 0x0100_0000,
    |               ^^^^^^^^^^^ disallowed custom discriminant
237 |     Break = 0x0100_0001,
    |             ^^^^^^^^^^^ disallowed custom discriminant
238 |     Return = 0x0100_0002,
    |              ^^^^^^^^^^^ disallowed custom discriminant
239 |     Continue = 0x0100_0003,
    |                ^^^^^^^^^^^ disallowed custom discriminant
...
242 |     Unstable(i32),
    |     ------------- tuple variant defined here
    |
    = note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information

For more information about this error, try `rustc --explain E0658`.
error: could not compile `marker_api` due to previous error
error: failed to compile `marker_rustc_driver v0.1.1`, intermediate artifacts can be found at `C:\Users\gerzo\AppData\Local\Temp\cargo-installtaHIu9`Error: Installing the driver failed

* Make sure that you have the `rustc-dev` and `llvm-tools` components installed. Try:
    ```
    cargo marker setup --auto-install-toolchain
    ```
    or:
    ```
    rustup toolchain install nightly-2023-07-13 --component rustc-dev llvm-tools
    ```

This is because on windows rustup modifies Path, and the driver gets compiled with 1.65.0 version of toolchain.

If you get past by that, install the toolchain in a separate directory elsewhere where there is no rust-toolchain file, and then comment out the setup step in that repro script it will fail with this error:

Details
D:/dev/marker > nu dbg.nu                                                                                                      08/12/2023 05:43:12 PM
info: syncing channel updates for 'nightly-2023-07-13-x86_64-pc-windows-msvc'
info: latest update on 2023-07-13, rust version 1.73.0-nightly (33a2c2487 2023-07-12)
info: component 'llvm-tools' for target 'x86_64-pc-windows-msvc' is up to date
info: component 'rustc-dev' for target 'x86_64-pc-windows-msvc' is up to date

  nightly-2023-07-13-x86_64-pc-windows-msvc unchanged - rustc 1.73.0-nightly (33a2c2487 2023-07-12)

info: checking for self-update
Compiling rustc driver v0.1.1 with nightly-2023-07-13
    Updating crates.io index
  Installing marker_rustc_driver v0.1.1
    Updating crates.io index
   Compiling proc-macro2 v1.0.66
   Compiling unicode-ident v1.0.11
   Compiling windows_x86_64_msvc v0.48.0
   Compiling syn v1.0.109
   Compiling rustc_tools_util v0.3.0
   Compiling cfg-if v1.0.0
   Compiling bumpalo v3.13.0
   Compiling marker_rustc_driver v0.1.1                                                                                                              
   Compiling windows-targets v0.48.1
   Compiling windows-sys v0.48.0
   Compiling quote v1.0.32
   Compiling libloading v0.8.0
   Compiling visibility v0.0.1
   Compiling marker_api v0.1.1
   Compiling marker_utils v0.1.1
   Compiling marker_adapter v0.1.1
    Finished release [optimized] target(s) in 9.31s
  Installing C:\Users\gerzo\.rustup\toolchains\nightly-2023-07-13-x86_64-pc-windows-msvc\bin\marker_rustc_driver.exe
   Installed package `marker_rustc_driver v0.1.1` (executable `marker_rustc_driver.exe`)
    Finished dev [unoptimized + debuginfo] target(s) in 0.14s
     Created binary (application) `version-drift-repro` package
Error: NoTargetDir

Given all of that, I adviced @nitkach to just not specify any cargo_path for metadata command, and use rustup run cargo build when doing any compiling.

As for the metadata command, I think it is reasonable to use whatever the toolchain is installed in the user's workspace to read the metadata. We also don't want to accidentally autoinstall the nightly-2023-07-13 when running the cargo metadata command.

Under that undescriptive NoTargetDir error hides the error that is depicted on the first diagram in the PR description (cargo nightly-2023-07-13 calls rustc 1.65.0 and passes the options that it doesn't support, namely --print split-debuginfo)

@xFrednet
Copy link
Member

Thank you for the explanation and support @Veetaha

Could you explain how you tested this PR?

I am really surprised to see the difference in behavior of rustup between unix and windows here, because this bug doesn't reproduce for me on my Linux devbox as well, we assumed it did, and didn't verify it on linux, but it is windows-specific, in fact.

That explains the difference. Handling all OS specific cases in cargo-marker is the real challenge. I only use Linux and rely on the CI and now others for testing other platforms.


At this point, I feel like you have a better understanding than me, when it comes to cargo-marker. I just want it to somehow work, to run the driver. I mainly want to work on the AST

@Veetaha
Copy link
Contributor

Veetaha commented Aug 13, 2023

At this point, I feel like you have a better understanding than me, when it comes to cargo-marker.

I think today my specialty is "unraveling convoluted bugs in distributed systems", where cargo-marker, cargo, rustc, rustup, marker_rustc_driver, lint_dlls are its own kind of a distributed system with its own backward/forward compatibility problems and eventual consistencies. I'll see if I find more capacity to write some code in cargo-marker, for now I am just helping @nitkach with Rust, he has no commercial experience yet, so he's learning on cargo-marker for now

@xFrednet
Copy link
Member

Hey @nitkach and @Veetaha, I'm planning the v0.2.0 release for Thursday next week. Do you know if you'll be able to address the last comments until then? I think there are only two open ones:

  1. Clippy requires self to be used inside the function body, otherwise it warns about the following lint.

    Can you change this into using #[allow(clippy::unused_self)] instead?

  2. And config.normalize() no is no longer working.

Once they're addressed and the branch has been rebased (and some commits squashed), we can merge this as well. #214 Will most likely be merged today, so it might be better to wait with the rebase until then.

It's totally fine if you don't have the time. Also, please reach out if I can assist in any way! :)

Copy link
Member

@xFrednet xFrednet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This version looks good to me, thank you for the update!

Before this is merged, would you mind squashing your commits? You don't have to reduce it to a single one, but having descriptive commit messages would awesome. Marker usually also uses a Rebase Workflow meaning that PRs should generally not include merge commits.

Resolving merge commits in the middle of a commit history can sadly be tricky. I would suggest just squashing them with the rest of your commits into one. At least that's the easiest way. If you require any help, please reach out!

Once that is done, everything should be good to go :)

@Veetaha
Copy link
Contributor

Veetaha commented Aug 18, 2023

Merge commit is more convenient for reviewers because it's just a new commit to the branch. This way it's possible to review only the new incremental changes since the last review.

image

However, when merging into master it does make sense to perform an ultimate squash to have just a single commit for the PR which could internally have a big and dirty commit history.
In fact if you set this in the config, then bors will automatically squash commits and use the PR description and name as the commit message

# The result of merging the PR should produce a commit which is formatted
# from the PR title and PR description.
use_squash_merge = true

I know bors is deprecated, so I don't think it makes sense to configure it to do this. It's better to transition to merge queues. So @nitkach let's squash to commits manually.

Veetaha pushed a commit to nitkach/marker that referenced this pull request Aug 18, 2023
…g and refactoring

This commit contains quite a lot if changes. See them all in the PR description rust-marker#217
…g and refactoring

This commit contains quite a lot if changes. See them all in the PR description rust-marker#217
@Veetaha
Copy link
Contributor

Veetaha commented Aug 18, 2023

@xFrednet forget what I said about reviewing convenience. It's not worth it. Merge commits are so hard to wrap your head around, that it's better to always use rebase-and-squash. I thought it was simple until I had to squash the commits.

I rebased everything into a single commit. I am going to try my grasp at merge queues CI for this repo, and will hopefully find a way to make squashing automatic (IIRC merge queues support something like that).

@xFrednet could you merge this please?

@xFrednet
Copy link
Member

@xFrednet forget what I said about reviewing convenience. It's not worth it. Merge commits are so hard to wrap your head around, that it's better to always use rebase-and-squash. I thought it was simple until I had to squash the commits.

GH sucks when it comes to displaying rebases correctly. I'm used to roughly remembering what was written beforehand, and the viewed file checkbox also stays checked, if the file hasn't been changed by the rebased.

I rebased everything into a single commit. I am going to try my grasp at merge queues CI for this repo, and will hopefully find a way to make squashing automatic (IIRC merge queues support something like that).

In Clippy we tried the @bors squash, but it sadly lost the author. Even if it kept it, it would lose the signature (for signed commits). Squashing with GH might work, though. It would be awesome if you could take a look at the merge queue.

My semester is starting next week, but I hope to stay as active as I did, during the past few weeks of vacation. Ain't no rest for the wicket ^^

Copy link
Member

@xFrednet xFrednet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for all the work, you two have put into this! I'm really happy to merge this now and have these kinds of bugs fixed.

Enjoy your weekend!

bors r+

@bors
Copy link
Contributor

bors bot commented Aug 18, 2023

Build succeeded!

The publicly hosted instance of bors-ng is deprecated and will go away soon.

If you want to self-host your own instance, instructions are here.
For more help, visit the forum.

If you want to switch to GitHub's built-in merge queue, visit their help page.

@bors bors bot merged commit 74554e7 into rust-marker:master Aug 18, 2023
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-marker-cargo Area: All things connected to `cargo_marker` C-enhancement Category: New feature or request S-waiting-on-review Status: Awaiting review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants