Skip to content

Commit e7070dd

Browse files
committed
Auto merge of #44071 - alexcrichton:no-cycles, r=nikomatsakis
rustc: Start moving toward "try_get is a bug" for incremental This PR is an effort to burn down some of the work items on #42633. The basic change here was to leave the `try_get` function exposed but have it return a `DiagnosticBuilder` instead of a `CycleError`. This means that it should be a compiler bug to *not* handle the error as dropping a diagnostic should result in a complier panic. After that change it was then necessary to update the compiler's callsites of `try_get` to handle the error coming out. These were handled as: * The `sized_constraint` and `needs_drop_raw` checks take the diagnostic and defer it as a compiler bug. This was a new piece of functionality added to the error handling infrastructure, and the idea is that for both these checks a "real" compiler error should be emitted elsewhere, so it's only a bug if we don't actually emit the complier error elsewhere. * MIR inlining was updated to just ignore the diagnostic. This is being tracked by #43542 which sounded like it either already had some work underway or was planning to change regardless. * The final case, `item_path`, is still sort of up for debate. At the time of this writing this PR simply removes the invocations of `try_get` there, assuming that the query will always succeed. This turns out to be true for the test suite anyway! It sounds like, though, that this logic was intended to assist in "weird" situations like `RUST_LOG` where debug implementations can trigger at any time. This PR would therefore, however, break those implementations. I'm unfortunately sort of out of ideas on how to handle `item_path`, but other thoughts would be welcome! Closes #42633
2 parents 398aaff + c766aa4 commit e7070dd

File tree

7 files changed

+59
-33
lines changed

7 files changed

+59
-33
lines changed

src/librustc/ty/item_path.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
1313
use ty::{self, Ty, TyCtxt};
1414
use syntax::ast;
1515
use syntax::symbol::Symbol;
16-
use syntax_pos::DUMMY_SP;
1716

1817
use std::cell::Cell;
1918

@@ -222,11 +221,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
222221
let use_types = !self.is_default_impl(impl_def_id) && (!impl_def_id.is_local() || {
223222
// Otherwise, use filename/line-number if forced.
224223
let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
225-
!force_no_types && {
226-
// Otherwise, use types if we can query them without inducing a cycle.
227-
ty::queries::impl_trait_ref::try_get(self, DUMMY_SP, impl_def_id).is_ok() &&
228-
ty::queries::type_of::try_get(self, DUMMY_SP, impl_def_id).is_ok()
229-
}
224+
!force_no_types
230225
});
231226

232227
if !use_types {

src/librustc/ty/maps.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,15 @@ impl<M: QueryDescription> QueryMap<M> {
212212
}
213213
}
214214

215-
pub struct CycleError<'a, 'tcx: 'a> {
215+
struct CycleError<'a, 'tcx: 'a> {
216216
span: Span,
217217
cycle: RefMut<'a, [(Span, Query<'tcx>)]>,
218218
}
219219

220220
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
221-
pub fn report_cycle(self, CycleError { span, cycle }: CycleError) {
221+
fn report_cycle(self, CycleError { span, cycle }: CycleError)
222+
-> DiagnosticBuilder<'a>
223+
{
222224
// Subtle: release the refcell lock before invoking `describe()`
223225
// below by dropping `cycle`.
224226
let stack = cycle.to_vec();
@@ -247,8 +249,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
247249
err.note(&format!("...which then again requires {}, completing the cycle.",
248250
stack[0].1.describe(self)));
249251

250-
err.emit();
251-
});
252+
return err
253+
})
252254
}
253255

254256
fn cycle_check<F, R>(self, span: Span, query: Query<'gcx>, compute: F)
@@ -704,8 +706,11 @@ macro_rules! define_maps {
704706
}
705707

706708
pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
707-
-> Result<$V, CycleError<'a, $tcx>> {
708-
Self::try_get_with(tcx, span, key, Clone::clone)
709+
-> Result<$V, DiagnosticBuilder<'a>> {
710+
match Self::try_get_with(tcx, span, key, Clone::clone) {
711+
Ok(e) => Ok(e),
712+
Err(e) => Err(tcx.report_cycle(e)),
713+
}
709714
}
710715

