Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

jsgf
Copy link
Contributor

@jsgf jsgf commented May 26, 2020

This PR implements --extern-location as a followup to #72342 as part of the implementation of #57274. The goal of this PR is to allow rustc, in coordination with the build system, to present a useful diagnostic about how to remove an unnecessary dependency from a dependency specification file (eg Cargo.toml).

EDIT: Updated to current PR state.

The location is specified for each named crate - that is, for a given --extern foo[=path] there can also be --extern-location foo=<location>. It supports three two styles of location:
~~1. --extern-location foo=file:<path>:<line> - a file path and line specification

  1. --extern-location foo=span:<path>:<start>:<end> - a span specified as a file and start and end byte offsets~~
  2. --extern-location foo=raw:<anything> - a raw string which is included in the output
  3. --extern-location foo=json:<anything> - an arbitrary Json structure which is emitted via Json diagnostics in a tool_metadata field.

1 & 2 are turned into an internal Span, so long as the path exists and is readable, and the location is meaningful (within the file, etc). This is used as the Span for a fix suggestion which is reported like other fix suggestions.

raw and json are for the case where the location isn't best expressed as a file and location within that file. For example, it could be a rule name and the name of a dependency within that rule. rustc makes no attempt to parse the raw string, and simply includes it in the output diagnostic text. json is only included in json diagnostics. raw is emitted as text and also as a json string in tool_metadata.

If no --extern-location option is specified then it will emit a default json structure consisting of {"name": name, "path": path} corresponding to the name and path in --extern name=path.

This is a prototype/RFC to make some of the earlier conversations more concrete. It doesn't stand on its own - it's only useful if implemented by Cargo and other build systems. There's also a ton of implementation details which I'd appreciate a second eye on as well.

NOTE The first commit in this PR is #72342 and should be ignored for the purposes of review. The first commit is a very simplistic implementation which is basically raw-only, presented as a MVP. The second implements the full thing, and subsequent commits are incremental fixes.

cc @ehuss @est31 @petrochenkov @estebank

@rust-highfive
Copy link
Contributor

r? @matthewjasper

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 26, 2020
@petrochenkov petrochenkov self-assigned this May 26, 2020
@tshepang
Copy link
Member

When I saw -loc, my head said "lines of code". Would it be ok to rename to --extern-location?

@jsgf
Copy link
Contributor Author

jsgf commented May 27, 2020

@tshepang Yes, I have a tendency to over-abbr.

@jsgf jsgf force-pushed the extern-loc branch 2 times, most recently from 9c0c9fe to bd9b98c Compare May 27, 2020 06:12
@rust-highfive

This comment has been minimized.

@jsgf jsgf changed the title Implement --extern-loc Implement --extern-location May 27, 2020
@jsgf jsgf force-pushed the extern-loc branch 2 times, most recently from 2951ba5 to bf1c504 Compare May 27, 2020 23:28
@rust-highfive

This comment has been minimized.

@rust-highfive
Copy link
Contributor

The job mingw-check of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
##[section]Starting: Linux mingw-check
##[section]Starting: Initialize job
Agent name: 'Azure Pipelines 65'
Agent machine name: 'fv-az578'
Current agent version: '2.168.2'
##[group]Operating System
16.04.6
LTS
LTS
##[endgroup]
##[group]Virtual Environment
Environment: ubuntu-16.04
Version: 20200517.1
Included Software: https://github.com/actions/virtual-environments/blob/ubuntu16/20200517.1/images/linux/Ubuntu1604-README.md
##[endgroup]
Agent running as: 'vsts'
Prepare build directory.
Set build variables.
Download all required tasks.
Download all required tasks.
Downloading task: Bash (3.163.2)
Checking job knob settings.
   Knob: AgentToolsDirectory = /opt/hostedtoolcache Source: ${AGENT_TOOLSDIRECTORY} 
   Knob: AgentPerflog = /home/vsts/perflog Source: ${VSTS_AGENT_PERFLOG} 
Start tracking orphan processes.
##[section]Finishing: Initialize job
##[section]Starting: Configure Job Name
==============================================================================
---
========================== Starting Command Output ===========================
[command]/bin/bash --noprofile --norc /home/vsts/work/_temp/fb540377-1c06-4650-9516-8e45d0174c18.sh

