Skip to content

Commit 25f6d69

Browse files
committed
Modify query live_symbols_and_ignored_derived_traits
Now the query returns Result, because we need to track ErrorGuaranteed in case visits return earlier by tainted_by_errors. Signed-off-by: Shunpoco <[email protected]>
1 parent 4d6f480 commit 25f6d69

File tree

3 files changed

+76
-47
lines changed

3 files changed

+76
-47
lines changed

compiler/rustc_middle/src/query/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,10 +1200,10 @@ rustc_queries! {
12001200
/// Return the live symbols in the crate for dead code check.
12011201
///
12021202
/// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone).
1203-
query live_symbols_and_ignored_derived_traits(_: ()) -> &'tcx (
1203+
query live_symbols_and_ignored_derived_traits(_: ()) -> &'tcx Result<(
12041204
LocalDefIdSet,
12051205
LocalDefIdMap<FxIndexSet<DefId>>,
1206-
) {
1206+
), ErrorGuaranteed> {
12071207
arena_cache
12081208
desc { "finding live symbols in crate" }
12091209
}

compiler/rustc_passes/src/dead.rs

Lines changed: 72 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
// is dead.
55

66
use std::mem;
7+
use std::ops::ControlFlow;
78

89
use hir::def_id::{LocalDefIdMap, LocalDefIdSet};
910
use rustc_abi::FieldIdx;
1011
use rustc_data_structures::fx::FxIndexSet;
11-
use rustc_errors::MultiSpan;
12+
use rustc_errors::{ErrorGuaranteed, MultiSpan};
1213
use rustc_hir::def::{CtorOf, DefKind, Res};
1314
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
1415
use rustc_hir::intravisit::{self, Visitor};
@@ -178,12 +179,12 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
178179
.iter()
179180
.any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(_)))
180181
{
181-
self.visit_expr(expr);
182+
let _ = self.visit_expr(expr);
182183
} else if let hir::ExprKind::Field(base, ..) = expr.kind {
183184
// Ignore write to field
184185
self.handle_assign(base);
185186
} else {
186-
self.visit_expr(expr);
187+
let _ = self.visit_expr(expr);
187188
}
188189
}
189190

@@ -318,7 +319,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
318319
}
319320
}
320321

321-
fn mark_live_symbols(&mut self) {
322+
fn mark_live_symbols(&mut self) -> <MarkSymbolVisitor<'tcx> as Visitor<'tcx>>::Result {
322323
while let Some(work) = self.worklist.pop() {
323324
let (mut id, comes_from_allow_expect) = work;
324325

@@ -366,8 +367,13 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
366367
continue;
367368
}
368369

369-
self.visit_node(self.tcx.hir_node_by_def_id(id));
370+
let visit_result = self.visit_node(self.tcx.hir_node_by_def_id(id));
371+
if visit_result.is_break() {
372+
return visit_result;
373+
}
370374
}
375+
376+
ControlFlow::Continue(())
371377
}
372378

373379
/// Automatically generated items marked with `rustc_trivial_field_reads`
@@ -395,19 +401,22 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
395401
false
396402
}
397403

398-
fn visit_node(&mut self, node: Node<'tcx>) {
404+
fn visit_node(
405+
&mut self,
406+
node: Node<'tcx>,
407+
) -> <MarkSymbolVisitor<'tcx> as Visitor<'tcx>>::Result {
399408
if let Node::ImplItem(hir::ImplItem { owner_id, .. }) = node
400409
&& self.should_ignore_item(owner_id.to_def_id())
401410
{
402-
return;
411+
return ControlFlow::Continue(());
403412
}
404413

405414
let unconditionally_treated_fields_as_live =
406415
self.repr_unconditionally_treats_fields_as_live;
407416
let had_repr_simd = self.repr_has_repr_simd;
408417
self.repr_unconditionally_treats_fields_as_live = false;
409418
self.repr_has_repr_simd = false;
410-
match node {
419+
let walk_result = match node {
411420
Node::Item(item) => match item.kind {
412421
hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
413422
let def = self.tcx.adt_def(item.owner_id);
@@ -417,7 +426,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
417426

418427
intravisit::walk_item(self, item)
419428
}
420-
hir::ItemKind::ForeignMod { .. } => {}
429+
hir::ItemKind::ForeignMod { .. } => ControlFlow::Continue(()),
421430
hir::ItemKind::Trait(.., trait_item_refs) => {
422431
// mark assoc ty live if the trait is live
423432
for trait_item in trait_item_refs {
@@ -435,7 +444,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
435444
if let Some(trait_id) = self.tcx.trait_of_assoc(trait_item_id) {
436445
self.check_def_id(trait_id);
437446
}
438-
intravisit::walk_trait_item(self, trait_item);
447+
intravisit::walk_trait_item(self, trait_item)
439448
}
440449
Node::ImplItem(impl_item) => {
441450
let item = self.tcx.local_parent(impl_item.owner_id.def_id);
@@ -456,16 +465,16 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
456465
_ => {}
457466
}
458467
}
459-
intravisit::walk_impl_item(self, impl_item);
460-
}
461-
Node::ForeignItem(foreign_item) => {
462-
intravisit::walk_foreign_item(self, foreign_item);
468+
intravisit::walk_impl_item(self, impl_item)
463469
}
470+
Node::ForeignItem(foreign_item) => intravisit::walk_foreign_item(self, foreign_item),
464471
Node::OpaqueTy(opaq) => intravisit::walk_opaque_ty(self, opaq),
465-
_ => {}
466-
}
472+
_ => ControlFlow::Continue(()),
473+
};
467474
self.repr_has_repr_simd = had_repr_simd;
468475
self.repr_unconditionally_treats_fields_as_live = unconditionally_treated_fields_as_live;
476+
477+
walk_result
469478
}
470479

