Skip to content

Commit 01be6dd

Browse files
committed
Merge branch 'master' of github.com:rust-lang/rust into issue-83852
2 parents 82b2863 + c755ee4 commit 01be6dd

File tree

72 files changed

+898
-505
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+898
-505
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -5308,6 +5308,7 @@ name = "tidy"
53085308
version = "0.1.0"
53095309
dependencies = [
53105310
"cargo_metadata 0.11.1",
5311+
"crossbeam-utils 0.8.0",
53115312
"lazy_static",
53125313
"regex",
53135314
"walkdir",

compiler/rustc_builtin_macros/src/derive.rs

+32-25
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::cfg_eval::cfg_eval;
22

3-
use rustc_ast::{self as ast, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
3+
use rustc_ast::{self as ast, attr, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
44
use rustc_errors::{struct_span_err, Applicability};
55
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
66
use rustc_feature::AttributeTemplate;
@@ -26,32 +26,39 @@ impl MultiItemModifier for Expander {
2626
return ExpandResult::Ready(vec![item]);
2727
}
2828

29-
let template =
30-
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
31-
let attr = ecx.attribute(meta_item.clone());
32-
validate_attr::check_builtin_attribute(&sess.parse_sess, &attr, sym::derive, template);
29+
let result =
30+
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
31+
let template =
32+
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
33+
let attr = attr::mk_attr_outer(meta_item.clone());
34+
validate_attr::check_builtin_attribute(
35+
&sess.parse_sess,
36+
&attr,
37+
sym::derive,
38+
template,
39+
);
3340

34-
let derives: Vec<_> = attr
35-
.meta_item_list()
36-
.unwrap_or_default()
37-
.into_iter()
38-
.filter_map(|nested_meta| match nested_meta {
39-
NestedMetaItem::MetaItem(meta) => Some(meta),
40-
NestedMetaItem::Literal(lit) => {
41-
// Reject `#[derive("Debug")]`.
42-
report_unexpected_literal(sess, &lit);
43-
None
44-
}
45-
})
46-
.map(|meta| {
47-
// Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths.
48-
report_path_args(sess, &meta);
49-
meta.path
50-
})
51-
.collect();
41+
attr.meta_item_list()
42+
.unwrap_or_default()
43+
.into_iter()
44+
.filter_map(|nested_meta| match nested_meta {
45+
NestedMetaItem::MetaItem(meta) => Some(meta),
46+
NestedMetaItem::Literal(lit) => {
47+
// Reject `#[derive("Debug")]`.
48+
report_unexpected_literal(sess, &lit);
49+
None
50+
}
51+
})
52+
.map(|meta| {
53+
// Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths.
54+
report_path_args(sess, &meta);
55+
meta.path
56+
})
57+
.map(|path| (path, None))
58+
.collect()
59+
});
5260

53-
// FIXME: Try to cache intermediate results to avoid collecting same paths multiple times.
54-
match ecx.resolver.resolve_derives(ecx.current_expansion.id, derives, ecx.force_mode) {
61+
match result {
5562
Ok(()) => ExpandResult::Ready(cfg_eval(ecx, item)),
5663
Err(Indeterminate) => ExpandResult::Retry(item),
5764
}

compiler/rustc_errors/src/emitter.rs

+3
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ pub trait Emitter {
195195

196196
fn emit_future_breakage_report(&mut self, _diags: Vec<(FutureBreakage, Diagnostic)>) {}
197197

198+
/// Emit list of unused externs
199+
fn emit_unused_externs(&mut self, _lint_level: &str, _unused_externs: &[&str]) {}
200+
198201
/// Checks if should show explanations about "rustc --explain"
199202
fn should_show_explain(&self) -> bool {
200203
true

compiler/rustc_errors/src/json.rs

+25
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,19 @@ impl Emitter for JsonEmitter {
159159
}
160160
}
161161

162+
fn emit_unused_externs(&mut self, lint_level: &str, unused_externs: &[&str]) {
163+
let data = UnusedExterns { lint_level, unused_extern_names: unused_externs };
164+
let result = if self.pretty {
165+
writeln!(&mut self.dst, "{}", as_pretty_json(&data))
166+
} else {
167+
writeln!(&mut self.dst, "{}", as_json(&data))
168+
}
169+
.and_then(|_| self.dst.flush());
170+
if let Err(e) = result {
171+
panic!("failed to print unused externs: {:?}", e);
172+
}
173+
}
174+
162175
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
163176
Some(&self.sm)
164177
}
@@ -322,6 +335,18 @@ struct FutureIncompatReport {
322335
future_incompat_report: Vec<FutureBreakageItem>,
323336
}
324337

338+
// NOTE: Keep this in sync with the equivalent structs in rustdoc's
339+
// doctest component (as well as cargo).
340+
// We could unify this struct the one in rustdoc but they have different
341+
// ownership semantics, so doing so would create wasteful allocations.
342+
#[derive(Encodable)]
343+
struct UnusedExterns<'a, 'b, 'c> {
344+
/// The severity level of the unused dependencies lint
345+
lint_level: &'a str,
346+
/// List of unused externs by their names.
347+
unused_extern_names: &'b [&'c str],
348+
}
349+
325350
impl Diagnostic {
326351
fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnostic {
327352
let sugg = diag.suggestions.iter().map(|sugg| Diagnostic {

compiler/rustc_errors/src/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,10 @@ impl Handler {
765765
self.inner.borrow_mut().emitter.emit_future_breakage_report(diags)
766766
}
767767

768+
pub fn emit_unused_externs(&self, lint_level: &str, unused_externs: &[&str]) {
769+
self.inner.borrow_mut().emit_unused_externs(lint_level, unused_externs)
770+
}
771+
768772
pub fn delay_as_bug(&self, diagnostic: Diagnostic) {
769773
self.inner.borrow_mut().delay_as_bug(diagnostic)
770774
}
@@ -839,6 +843,10 @@ impl HandlerInner {
839843
self.emitter.emit_artifact_notification(path, artifact_type);
840844
}
841845

846+
fn emit_unused_externs(&mut self, lint_level: &str, unused_externs: &[&str]) {
847+
self.emitter.emit_unused_externs(lint_level, unused_externs);
848+
}
849+
842850
fn treat_err_as_bug(&self) -> bool {
843851
self.flags.treat_err_as_bug.map_or(false, |c| self.err_count() >= c.get())
844852
}

compiler/rustc_expand/src/base.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,8 @@ impl SyntaxExtension {
868868
/// Error type that denotes indeterminacy.
869869
pub struct Indeterminate;
870870

871+
pub type DeriveResolutions = Vec<(ast::Path, Option<Lrc<SyntaxExtension>>)>;
872+
871873
pub trait ResolverExpand {
872874
fn next_node_id(&mut self) -> NodeId;
873875

@@ -904,15 +906,12 @@ pub trait ResolverExpand {
904906
fn resolve_derives(
905907
&mut self,
906908
expn_id: ExpnId,
907-
derives: Vec<ast::Path>,
908909
force: bool,
910+
derive_paths: &dyn Fn() -> DeriveResolutions,
909911
) -> Result<(), Indeterminate>;
910912
/// Take resolutions for paths inside the `#[derive(...)]` attribute with the given `ExpnId`
911913
/// back from resolver.
912-
fn take_derive_resolutions(
913-
&mut self,
914-
expn_id: ExpnId,
915-
) -> Option<Vec<(Lrc<SyntaxExtension>, ast::Path)>>;
914+
fn take_derive_resolutions(&mut self, expn_id: ExpnId) -> Option<DeriveResolutions>;
916915
/// Path resolution logic for `#[cfg_accessible(path)]`.
917916
fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate>;
918917
}

compiler/rustc_expand/src/expand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
515515
invocations.reserve(derives.len());
516516
derives
517517
.into_iter()
518-
.map(|(_exts, path)| {
518+
.map(|(path, _exts)| {
519519
// FIXME: Consider using the derive resolutions (`_exts`)
520520
// instead of enqueuing the derives to be resolved again later.
521521
let expn_id = ExpnId::fresh(None);

compiler/rustc_interface/src/passes.rs

+7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
1616
use rustc_hir::definitions::Definitions;
1717
use rustc_hir::Crate;
1818
use rustc_lint::LintStore;
19+
use rustc_metadata::creader::CStore;
1920
use rustc_middle::arena::Arena;
2021
use rustc_middle::dep_graph::DepGraph;
2122
use rustc_middle::middle;
@@ -831,6 +832,12 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
831832
});
832833

833834
sess.time("looking_for_derive_registrar", || proc_macro_decls::find(tcx));
835+
836+
let cstore = tcx
837+
.cstore_as_any()
838+
.downcast_ref::<CStore>()
839+
.expect("`tcx.cstore` is not a `CStore`");
840+
cstore.report_unused_deps(tcx);
834841
},
835842
{
836843
par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| {

compiler/rustc_metadata/src/creader.rs

+34-3
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ pub struct CStore {
4646
/// This map is used to verify we get no hash conflicts between
4747
/// `StableCrateId` values.
4848
stable_crate_ids: FxHashMap<StableCrateId, CrateNum>,
49+
50+
/// Unused externs of the crate
51+
unused_externs: Vec<Symbol>,
4952
}
5053

5154
pub struct CrateLoader<'a> {
@@ -190,6 +193,27 @@ impl CStore {
190193
crate fn has_global_allocator(&self) -> bool {
191194
self.has_global_allocator
192195
}
196+
197+
pub fn report_unused_deps(&self, tcx: TyCtxt<'_>) {
198+
// We put the check for the option before the lint_level_at_node call
199+
// because the call mutates internal state and introducing it
200+
// leads to some ui tests failing.
201+
if !tcx.sess.opts.json_unused_externs {
202+
return;
203+
}
204+
let level = tcx
205+
.lint_level_at_node(lint::builtin::UNUSED_CRATE_DEPENDENCIES, rustc_hir::CRATE_HIR_ID)
206+
.0;
207+
if level != lint::Level::Allow {
208+
let unused_externs =
209+
self.unused_externs.iter().map(|ident| ident.to_ident_string()).collect::<Vec<_>>();
210+
let unused_externs = unused_externs.iter().map(String::as_str).collect::<Vec<&str>>();
211+
tcx.sess
212+
.parse_sess
213+
.span_diagnostic
214+
.emit_unused_externs(level.as_str(), &unused_externs);
215+
}
216+
}
193217
}
194218

195219
impl<'a> CrateLoader<'a> {
@@ -217,6 +241,7 @@ impl<'a> CrateLoader<'a> {
217241
allocator_kind: None,
218242
has_global_allocator: false,
219243
stable_crate_ids,
244+
unused_externs: Vec::new(),
220245
},
221246
used_extern_options: Default::default(),
222247
}
@@ -904,11 +929,17 @@ impl<'a> CrateLoader<'a> {
904929
// Don't worry about pathless `--extern foo` sysroot references
905930
continue;
906931
}
907-
if self.used_extern_options.contains(&Symbol::intern(name)) {
932+
let name_interned = Symbol::intern(name);
933+
if self.used_extern_options.contains(&name_interned) {
908934
continue;
909935
}
910936

911937
// Got a real unused --extern
938+
if self.sess.opts.json_unused_externs {
939+
self.cstore.unused_externs.push(name_interned);
940+
continue;
941+
}
942+
912943
let diag = match self.sess.opts.extern_dep_specs.get(name) {
913944
Some(loc) => BuiltinLintDiagnostics::ExternDepSpec(name.clone(), loc.into()),
914945
None => {
@@ -941,9 +972,9 @@ impl<'a> CrateLoader<'a> {
941972
self.inject_allocator_crate(krate);
942973
self.inject_panic_runtime(krate);
943974

944-
info!("{:?}", CrateDump(&self.cstore));
945-
946975
self.report_unused_deps(krate);
976+
977+
info!("{:?}", CrateDump(&self.cstore));
947978
}
948979

949980
pub fn process_extern_crate(

compiler/rustc_middle/src/mir/mod.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -1482,7 +1482,7 @@ pub enum StatementKind<'tcx> {
14821482
///
14831483
/// Note that this also is emitted for regular `let` bindings to ensure that locals that are
14841484
/// never accessed still get some sanity checks for, e.g., `let x: ! = ..;`
1485-
FakeRead(FakeReadCause, Box<Place<'tcx>>),
1485+
FakeRead(Box<(FakeReadCause, Place<'tcx>)>),
14861486

14871487
/// Write the discriminant for a variant to the enum Place.
14881488
SetDiscriminant { place: Box<Place<'tcx>>, variant_index: VariantIdx },
@@ -1575,7 +1575,12 @@ pub enum FakeReadCause {
15751575

15761576
/// `let x: !; match x {}` doesn't generate any read of x so we need to
15771577
/// generate a read of x to check that it is initialized and safe.
1578-
ForMatchedPlace,
1578+
///
1579+
/// If a closure pattern matches a Place starting with an Upvar, then we introduce a
1580+
/// FakeRead for that Place outside the closure, in such a case this option would be
1581+
/// Some(closure_def_id).
1582+
/// Otherwise, the value of the optional DefId will be None.
1583+
ForMatchedPlace(Option<DefId>),
15791584

15801585
/// A fake read of the RefWithinGuard version of a bind-by-value variable
15811586
/// in a match guard to ensure that it's value hasn't change by the time
@@ -1594,7 +1599,12 @@ pub enum FakeReadCause {
15941599
/// but in some cases it can affect the borrow checker, as in #53695.
15951600
/// Therefore, we insert a "fake read" here to ensure that we get
15961601
/// appropriate errors.
1597-
ForLet,
1602+
///
1603+
/// If a closure pattern matches a Place starting with an Upvar, then we introduce a
1604+
/// FakeRead for that Place outside the closure, in such a case this option would be
1605+
/// Some(closure_def_id).
1606+
/// Otherwise, the value of the optional DefId will be None.
1607+
ForLet(Option<DefId>),
15981608

15991609
/// If we have an index expression like
16001610
///
@@ -1618,7 +1628,9 @@ impl Debug for Statement<'_> {
16181628
use self::StatementKind::*;
16191629
match self.kind {
16201630
Assign(box (ref place, ref rv)) => write!(fmt, "{:?} = {:?}", place, rv),
1621-
FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place),
1631+
FakeRead(box (ref cause, ref place)) => {
1632+
write!(fmt, "FakeRead({:?}, {:?})", cause, place)
1633+
}
16221634
Retag(ref kind, ref place) => write!(
16231635
fmt,
16241636
"Retag({}{:?})",

compiler/rustc_middle/src/mir/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ macro_rules! make_mir_visitor {
380380
) => {
381381
self.visit_assign(place, rvalue, location);
382382
}
383-
StatementKind::FakeRead(_, place) => {
383+
StatementKind::FakeRead(box (_, place)) => {
384384
self.visit_place(
385385
place,
386386
PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),

compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1728,7 +1728,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
17281728
impl<'tcx> Visitor<'tcx> for FakeReadCauseFinder<'tcx> {
17291729
fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
17301730
match statement {
1731-
Statement { kind: StatementKind::FakeRead(cause, box place), .. }
1731+
Statement { kind: StatementKind::FakeRead(box (cause, place)), .. }
17321732
if *place == self.place =>
17331733
{
17341734
self.cause = Some(*cause);

compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
515515
let block = &self.body.basic_blocks()[location.block];
516516

517517
let kind = if let Some(&Statement {
518-
kind: StatementKind::FakeRead(FakeReadCause::ForLet, _),
518+
kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), _)),
519519
..
520520
}) = block.statements.get(location.statement_index)
521521
{

compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use rustc_hir::def_id::DefId;
77
use rustc_hir::lang_items::LangItemGroup;
88
use rustc_hir::GeneratorKind;
99
use rustc_middle::mir::{
10-
AggregateKind, Constant, Field, Local, LocalInfo, LocalKind, Location, Operand, Place,
11-
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
10+
AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand,
11+
Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
1212
};
1313
use rustc_middle::ty::print::Print;
1414
use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
@@ -795,6 +795,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
795795
}
796796
}
797797

798+
// StatementKind::FakeRead only contains a def_id if they are introduced as a result
799+
// of pattern matching within a closure.
800+
if let StatementKind::FakeRead(box (cause, ref place)) = stmt.kind {
801+
match cause {
802+
FakeReadCause::ForMatchedPlace(Some(closure_def_id))
803+
| FakeReadCause::ForLet(Some(closure_def_id)) => {
804+
debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place);
805+
let places = &[Operand::Move(*place)];
806+
if let Some((args_span, generator_kind, var_span)) =
807+
self.closure_span(closure_def_id, moved_place, places)
808+
{
809+
return ClosureUse { generator_kind, args_span, var_span };
810+
}
811+
}
812+
_ => {}
813+
}
814+
}
815+
798816
let normal_ret =
799817
if moved_place.projection.iter().any(|p| matches!(p, ProjectionElem::Downcast(..))) {
800818
PatUse(stmt.source_info.span)

0 commit comments

Comments
 (0)