diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 500af5fc772..14bc19dffd5 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -57,6 +57,8 @@ pub struct Session { pub crate_metadata: RefCell>, pub features: RefCell, + pub delayed_span_bug: RefCell>, + /// The maximum recursion limit for potentially infinitely recursive /// operations such as auto-dereference and monomorphization. pub recursion_limit: Cell, @@ -114,7 +116,15 @@ impl Session { self.diagnostic().handler().has_errors() } pub fn abort_if_errors(&self) { - self.diagnostic().handler().abort_if_errors() + self.diagnostic().handler().abort_if_errors(); + + let delayed_bug = self.delayed_span_bug.borrow(); + match *delayed_bug { + Some((span, ref errmsg)) => { + self.diagnostic().span_bug(span, errmsg); + }, + _ => {} + } } pub fn span_warn(&self, sp: Span, msg: &str) { if self.can_print_warnings { @@ -171,6 +181,11 @@ impl Session { None => self.bug(msg), } } + /// Delay a span_bug() call until abort_if_errors() + pub fn delay_span_bug(&self, sp: Span, msg: &str) { + let mut delayed = self.delayed_span_bug.borrow_mut(); + *delayed = Some((sp, msg.to_string())); + } pub fn span_bug(&self, sp: Span, msg: &str) -> ! { self.diagnostic().span_bug(sp, msg) } @@ -402,6 +417,7 @@ pub fn build_session_(sopts: config::Options, plugin_llvm_passes: RefCell::new(Vec::new()), crate_types: RefCell::new(Vec::new()), crate_metadata: RefCell::new(Vec::new()), + delayed_span_bug: RefCell::new(None), features: RefCell::new(feature_gate::Features::new()), recursion_limit: Cell::new(64), can_print_warnings: can_print_warnings diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 9554e6ad8aa..55ad52dab95 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -544,7 +544,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { if tcx.sess.has_errors() { // cannot run dropck; okay b/c in error state anyway. } else { - tcx.sess.span_bug(expr.span, "cat_expr_unadjusted Errd"); + tcx.sess.delay_span_bug(expr.span, "cat_expr Errd"); } } } @@ -565,7 +565,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { if tcx.sess.has_errors() { // cannot run dropck; okay b/c in error state anyway. } else { - tcx.sess.span_bug(expr.span, "cat_expr Errd"); + tcx.sess.delay_span_bug(expr.span, "cat_expr Errd"); } } } diff --git a/src/test/compile-fail/typeck-before-dropck-bug.rs b/src/test/compile-fail/typeck-before-dropck-bug.rs new file mode 100644 index 00000000000..04ee993c040 --- /dev/null +++ b/src/test/compile-fail/typeck-before-dropck-bug.rs @@ -0,0 +1,31 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { } + +// Before these errors would ICE as "cat_expr Errd" because the errors +// were unknown when the bug was triggered. + +fn unconstrained_type() { + []; + //~^ ERROR cannot determine a type for this expression: unconstrained type +} + +fn invalid_impl_within_scope() { + { + use std::ops::Deref; + struct Something; + + impl Deref for Something {} + //~^ ERROR not all trait items implemented, missing: `Target`, `deref` + + *Something + }; +}