about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-02-08 02:23:17 +0000
committerbors <bors@rust-lang.org>2021-02-08 02:23:17 +0000
commit0b7a598e12649d7ab2415a82cbc3fea879fa9dab (patch)
tree186f81bd7d9aa52d578c253d084d0ce7a188e649 /src
parentbb587b1a1737738658d2eaecd4c8c1cab555257a (diff)
parent91d8c3b521b95b64eec3329c2ddbddb2315024d9 (diff)
downloadrust-0b7a598e12649d7ab2415a82cbc3fea879fa9dab.tar.gz
rust-0b7a598e12649d7ab2415a82cbc3fea879fa9dab.zip
Auto merge of #72603 - jsgf:extern-loc, r=nikomatsakis
Implement `--extern-location`

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~~
1. `--extern-location foo=raw:<anything>` - a raw string which is included in the output
1. `--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`
Diffstat (limited to 'src')
-rw-r--r--src/doc/unstable-book/src/compiler-flags/extern-location.md31
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-bad-loctype.rs8
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-bad-loctype.stderr2
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-defl-json.rs10
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-defl-json.stderr17
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-json-bad-json.rs8
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-json-bad-json.stderr2
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-json-json.rs10
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-json-json.stderr17
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-json.rs10
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-json.stderr15
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs8
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-missing-loc.stderr2
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-missing-loctype.rs8
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-missing-loctype.stderr2
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-raw-json.rs10
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-raw-json.stderr17
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-raw-missing-loc.rs8
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-raw-missing-loc.stderr2
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-raw.rs10
-rw-r--r--src/test/ui/unused-crate-deps/extern-loc-raw.stderr15
-rw-r--r--src/test/ui/unused-crate-deps/libfib.stderr1
-rw-r--r--src/test/ui/unused-crate-deps/test.mk7
-rw-r--r--src/test/ui/unused-crate-deps/unused-aliases.stderr1
-rw-r--r--src/test/ui/unused-crate-deps/warn-attr.stderr1
-rw-r--r--src/test/ui/unused-crate-deps/warn-cmdline-static.stderr1
-rw-r--r--src/test/ui/unused-crate-deps/warn-cmdline.stderr1
27 files changed, 224 insertions, 0 deletions
diff --git a/src/doc/unstable-book/src/compiler-flags/extern-location.md b/src/doc/unstable-book/src/compiler-flags/extern-location.md
new file mode 100644
index 00000000000..1c80d5426bf
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/extern-location.md
@@ -0,0 +1,31 @@
+# `extern-location`
+
+MCP for this feature: [#303]
+
+[#303]: https://github.com/rust-lang/compiler-team/issues/303
+
+------------------------
+
+The `unused-extern-crates` lint reports when a crate was specified on the rustc
+command-line with `--extern name=path` but no symbols were referenced in it.
+This is useful to know, but it's hard to map that back to a specific place a user
+or tool could fix (ie, to remove the unused dependency).
+
+The `--extern-location` flag allows the build system to associate a location with
+the `--extern` option, which is then emitted as part of the diagnostics. This location
+is abstract and just round-tripped through rustc; the compiler never attempts to
+interpret it in any way.
+
+There are two supported forms of location: a bare string, or a blob of json:
+- `--extern-location foo=raw:Makefile:123` would associate the raw string `Makefile:123`
+- `--extern-location 'bar=json:{"target":"//my_project:library","dep":"//common:serde"}` would
+  associate the json structure with `--extern bar=<path>`, indicating which dependency of
+  which rule introduced the unused extern crate.
+
+This primarily intended to be used with tooling - for example a linter which can automatically
+remove unused dependencies - rather than being directly presented to users.
+
+`raw` locations are presented as part of the normal rendered diagnostics and included in
+the json form. `json` locations are only included in the json form of diagnostics,
+as a `tool_metadata` field. For `raw` locations `tool_metadata` is simply a json string,
+whereas `json` allows the rustc invoker to fully control its form and content.
diff --git a/src/test/ui/unused-crate-deps/extern-loc-bad-loctype.rs b/src/test/ui/unused-crate-deps/extern-loc-bad-loctype.rs
new file mode 100644
index 00000000000..3e1527e2c2e
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-bad-loctype.rs
@@ -0,0 +1,8 @@
+// --extern-location with bad location type
+
+// aux-crate:bar=bar.rs
+// compile-flags:--extern-location bar=badloc:in-the-test-file
+
+#![warn(unused_crate_dependencies)]
+
+fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-bad-loctype.stderr b/src/test/ui/unused-crate-deps/extern-loc-bad-loctype.stderr
new file mode 100644
index 00000000000..12378f12557
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-bad-loctype.stderr
@@ -0,0 +1,2 @@
+error: unknown location type `badloc`: use `raw` or `json`
+
diff --git a/src/test/ui/unused-crate-deps/extern-loc-defl-json.rs b/src/test/ui/unused-crate-deps/extern-loc-defl-json.rs
new file mode 100644
index 00000000000..a023f535b81
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-defl-json.rs
@@ -0,0 +1,10 @@
+// Default extern location from name and path if one isn't specified
+
+// check-pass
+// aux-crate:bar=bar.rs
+// compile-flags:--error-format json
+
+#![warn(unused_crate_dependencies)]
+//~^ WARNING external crate `bar` unused in
+
+fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-defl-json.stderr b/src/test/ui/unused-crate-deps/extern-loc-defl-json.stderr
new file mode 100644
index 00000000000..cee3f6c1495
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-defl-json.stderr
@@ -0,0 +1,17 @@
+{"message":"external crate `bar` unused in `extern_loc_defl_json`: remove the dependency or add `use bar as _;`","code":{"code":"unused_crate_dependencies","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/extern-loc-defl-json.rs","byte_start":146,"byte_end":146,"line_start":7,"line_end":7,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/extern-loc-defl-json.rs","byte_start":154,"byte_end":179,"line_start":7,"line_end":7,"column_start":9,"column_end":34,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":9,"highlight_end":34}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove unnecessary dependency `bar`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"json extern location","code":null,"level":"help","spans":[],"children":[],"rendered":null,"tool_metadata":{"name":"bar"}}],"rendered":"warning: external crate `bar` unused in `extern_loc_defl_json`: remove the dependency or add `use bar as _;`
+  --> $DIR/extern-loc-defl-json.rs:7:1
+   |
+LL | #![warn(unused_crate_dependencies)]
+   | ^
+   |
+note: the lint level is defined here
+  --> $DIR/extern-loc-defl-json.rs:7:9
+   |
+LL | #![warn(unused_crate_dependencies)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: remove unnecessary dependency `bar`
+
+"}
+{"message":"1 warning emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"warning: 1 warning emitted
+
+"}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-json-bad-json.rs b/src/test/ui/unused-crate-deps/extern-loc-json-bad-json.rs
new file mode 100644
index 00000000000..6fdf710a126
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-json-bad-json.rs
@@ -0,0 +1,8 @@
+// --extern-location with a raw reference
+
+// aux-crate:bar=bar.rs
+// compile-flags:--extern-location bar=json:[{"malformed
+
+#![warn(unused_crate_dependencies)]
+
+fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-json-bad-json.stderr b/src/test/ui/unused-crate-deps/extern-loc-json-bad-json.stderr
new file mode 100644
index 00000000000..20d606372e0
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-json-bad-json.stderr
@@ -0,0 +1,2 @@
+error: `--extern-location`: malformed json location `[{"malformed`
+
diff --git a/src/test/ui/unused-crate-deps/extern-loc-json-json.rs b/src/test/ui/unused-crate-deps/extern-loc-json-json.rs
new file mode 100644
index 00000000000..02a9869151f
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-json-json.rs
@@ -0,0 +1,10 @@
+// --extern-location with a raw reference
+
+// check-pass
+// aux-crate:bar=bar.rs
+// compile-flags:--extern-location bar=json:{"key":123,"value":{}} --error-format json
+
+#![warn(unused_crate_dependencies)]
+//~^ WARNING external crate `bar` unused in
+
+fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-json-json.stderr b/src/test/ui/unused-crate-deps/extern-loc-json-json.stderr
new file mode 100644
index 00000000000..5fc8397e469
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-json-json.stderr
@@ -0,0 +1,17 @@
+{"message":"external crate `bar` unused in `extern_loc_json_json`: remove the dependency or add `use bar as _;`","code":{"code":"unused_crate_dependencies","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/extern-loc-json-json.rs","byte_start":169,"byte_end":169,"line_start":7,"line_end":7,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/extern-loc-json-json.rs","byte_start":177,"byte_end":202,"line_start":7,"line_end":7,"column_start":9,"column_end":34,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":9,"highlight_end":34}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove unnecessary dependency `bar`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"json extern location","code":null,"level":"help","spans":[],"children":[],"rendered":null,"tool_metadata":{"key":123,"value":{}}}],"rendered":"warning: external crate `bar` unused in `extern_loc_json_json`: remove the dependency or add `use bar as _;`
+  --> $DIR/extern-loc-json-json.rs:7:1
+   |
+LL | #![warn(unused_crate_dependencies)]
+   | ^
+   |
+note: the lint level is defined here
+  --> $DIR/extern-loc-json-json.rs:7:9
+   |
+LL | #![warn(unused_crate_dependencies)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: remove unnecessary dependency `bar`
+
+"}
+{"message":"1 warning emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"warning: 1 warning emitted
+
+"}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-json.rs b/src/test/ui/unused-crate-deps/extern-loc-json.rs
new file mode 100644
index 00000000000..212610d532e
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-json.rs
@@ -0,0 +1,10 @@
+// --extern-location with a raw reference
+
+// check-pass
+// aux-crate:bar=bar.rs
+// compile-flags:--extern-location bar=json:{"key":123,"value":{}}
+
+#![warn(unused_crate_dependencies)]
+//~^ WARNING external crate `bar` unused in
+
+fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-json.stderr b/src/test/ui/unused-crate-deps/extern-loc-json.stderr
new file mode 100644
index 00000000000..a6bbc0da1c6
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-json.stderr
@@ -0,0 +1,15 @@
+warning: external crate `bar` unused in `extern_loc_json`: remove the dependency or add `use bar as _;`
+  --> $DIR/extern-loc-json.rs:7:1
+   |
+LL | #![warn(unused_crate_dependencies)]
+   | ^
+   |
+note: the lint level is defined here
+  --> $DIR/extern-loc-json.rs:7:9
+   |
+LL | #![warn(unused_crate_dependencies)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: remove unnecessary dependency `bar`
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs b/src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs
new file mode 100644
index 00000000000..9339a004d3b
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-missing-loc.rs
@@ -0,0 +1,8 @@
+// --extern-location with a raw reference
+
+// aux-crate:bar=bar.rs
+// compile-flags:--extern-location bar
+
+#![warn(unused_crate_dependencies)]
+
+fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-missing-loc.stderr b/src/test/ui/unused-crate-deps/extern-loc-missing-loc.stderr
new file mode 100644
index 00000000000..4584fbfb67f
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-missing-loc.stderr
@@ -0,0 +1,2 @@
+error: `--extern-location`: specify location for extern crate `bar`
+
diff --git a/src/test/ui/unused-crate-deps/extern-loc-missing-loctype.rs b/src/test/ui/unused-crate-deps/extern-loc-missing-loctype.rs
new file mode 100644
index 00000000000..4768365a653
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-missing-loctype.rs
@@ -0,0 +1,8 @@
+// --extern-location with no type
+
+// aux-crate:bar=bar.rs
+// compile-flags:--extern-location bar=missing-loc-type
+
+#![warn(unused_crate_dependencies)]
+
+fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-missing-loctype.stderr b/src/test/ui/unused-crate-deps/extern-loc-missing-loctype.stderr
new file mode 100644
index 00000000000..d0c36ebeb14
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-missing-loctype.stderr
@@ -0,0 +1,2 @@
+error: unknown location type `missing-loc-type`: use `raw` or `json`
+
diff --git a/src/test/ui/unused-crate-deps/extern-loc-raw-json.rs b/src/test/ui/unused-crate-deps/extern-loc-raw-json.rs
new file mode 100644
index 00000000000..207615ccc87
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-raw-json.rs
@@ -0,0 +1,10 @@
+// --extern-location with a raw reference
+
+// check-pass
+// aux-crate:bar=bar.rs
+// compile-flags:--extern-location bar=raw:in-the-test-file --error-format json
+
+#![warn(unused_crate_dependencies)]
+//~^ WARNING external crate `bar` unused in
+
+fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-raw-json.stderr b/src/test/ui/unused-crate-deps/extern-loc-raw-json.stderr
new file mode 100644
index 00000000000..25f099927fd
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-raw-json.stderr
@@ -0,0 +1,17 @@
+{"message":"external crate `bar` unused in `extern_loc_raw_json`: remove the dependency or add `use bar as _;`","code":{"code":"unused_crate_dependencies","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/extern-loc-raw-json.rs","byte_start":162,"byte_end":162,"line_start":7,"line_end":7,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"the lint level is defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/extern-loc-raw-json.rs","byte_start":170,"byte_end":195,"line_start":7,"line_end":7,"column_start":9,"column_end":34,"is_primary":true,"text":[{"text":"#![warn(unused_crate_dependencies)]","highlight_start":9,"highlight_end":34}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove unnecessary dependency `bar` at `in-the-test-file`","code":null,"level":"help","spans":[],"children":[],"rendered":null},{"message":"raw extern location","code":null,"level":"help","spans":[{"file_name":"$DIR/extern-loc-raw-json.rs","byte_start":0,"byte_end":0,"line_start":1,"line_end":1,"column_start":1,"column_end":1,"is_primary":true,"text":[],"label":null,"suggested_replacement":"in-the-test-file","suggestion_applicability":"Unspecified","expansion":null}],"children":[],"rendered":null},{"message":"json extern location","code":null,"level":"help","spans":[],"children":[],"rendered":null,"tool_metadata":"in-the-test-file"}],"rendered":"warning: external crate `bar` unused in `extern_loc_raw_json`: remove the dependency or add `use bar as _;`
+  --> $DIR/extern-loc-raw-json.rs:7:1
+   |
+LL | #![warn(unused_crate_dependencies)]
+   | ^
+   |
+note: the lint level is defined here
+  --> $DIR/extern-loc-raw-json.rs:7:9
+   |
+LL | #![warn(unused_crate_dependencies)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: remove unnecessary dependency `bar` at `in-the-test-file`
+
+"}
+{"message":"1 warning emitted","code":null,"level":"warning","spans":[],"children":[],"rendered":"warning: 1 warning emitted
+
+"}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-raw-missing-loc.rs b/src/test/ui/unused-crate-deps/extern-loc-raw-missing-loc.rs
new file mode 100644
index 00000000000..65b64268394
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-raw-missing-loc.rs
@@ -0,0 +1,8 @@
+// --extern-location with a raw reference
+
+// aux-crate:bar=bar.rs
+// compile-flags:--extern-location bar=raw
+
+#![warn(unused_crate_dependencies)]
+
+fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-raw-missing-loc.stderr b/src/test/ui/unused-crate-deps/extern-loc-raw-missing-loc.stderr
new file mode 100644
index 00000000000..4b51266e4f6
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-raw-missing-loc.stderr
@@ -0,0 +1,2 @@
+error: `--extern-location`: missing `raw` location
+
diff --git a/src/test/ui/unused-crate-deps/extern-loc-raw.rs b/src/test/ui/unused-crate-deps/extern-loc-raw.rs
new file mode 100644
index 00000000000..fc3fed1e10e
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-raw.rs
@@ -0,0 +1,10 @@
+// --extern-location with a raw reference
+
+// check-pass
+// aux-crate:bar=bar.rs
+// compile-flags:--extern-location bar=raw:in-the-test-file
+
+#![warn(unused_crate_dependencies)]
+//~^ WARNING external crate `bar` unused in
+
+fn main() {}
diff --git a/src/test/ui/unused-crate-deps/extern-loc-raw.stderr b/src/test/ui/unused-crate-deps/extern-loc-raw.stderr
new file mode 100644
index 00000000000..2cdd0055866
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/extern-loc-raw.stderr
@@ -0,0 +1,15 @@
+warning: external crate `bar` unused in `extern_loc_raw`: remove the dependency or add `use bar as _;`
+  --> $DIR/extern-loc-raw.rs:7:1
+   |
+LL | #![warn(unused_crate_dependencies)]
+   | ^
+   |
+note: the lint level is defined here
+  --> $DIR/extern-loc-raw.rs:7:9
+   |
+LL | #![warn(unused_crate_dependencies)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: remove unnecessary dependency `bar` at `in-the-test-file`
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/unused-crate-deps/libfib.stderr b/src/test/ui/unused-crate-deps/libfib.stderr
index 15833126bd6..479f51bff46 100644
--- a/src/test/ui/unused-crate-deps/libfib.stderr
+++ b/src/test/ui/unused-crate-deps/libfib.stderr
@@ -5,6 +5,7 @@ LL | pub fn fib(n: u32) -> Vec<u32> {
    | ^
    |
    = note: requested on the command line with `-W unused-crate-dependencies`
+   = help: remove unnecessary dependency `bar`
 
 warning: 1 warning emitted
 
diff --git a/src/test/ui/unused-crate-deps/test.mk b/src/test/ui/unused-crate-deps/test.mk
new file mode 100644
index 00000000000..0b98b4e44fb
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/test.mk
@@ -0,0 +1,7 @@
+# Everyone uses make for building Rust
+
+foo: bar.rlib
+	$(RUSTC) --crate-type bin --extern bar=bar.rlib
+
+%.rlib: %.rs
+	$(RUSTC) --crate-type lib $<
diff --git a/src/test/ui/unused-crate-deps/unused-aliases.stderr b/src/test/ui/unused-crate-deps/unused-aliases.stderr
index c8c6c4507b0..1142d156d0e 100644
--- a/src/test/ui/unused-crate-deps/unused-aliases.stderr
+++ b/src/test/ui/unused-crate-deps/unused-aliases.stderr
@@ -9,6 +9,7 @@ note: the lint level is defined here
    |
 LL | #![warn(unused_crate_dependencies)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: remove unnecessary dependency `barbar`
 
 warning: 1 warning emitted
 
diff --git a/src/test/ui/unused-crate-deps/warn-attr.stderr b/src/test/ui/unused-crate-deps/warn-attr.stderr
index 0d38315704b..29667d9525c 100644
--- a/src/test/ui/unused-crate-deps/warn-attr.stderr
+++ b/src/test/ui/unused-crate-deps/warn-attr.stderr
@@ -9,6 +9,7 @@ note: the lint level is defined here
    |
 LL | #![warn(unused_crate_dependencies)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: remove unnecessary dependency `bar`
 
 warning: 1 warning emitted
 
diff --git a/src/test/ui/unused-crate-deps/warn-cmdline-static.stderr b/src/test/ui/unused-crate-deps/warn-cmdline-static.stderr
index 65956461d64..2c0c9215129 100644
--- a/src/test/ui/unused-crate-deps/warn-cmdline-static.stderr
+++ b/src/test/ui/unused-crate-deps/warn-cmdline-static.stderr
@@ -5,6 +5,7 @@ LL | fn main() {}
    | ^
    |
    = note: requested on the command line with `-W unused-crate-dependencies`
+   = help: remove unnecessary dependency `bar`
 
 warning: 1 warning emitted
 
diff --git a/src/test/ui/unused-crate-deps/warn-cmdline.stderr b/src/test/ui/unused-crate-deps/warn-cmdline.stderr
index ea675ba9a1e..2cd49218f5a 100644
--- a/src/test/ui/unused-crate-deps/warn-cmdline.stderr
+++ b/src/test/ui/unused-crate-deps/warn-cmdline.stderr
@@ -5,6 +5,7 @@ LL | fn main() {}
    | ^
    |
    = note: requested on the command line with `-W unused-crate-dependencies`
+   = help: remove unnecessary dependency `bar`
 
 warning: 1 warning emitted