471480
fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) {
@@ -520,21 +529,25 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
520529
}
521530

522531
impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
523-
fn visit_nested_body(&mut self, body: hir::BodyId) {
532+
type Result = ControlFlow<ErrorGuaranteed>;
533+
534+
fn visit_nested_body(&mut self, body: hir::BodyId) -> Self::Result {
524535
let typeck_results = self.tcx.typeck_body(body);
525536

526537
// The result shouldn't be tainted, otherwise it will cause ICE.
527-
if typeck_results.tainted_by_errors.is_some() {
528-
return;
538+
if let Some(guar) = typeck_results.tainted_by_errors {
539+
return ControlFlow::Break(guar);
529540
}
530541

531542
let old_maybe_typeck_results = self.maybe_typeck_results.replace(typeck_results);
532543
let body = self.tcx.hir_body(body);
533-
self.visit_body(body);
544+
let result = self.visit_body(body);
534545
self.maybe_typeck_results = old_maybe_typeck_results;
546+
547+
result
535548
}
536549

537-
fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>) {
550+
fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>) -> Self::Result {
538551
let tcx = self.tcx;
539552
let unconditionally_treat_fields_as_live = self.repr_unconditionally_treats_fields_as_live;
540553
let has_repr_simd = self.repr_has_repr_simd;
@@ -551,10 +564,10 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
551564
});
552565
self.live_symbols.extend(live_fields);
553566

554-
intravisit::walk_struct_def(self, def);
567+
intravisit::walk_struct_def(self, def)
555568
}
556569

557-
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
570+
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result {
558571
match expr.kind {
559572
hir::ExprKind::Path(ref qpath @ QPath::TypeRelative(..)) => {
560573
let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
@@ -590,20 +603,22 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
590603
_ => (),
591604
}
592605

593-
intravisit::walk_expr(self, expr);
606+
intravisit::walk_expr(self, expr)
594607
}
595608

596-
fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
609+
fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> Self::Result {
597610
// Inside the body, ignore constructions of variants
598611
// necessary for the pattern to match. Those construction sites
599612
// can't be reached unless the variant is constructed elsewhere.
600613
let len = self.ignore_variant_stack.len();
601614
self.ignore_variant_stack.extend(arm.pat.necessary_variants());
602-
intravisit::walk_arm(self, arm);
615+
let result = intravisit::walk_arm(self, arm);
603616
self.ignore_variant_stack.truncate(len);
617+
618+
result
604619
}
605620

606-
fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
621+
fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Self::Result {
607622
self.in_pat = true;
608623
match pat.kind {
609624
PatKind::Struct(ref path, fields, _) => {
@@ -617,11 +632,13 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
617632
_ => (),
618633
}
619634

620-
intravisit::walk_pat(self, pat);
635+
let result = intravisit::walk_pat(self, pat);
621636
self.in_pat = false;
637+
638+
result
622639
}
623640

624-
fn visit_pat_expr(&mut self, expr: &'tcx rustc_hir::PatExpr<'tcx>) {
641+
fn visit_pat_expr(&mut self, expr: &'tcx rustc_hir::PatExpr<'tcx>) -> Self::Result {
625642
match &expr.kind {
626643
rustc_hir::PatExprKind::Path(qpath) => {
627644
// mark the type of variant live when meeting E::V in expr
@@ -634,37 +651,41 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
634651
}
635652
_ => {}
636653
}
637-
intravisit::walk_pat_expr(self, expr);
654+
intravisit::walk_pat_expr(self, expr)
638655
}
639656

640-
fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) {
657+
fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) -> Self::Result {
641658
self.handle_res(path.res);
642-
intravisit::walk_path(self, path);
659+
intravisit::walk_path(self, path)
643660
}
644661

645-
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
662+
fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) -> Self::Result {
646663
// When inline const blocks are used in pattern position, paths
647664
// referenced by it should be considered as used.
648665
let in_pat = mem::replace(&mut self.in_pat, false);
649666

650667
self.live_symbols.insert(c.def_id);
651-
intravisit::walk_anon_const(self, c);
668+
let result = intravisit::walk_anon_const(self, c);
652669

653670
self.in_pat = in_pat;
671+
672+
result
654673
}
655674

656-
fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) {
675+
fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) -> Self::Result {
657676
// When inline const blocks are used in pattern position, paths
658677
// referenced by it should be considered as used.
659678
let in_pat = mem::replace(&mut self.in_pat, false);
660679

661680
self.live_symbols.insert(c.def_id);
662-
intravisit::walk_inline_const(self, c);
681+
let result = intravisit::walk_inline_const(self, c);
663682

664683
self.in_pat = in_pat;
684+
685+
result
665686
}
666687