##[section]Finishing: Disable git automatic line ending conversion
##[section]Starting: Checkout rust-lang/rust@refs/pull/72603/merge to s
Task         : Get sources
Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
Version      : 1.0.0
Author       : Microsoft
---
##[command]git remote add origin https://github.com/rust-lang/rust
##[command]git config gc.auto 0
##[command]git config --get-all http.https://github.com/rust-lang/rust.extraheader
##[command]git config --get-all http.proxy
##[command]git -c http.extraheader="AUTHORIZATION: basic ***" fetch --force --tags --prune --progress --no-recurse-submodules --depth=2 origin +refs/heads/*:refs/remotes/origin/* +refs/pull/72603/merge:refs/remotes/pull/72603/merge
---
 ---> 3adb0605cc65
Step 6/7 : ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
 ---> Using cache
 ---> 28dbc326cb7f
Step 7/7 : ENV SCRIPT python3 ../x.py test src/tools/expand-yaml-anchors &&            python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu &&            python3 ../x.py build --stage 0 src/tools/build-manifest &&            python3 ../x.py test --stage 0 src/tools/compiletest &&            python3 ../x.py test src/tools/tidy &&            python3 ../x.py doc --stage 0 src/libstd &&            /scripts/validate-toolstate.sh
 ---> 537a01811900
Successfully built 537a01811900
Successfully tagged rust-ci:latest
Built container sha256:537a018119009dc218456238dec90b5530050db1e2a1e166550c218003f6159d
---
    Checking rustc_feature v0.0.0 (/checkout/src/librustc_feature)
    Checking fmt_macros v0.0.0 (/checkout/src/libfmt_macros)
    Checking rustc_ast_pretty v0.0.0 (/checkout/src/librustc_ast_pretty)
    Checking rustc_hir v0.0.0 (/checkout/src/librustc_hir)
    Checking rustc_query_system v0.0.0 (/checkout/src/librustc_query_system)
    Checking chalk-rust-ir v0.10.0
    Checking chalk-solve v0.10.0
    Checking rustc_hir_pretty v0.0.0 (/checkout/src/librustc_hir_pretty)
    Checking rustc_parse v0.0.0 (/checkout/src/librustc_parse)
    Checking rustc_ast_lowering v0.0.0 (/checkout/src/librustc_ast_lowering)
---
configure: llvm.assertions      := True
configure: dist.missing-tools   := True
configure: rust.codegen-units-std := 1
configure: rust.verify-llvm-ir  := True
configure: build.configure-args := ['--enable-sccache', '--disable-manage-submodu ...
configure: writing `config.toml` in current directory
configure: 
configure: run `python /checkout/x.py --help`
configure: 
---
Hugepagesize:       2048 kB
DirectMap4k:      147392 kB
DirectMap2M:     2998272 kB
DirectMap1G:     6291456 kB
+ python3 ../x.py test src/tools/expand-yaml-anchors
Ensuring the YAML anchors in the GitHub Actions config were expanded
Ensuring the YAML anchors in the GitHub Actions config were expanded
Building stage0 tool expand-yaml-anchors (x86_64-unknown-linux-gnu)
   Compiling unicode-xid v0.2.0
   Compiling syn v1.0.11
   Compiling linked-hash-map v0.5.2
   Compiling lazy_static v1.4.0
   Compiling lazy_static v1.4.0
   Compiling yaml-rust v0.4.3
   Compiling quote v1.0.2
   Compiling thiserror-impl v1.0.5
   Compiling thiserror v1.0.5
   Compiling yaml-merge-keys v0.4.0
   Compiling expand-yaml-anchors v0.1.0 (/checkout/src/tools/expand-yaml-anchors)
Build completed successfully in 0:00:32
+ python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu
    Finished dev [unoptimized] target(s) in 0.21s
Checking rustdoc artifacts (x86_64-unknown-linux-gnu -> i686-pc-windows-gnu)
---
    Checking rustc_feature v0.0.0 (/checkout/src/librustc_feature)
    Checking fmt_macros v0.0.0 (/checkout/src/libfmt_macros)
    Checking rustc_ast_pretty v0.0.0 (/checkout/src/librustc_ast_pretty)
    Checking rustc_hir v0.0.0 (/checkout/src/librustc_hir)
    Checking chalk-rust-ir v0.10.0
    Checking rustc_query_system v0.0.0 (/checkout/src/librustc_query_system)
    Checking chalk-solve v0.10.0
    Checking rustc_hir_pretty v0.0.0 (/checkout/src/librustc_hir_pretty)
    Checking rustc_parse v0.0.0 (/checkout/src/librustc_parse)
    Checking rustc_ast_lowering v0.0.0 (/checkout/src/librustc_ast_lowering)
---
skip untracked path cpu-usage.csv during rustfmt invocations
skip untracked path src/doc/book/ during rustfmt invocations
skip untracked path src/doc/rust-by-example/ during rustfmt invocations
skip untracked path src/llvm-project/ during rustfmt invocations
Diff in /checkout/src/librustc_lint/context.rs at line 31:
 use rustc_middle::middle::stability;
 use rustc_middle::ty::layout::{LayoutError, TyAndLayout};
 use rustc_middle::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt};