711716
pub fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) {
@@ -714,7 +719,7 @@ macro_rules! define_maps {
714719

715720
match Self::try_get_with(tcx, span, key, |_| ()) {
716721
Ok(()) => {}
717-
Err(e) => tcx.report_cycle(e)
722+
Err(e) => tcx.report_cycle(e).emit(),
718723
}
719724
}
720725
})*
@@ -751,8 +756,8 @@ macro_rules! define_maps {
751756
impl<'a, $tcx, 'lcx> TyCtxtAt<'a, $tcx, 'lcx> {
752757
$($(#[$attr])*
753758
pub fn $name(self, key: $K) -> $V {
754-
queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|e| {
755-
self.report_cycle(e);
759+
queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|mut e| {
760+
e.emit();
756761
Value::from_cycle_error(self.global_tcx())
757762
})
758763
})*

src/librustc/ty/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1684,12 +1684,15 @@ impl<'a, 'gcx, 'tcx> AdtDef {
16841684
pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx [Ty<'tcx>] {
16851685
match queries::adt_sized_constraint::try_get(tcx, DUMMY_SP, self.did) {
16861686
Ok(tys) => tys,
1687-
Err(_) => {
1687+
Err(mut bug) => {
16881688
debug!("adt_sized_constraint: {:?} is recursive", self);
16891689
// This should be reported as an error by `check_representable`.
16901690
//
16911691
// Consider the type as Sized in the meanwhile to avoid
1692-
// further errors.
1692+
// further errors. Delay our `bug` diagnostic here to get
1693+
// emitted later as well in case we accidentally otherwise don't
1694+
// emit an error.
1695+
bug.delay_as_bug();
16931696
tcx.intern_type_list(&[tcx.types.err])
16941697
}
16951698
}

src/librustc/ty/util.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1069,11 +1069,15 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10691069
let needs_drop = |ty: Ty<'tcx>| -> bool {
10701070
match ty::queries::needs_drop_raw::try_get(tcx, DUMMY_SP, param_env.and(ty)) {
10711071
Ok(v) => v,
1072-
Err(_) => {
1072+
Err(mut bug) => {
10731073
// Cycles should be reported as an error by `check_representable`.
10741074
//
1075-
// Consider the type as not needing drop in the meanwhile to avoid
1076-
// further errors.
1075+
// Consider the type as not needing drop in the meanwhile to
1076+
// avoid further errors.
1077+
//
1078+
// In case we forgot to emit a bug elsewhere, delay our
1079+
// diagnostic to get emitted as a compiler bug.
1080+
bug.delay_as_bug();
10771081
false
10781082
}
10791083
}

src/librustc_errors/diagnostic_builder.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,22 @@ impl<'a> DiagnosticBuilder<'a> {
110110
// }
111111
}
112112

113+
/// Delay emission of this diagnostic as a bug.
114+
///
115+
/// This can be useful in contexts where an error indicates a bug but
116+
/// typically this only happens when other compilation errors have already
117+
/// happened. In those cases this can be used to defer emission of this
118+
/// diagnostic as a bug in the compiler only if no other errors have been
119+
/// emitted.
120+
///
121+
/// In the meantime, though, callsites are required to deal with the "bug"
122+
/// locally in whichever way makes the most sense.
123+
pub fn delay_as_bug(&mut self) {
124+
self.level = Level::Bug;
125+
*self.handler.delayed_span_bug.borrow_mut() = Some(self.diagnostic.clone());
126+
self.cancel();
127+
}
128+
113129
/// Add a span/label to be included in the resulting snippet.
114130
/// This is pushed onto the `MultiSpan` that was created when the
115131
/// diagnostic was first built. If you don't call this function at
@@ -182,8 +198,10 @@ impl<'a> DiagnosticBuilder<'a> {
182198
DiagnosticBuilder::new_diagnostic(handler, diagnostic)
183199
}
184200

185-
/// Creates a new `DiagnosticBuilder` with an already constructed diagnostic.
186-
pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> DiagnosticBuilder<'a> {
201+
/// Creates a new `DiagnosticBuilder` with an already constructed
202+
/// diagnostic.
203+
pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic)
204+
-> DiagnosticBuilder<'a> {
187205
DiagnosticBuilder { handler, diagnostic }
188206
}
189207
}

src/librustc_errors/lib.rs

+6-10
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ pub struct Handler {
272272
pub can_emit_warnings: bool,
273273
treat_err_as_bug: bool,
274274
continue_after_error: Cell<bool>,
275-
delayed_span_bug: RefCell<Option<(MultiSpan, String)>>,
275+
delayed_span_bug: RefCell<Option<Diagnostic>>,
276276
tracked_diagnostics: RefCell<Option<Vec<Diagnostic>>>,
277277
}
278278

@@ -439,8 +439,9 @@ impl Handler {
439439
if self.treat_err_as_bug {
440440
self.span_bug(sp, msg);
441441
}
442-
let mut delayed = self.delayed_span_bug.borrow_mut();
443-
*delayed = Some((sp.into(), msg.to_string()));
442+
let mut diagnostic = Diagnostic::new(Level::Bug, msg);
443+
diagnostic.set_span(sp.into());
444+
*self.delayed_span_bug.borrow_mut() = Some(diagnostic);
444445
}
445446
pub fn span_bug_no_panic<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
446447
self.emit(&sp.into(), msg, Bug);
@@ -507,14 +508,9 @@ impl Handler {
507508
let s;
508509
match self.err_count.get() {
509510
0 => {
510-
let delayed_bug = self.delayed_span_bug.borrow();
511-
match *delayed_bug {
512-
Some((ref span, ref errmsg)) => {
513-
self.span_bug(span.clone(), errmsg);
514-
}
515-
_ => {}
511+
if let Some(bug) = self.delayed_span_bug.borrow_mut().take() {
512+
DiagnosticBuilder::new_diagnostic(self, bug).emit();
516513
}
517-
518514
return;
519515
}
520516
1 => s = "aborting due to previous error".to_string(),

src/librustc_mir/transform/inline.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,13 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
115115
Ok(ref callee_mir) if self.should_inline(callsite, callee_mir) => {
116116
callee_mir.subst(self.tcx, callsite.substs)
117117
}
118+
Ok(_) => continue,
118119

119-
_ => continue,
120+
Err(mut bug) => {
121+
// FIXME(#43542) shouldn't have to cancel an error
122+
bug.cancel();
123+
continue
124+
}
120125
};
121126

122127
let start = caller_mir.basic_blocks().len();

0 commit comments

Comments
 (0)