Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc: Start moving toward "try_get is a bug" for incremental #44071

Merged
merged 6 commits into from
Aug 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions src/librustc/ty/item_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use ty::{self, Ty, TyCtxt};
use syntax::ast;
use syntax::symbol::Symbol;
use syntax_pos::DUMMY_SP;

use std::cell::Cell;

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

if !use_types {
Expand Down
23 changes: 14 additions & 9 deletions src/librustc/ty/maps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,13 +212,15 @@ impl<M: QueryDescription> QueryMap<M> {
}
}

pub struct CycleError<'a, 'tcx: 'a> {
struct CycleError<'a, 'tcx: 'a> {
span: Span,
cycle: RefMut<'a, [(Span, Query<'tcx>)]>,
}

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

err.emit();
});
return err
})
}

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

pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
-> Result<$V, CycleError<'a, $tcx>> {
Self::try_get_with(tcx, span, key, Clone::clone)
-> Result<$V, DiagnosticBuilder<'a>> {
match Self::try_get_with(tcx, span, key, Clone::clone) {
Ok(e) => Ok(e),
Err(e) => Err(tcx.report_cycle(e)),
}
}

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

match Self::try_get_with(tcx, span, key, |_| ()) {
Ok(()) => {}
Err(e) => tcx.report_cycle(e)
Err(e) => tcx.report_cycle(e).emit(),
}
}
})*
Expand Down Expand Up @@ -751,8 +756,8 @@ macro_rules! define_maps {
impl<'a, $tcx, 'lcx> TyCtxtAt<'a, $tcx, 'lcx> {
$($(#[$attr])*
pub fn $name(self, key: $K) -> $V {
queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|e| {
self.report_cycle(e);
queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|mut e| {
e.emit();
Value::from_cycle_error(self.global_tcx())
})
})*
Expand Down
7 changes: 5 additions & 2 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1684,12 +1684,15 @@ impl<'a, 'gcx, 'tcx> AdtDef {
pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx [Ty<'tcx>] {
match queries::adt_sized_constraint::try_get(tcx, DUMMY_SP, self.did) {
Ok(tys) => tys,
Err(_) => {
Err(mut bug) => {
debug!("adt_sized_constraint: {:?} is recursive", self);
// This should be reported as an error by `check_representable`.
//
// Consider the type as Sized in the meanwhile to avoid
// further errors.
// further errors. Delay our `bug` diagnostic here to get
// emitted later as well in case we accidentally otherwise don't
// emit an error.
bug.delay_as_bug();
tcx.intern_type_list(&[tcx.types.err])
}
}
Expand Down
10 changes: 7 additions & 3 deletions src/librustc/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1069,11 +1069,15 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let needs_drop = |ty: Ty<'tcx>| -> bool {
match ty::queries::needs_drop_raw::try_get(tcx, DUMMY_SP, param_env.and(ty)) {
Ok(v) => v,
Err(_) => {
Err(mut bug) => {
// Cycles should be reported as an error by `check_representable`.
//
// Consider the type as not needing drop in the meanwhile to avoid
// further errors.
// Consider the type as not needing drop in the meanwhile to
// avoid further errors.
//
// In case we forgot to emit a bug elsewhere, delay our
// diagnostic to get emitted as a compiler bug.
bug.delay_as_bug();
false
}
}
Expand Down
22 changes: 20 additions & 2 deletions src/librustc_errors/diagnostic_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,22 @@ impl<'a> DiagnosticBuilder<'a> {
// }
}

/// Delay emission of this diagnostic as a bug.
///
/// This can be useful in contexts where an error indicates a bug but
/// typically this only happens when other compilation errors have already
/// happened. In those cases this can be used to defer emission of this
/// diagnostic as a bug in the compiler only if no other errors have been
/// emitted.
///
/// In the meantime, though, callsites are required to deal with the "bug"
/// locally in whichever way makes the most sense.
pub fn delay_as_bug(&mut self) {
self.level = Level::Bug;
*self.handler.delayed_span_bug.borrow_mut() = Some(self.diagnostic.clone());
self.cancel();
}

/// Add a span/label to be included in the resulting snippet.
/// This is pushed onto the `MultiSpan` that was created when the
/// diagnostic was first built. If you don't call this function at
Expand Down Expand Up @@ -182,8 +198,10 @@ impl<'a> DiagnosticBuilder<'a> {
DiagnosticBuilder::new_diagnostic(handler, diagnostic)
}

/// Creates a new `DiagnosticBuilder` with an already constructed diagnostic.
pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> DiagnosticBuilder<'a> {
/// Creates a new `DiagnosticBuilder` with an already constructed
/// diagnostic.
pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic)
-> DiagnosticBuilder<'a> {
DiagnosticBuilder { handler, diagnostic }
}
}
Expand Down
16 changes: 6 additions & 10 deletions src/librustc_errors/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ pub struct Handler {
pub can_emit_warnings: bool,
treat_err_as_bug: bool,
continue_after_error: Cell<bool>,
delayed_span_bug: RefCell<Option<(MultiSpan, String)>>,
delayed_span_bug: RefCell<Option<Diagnostic>>,
tracked_diagnostics: RefCell<Option<Vec<Diagnostic>>>,
}

Expand Down Expand Up @@ -442,8 +442,9 @@ impl Handler {
if self.treat_err_as_bug {
self.span_bug(sp, msg);
}
let mut delayed = self.delayed_span_bug.borrow_mut();
*delayed = Some((sp.into(), msg.to_string()));
let mut diagnostic = Diagnostic::new(Level::Bug, msg);
diagnostic.set_span(sp.into());
*self.delayed_span_bug.borrow_mut() = Some(diagnostic);
}
pub fn span_bug_no_panic<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.emit(&sp.into(), msg, Bug);
Expand Down Expand Up @@ -510,14 +511,9 @@ impl Handler {
let s;
match self.err_count.get() {
0 => {
let delayed_bug = self.delayed_span_bug.borrow();
match *delayed_bug {
Some((ref span, ref errmsg)) => {
self.span_bug(span.clone(), errmsg);
}
_ => {}
if let Some(bug) = self.delayed_span_bug.borrow_mut().take() {
DiagnosticBuilder::new_diagnostic(self, bug).emit();
}

return;
}
1 => s = "aborting due to previous error".to_string(),
Expand Down
7 changes: 6 additions & 1 deletion src/librustc_mir/transform/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,13 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
Ok(ref callee_mir) if self.should_inline(callsite, callee_mir) => {
callee_mir.subst(self.tcx, callsite.substs)
}
Ok(_) => continue,

_ => continue,
Err(mut bug) => {
// FIXME(#43542) shouldn't have to cancel an error
bug.cancel();
continue
}
};

let start = caller_mir.basic_blocks().len();
Expand Down