667-
fn visit_trait_ref(&mut self, t: &'tcx hir::TraitRef<'tcx>) {
688+
fn visit_trait_ref(&mut self, t: &'tcx hir::TraitRef<'tcx>) -> Self::Result {
668689
if let Some(trait_def_id) = t.path.res.opt_def_id()
669690
&& let Some(segment) = t.path.segments.last()
670691
&& let Some(args) = segment.args
@@ -686,7 +707,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
686707
}
687708
}
688709

689-
intravisit::walk_trait_ref(self, t);
710+
intravisit::walk_trait_ref(self, t)
690711
}
691712
}
692713

@@ -833,7 +854,7 @@ fn create_and_seed_worklist(
833854
fn live_symbols_and_ignored_derived_traits(
834855
tcx: TyCtxt<'_>,
835856
(): (),
836-
) -> (LocalDefIdSet, LocalDefIdMap<FxIndexSet<DefId>>) {
857+
) -> Result<(LocalDefIdSet, LocalDefIdMap<FxIndexSet<DefId>>), ErrorGuaranteed> {
837858
let (worklist, mut unsolved_items) = create_and_seed_worklist(tcx);
838859
let mut symbol_visitor = MarkSymbolVisitor {
839860
worklist,
@@ -847,7 +868,9 @@ fn live_symbols_and_ignored_derived_traits(
847868
ignore_variant_stack: vec![],
848869
ignored_derived_traits: Default::default(),
849870
};
850-
symbol_visitor.mark_live_symbols();
871+
if let ControlFlow::Break(guar) = symbol_visitor.mark_live_symbols() {
872+
return Err(guar);
873+
}
851874

852875
// We have marked the primary seeds as live. We now need to process unsolved items from traits
853876
// and trait impls: add them to the work list if the trait or the implemented type is live.
@@ -861,14 +884,16 @@ fn live_symbols_and_ignored_derived_traits(
861884
symbol_visitor
862885
.worklist
863886
.extend(items_to_check.drain(..).map(|id| (id, ComesFromAllowExpect::No)));
864-
symbol_visitor.mark_live_symbols();
887+
if let ControlFlow::Break(guar) = symbol_visitor.mark_live_symbols() {
888+
return Err(guar);
889+
}
865890

866891
items_to_check.extend(unsolved_items.extract_if(.., |&mut local_def_id| {
867892
symbol_visitor.check_impl_or_impl_item_live(local_def_id)
868893
}));
869894
}
870895

871-
(symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits)
896+
Ok((symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits))
872897
}
873898

874899
struct DeadItem {
@@ -1148,7 +1173,11 @@ impl<'tcx> DeadVisitor<'tcx> {
11481173
}
11491174

11501175
fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
1151-
let (live_symbols, ignored_derived_traits) = tcx.live_symbols_and_ignored_derived_traits(());
1176+
let live_symbols_result = tcx.live_symbols_and_ignored_derived_traits(());
1177+
if live_symbols_result.is_err() {
1178+
return;
1179+
}
1180+
let (live_symbols, ignored_derived_traits) = live_symbols_result.as_ref().unwrap();
11521181
let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits };
11531182

11541183
let module_items = tcx.hir_module_items(module);

tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
error: constant evaluation is taking a long time
2-
--> $DIR/do-not-ice-long-constant-evaluation-in-for-loop.rs:4:14
2+
--> $DIR/do-not-ice-long-constant-evaluation-in-for-loop.rs:9:14
33
|
44
LL | [(); loop {}];
55
| ^^^^^^^
66
|
77
= note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
88
If your compilation actually takes a long time, you can safely allow the lint.
99
help: the constant being evaluated
10-
--> $DIR/do-not-ice-long-constant-evaluation-in-for-loop.rs:4:14
10+
--> $DIR/do-not-ice-long-constant-evaluation-in-for-loop.rs:9:14
1111
|
1212
LL | [(); loop {}];
1313
| ^^^^^^^

0 commit comments

Comments
 (0)