+use rustc_session::config::ExternDepSpec;
 use rustc_session::lint::{add_elided_lifetime_in_path_suggestion, BuiltinLintDiagnostics};
 use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
Diff in /checkout/src/librustc_lint/context.rs at line 37:
Diff in /checkout/src/librustc_lint/context.rs at line 37:
-use rustc_session::config::ExternDepSpec;
 use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP};
 use rustc_target::abi::LayoutOf;
 
Running `"/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/rustfmt" "--config-path" "/checkout" "--edition" "2018" "--unstable-features" "--skip-children" "--check" "/checkout/src/librustc_lint/context.rs"` failed.
If you're running `tidy`, try again with `--bless`. Or, if you just want to format code, run `./x.py fmt` instead.
Build completed unsuccessfully in 0:00:38
== clock drift check ==
  local time: Thu May 28 23:43:15 UTC 2020
  network time: Thu, 28 May 2020 23:43:16 GMT
  network time: Thu, 28 May 2020 23:43:16 GMT
== end clock drift check ==

##[error]Bash exited with code '1'.
##[section]Finishing: Run build
##[section]Starting: Checkout rust-lang/rust@refs/pull/72603/merge to s
Task         : Get sources
Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
Version      : 1.0.0
Author       : Microsoft
Author       : Microsoft
Help         : [More Information](https://go.microsoft.com/fwlink/?LinkId=798199)
==============================================================================
Cleaning any cached credential from repository: rust-lang/rust (GitHub)
##[section]Finishing: Checkout rust-lang/rust@refs/pull/72603/merge to s
Cleaning up task key
Start cleaning up orphan processes.
Terminate orphan process: pid (3649) (python)
##[section]Finishing: Finalize Job

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @rust-lang/infra. (Feature Requests)

@petrochenkov petrochenkov added T-cargo Relevant to the cargo team, which will review and decide on the PR/issue. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 30, 2020
@petrochenkov
Copy link
Contributor

petrochenkov commented May 30, 2020

This is great, thank you.
Diagnostic spans pointing to build system files in particular.
I'll nominate this for the compiler and cargo teams because this needs feedback from some wider audience.
(One question in particular is what process to use - MCP? RFC?)

I'll leave a few notes and questions in comments below.

@petrochenkov
Copy link
Contributor

Note 1 - Motivation

This is useful not only for the unused_crate_dependencies lint, but for any kind of diagnostics that want to show the point where a crate name was introduced.

All "cannot find or load crate" errors, name ambiguity errors during resolution, lint for private dependencies (#44663), perhaps something else.

@petrochenkov
Copy link
Contributor

Note 2 - Dependency tracking

When file is loaded into source map during conversion into a span that file also becomes a dependency for the build.
It's emitted into the depinfo files (.d) used by cargo for rebuilds.

Looks like PR puts the files specified in --extern-location into source map lazily, only if an error requiring these spans actually happens.
This is great because, AFAIK, cargo doesn't rebuild anything when you touch Cargo.toml without introducing some real changes.
If Cargo.toml is put into depinfo, then the rebuilds will happen, unless cargo specifically removes it from dependencies.

Lazy loading may be inconvenient in some cases when we want to work with spans uniformly, though.
E.g. you cannot put an item span and a span from --extern-location together into a Vec<Span> without loading the file and adding it to dependencies.

@petrochenkov
Copy link
Contributor

Note 3 - Relative path

If the path in --extern-location foo=file:bar.mk is relative, what should be considered the base directory?

Will cargo and other tools use absolute or relative paths in practice?

@petrochenkov
Copy link
Contributor

Note 4 - Command line length compression

Somewhat related to note 3.

If tools start using absolute paths for --extern-location, e.g. --extern-location foo=span:/my/full/path/Cargo.toml:23:32 rather than --extern-location foo=span:Cargo.toml:23:32, then it will be easy to make the command line very long and hit some limits?

In practice all the paths from cargo will refer to the same Cargo.toml, but different byte ranges inside it.
So, some compression scheme could be useful.
--extern-location-file my_file=/my/full/path/Cargo.toml --extern-location foo=my_file:23:32 --extern-location bar=my_file:34:43.

@petrochenkov
Copy link
Contributor

Note 5 - Over-engineering

Are 4 types of extern locations really necessary?
(Leaving this for the teams' feedback.)

@petrochenkov petrochenkov added S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 30, 2020
@petrochenkov petrochenkov removed their assignment May 30, 2020
@jsgf
Copy link
Contributor Author

jsgf commented May 31, 2020

@petrochenkov Thank you very much for taking the time to look at this.

1: Yes, I hadn't really considered other uses, but I'm glad there are some.

2: I was concerned about the Spans becoming part of the state of the build, both as dependencies, and for incremental builds. I wasn't sure if it was desirable or not, or what the effects would be. It sounds like it's not an issue, and even desirable.

3: I think the path should be relative to rustc cwd, since Cargo (or build system in general) control both the working directory and the paths. They could be absolute, but that would be very redundant. They're also subject to --remap-path-prefix which I think is expected.

4: I was a little concerned about command-line expansion, but ultimately decided that it isn't an issue we need to solve now - it could be added later if experience shows that it's necessary. It's proportional to the number of direct dependencies a crate has, which doesn't seem to be large - I haven't done a systematic survey, but my gut says that it's going to be almost always <50. It would be a different matter if it also affected indirect dependencies. If it is needed, then I'm thinking of some scheme of adding a new option to give short ids to paths, and a new location type to reference them, eg, --extern-location-path 0:foo/Cargo.toml --extern-location spanref:0:234:567.

5: I have a local change to remove raw, since it's a strict subset of json. I'm using json for Buck, and I'd expect cargo to use span if it's going to use it at all, which makes file redundant - but it seems like the easiest to use for simpler cases. (This is also one of the reasons to defer a command-line option compression scheme for now.)

One thing I'd like to highlight is that the json support includes a schema change for the json diagnostics by adding a tool_metadata field. The intent is to allow json to be round-tripped through rustc without needing to invent a new encoding/serialization/quoting scheme. It's currently good enough for me to prototype with, but I'd like guidance as to whether there's a better way to handle this (if nothing else I wonder if it should be on just the top-level diagnostic, rather than every child diagnostic).

@jsgf
Copy link
Contributor Author

jsgf commented Jun 2, 2020

Thinking about raw vs json a bit more - the json type is only emitted in the json format diagnostics and never appears in the human-visible rendered form. But if you want to present something to the user as advice that's not a file coordinate, then it would be useful to have a text type for that...

@nikomatsakis
Copy link
Contributor

@bors delegate+

I'm delegating to @jsgf to do r=nikomatsakis once the nit is addressed.

@bors
Copy link
Collaborator

bors commented Feb 6, 2021

✌️ @jsgf can now approve this pull request

@bors
Copy link
Collaborator

bors commented Feb 7, 2021

☔ The latest upstream changes (presumably #79078) made this pull request unmergeable. Please resolve the merge conflicts.

jsgf added 3 commits February 7, 2021 14:54
This allows a build system to indicate a location in its own dependency
specification files (eg Cargo's `Cargo.toml`) which can be reported
along side any unused crate dependency.

This supports several types of location:
 - 'json' - provide some json-structured data, which is included in the json diagnostics
     in a `tool_metadata` field
 - 'raw' - emit the provided string into the output. This also appears as a json string in
     `tool_metadata`.

If no `--extern-location` is explicitly provided then a default json entry of the form
`"tool_metadata":{"name":<cratename>,"path":<cratepath>}` is emitted.
...so we can skip serializing `tool_metadata` if it hasn't been set.
This makes the output a bit cleaner, and avoiding having to update a
bunch of unrelated tests.
This will make sure the encoder will get updated if any new fields are
added to Diagnostic.
@jsgf
Copy link
Contributor Author

jsgf commented Feb 7, 2021

@bors r+

@bors
Copy link
Collaborator

bors commented Feb 7, 2021

📌 Commit 91d8c3b has been approved by jsgf

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 7, 2021
@jsgf
Copy link
Contributor Author

jsgf commented Feb 7, 2021

@bors r=nikomatsakis

@bors
Copy link
Collaborator

bors commented Feb 7, 2021

💡 This pull request was already approved, no need to approve it again.

@bors
Copy link
Collaborator

bors commented Feb 7, 2021

📌 Commit 91d8c3b has been approved by nikomatsakis

@bors
Copy link
Collaborator

bors commented Feb 8, 2021

⌛ Testing commit 91d8c3b with merge 0b7a598...

@bors
Copy link
Collaborator

bors commented Feb 8, 2021

☀️ Test successful - checks-actions
Approved by: nikomatsakis
Pushing 0b7a598 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Feb 8, 2021
@bors bors merged commit 0b7a598 into rust-lang:master Feb 8, 2021
@rustbot rustbot added this to the 1.52.0 milestone Feb 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-cargo Relevant to the cargo team, which will review and decide on the PR/issue. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.