Skip to content

Commit 32f3fe7

Browse files
committed
add rustc_error(delay_span_bug_from_inside_query) attribute
1 parent 6299c33 commit 32f3fe7

File tree

4 files changed

+40
-4
lines changed

4 files changed

+40
-4
lines changed

src/librustc/query/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ use syntax_pos::symbol::InternedString;
2929
// Queries marked with `fatal_cycle` do not need the latter implementation,
3030
// as they will raise an fatal error on query cycles instead.
3131
rustc_queries! {
32+
Other {
33+
query trigger_delay_span_bug(key: DefId) -> () {
34+
desc { "trigger a delay span bug" }
35+
}
36+
}
37+
3238
Other {
3339
/// Records the type of every item.
3440
query type_of(key: DefId) -> Ty<'tcx> {

src/librustc_codegen_utils/lib.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,52 @@ extern crate rustc;
1919

2020
use rustc::ty::TyCtxt;
2121
use rustc::ty::query::Providers;
22-
use rustc::hir::def_id::LOCAL_CRATE;
22+
use rustc::hir::def_id::{LOCAL_CRATE, DefId};
2323
use syntax::symbol::sym;
2424

2525
pub mod link;
2626
pub mod codegen_backend;
2727
pub mod symbol_names;
2828
pub mod symbol_names_test;
2929

30+
31+
pub fn trigger_delay_span_bug(tcx: TyCtxt<'_>, key: DefId) {
32+
tcx.sess.delay_span_bug(tcx.def_span(key), "compilation successful");
33+
}
34+
3035
/// check for the #[rustc_error] annotation, which forces an
3136
/// error in codegen. This is used to write compile-fail tests
3237
/// that actually test that compilation succeeds without
3338
/// reporting an error.
3439
pub fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) {
3540
if let Some((def_id, _)) = tcx.entry_fn(LOCAL_CRATE) {
36-
if tcx.has_attr(def_id, sym::rustc_error) {
37-
tcx.sess.span_fatal(tcx.def_span(def_id), "compilation successful");
41+
let attrs = &*tcx.get_attrs(def_id);
42+
for attr in attrs {
43+
if attr.check_name(sym::rustc_error) {
44+
match attr.meta_item_list() {
45+
// check if there is a #[rustc_error(delayed)]
46+
Some(list) => {
47+
if list.iter().any(|list_item| {
48+
list_item.ident().map(|i| i.name) ==
49+
Some(sym::delay_span_bug_from_inside_query)
50+
}) {
51+
tcx.ensure().trigger_delay_span_bug(def_id);
52+
}
53+
}
54+
// bare #[rustc_error]
55+
None => {
56+
tcx.sess.span_fatal(tcx.def_span(def_id), "compilation successful");
57+
}
58+
}
59+
}
3860
}
3961
}
4062
}
4163

4264
pub fn provide(providers: &mut Providers<'_>) {
4365
crate::symbol_names::provide(providers);
66+
*providers = Providers {
67+
trigger_delay_span_bug,
68+
..*providers
69+
};
4470
}

src/libsyntax/feature_gate/builtin_attrs.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
533533
rustc_attr!(TEST, rustc_variance, Normal, template!(Word)),
534534
rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")),
535535
rustc_attr!(TEST, rustc_regions, Normal, template!(Word)),
536-
rustc_attr!(TEST, rustc_error, Whitelisted, template!(Word)),
536+
rustc_attr!(
537+
TEST, rustc_error, Whitelisted,
538+
template!(Word, List: "delay_span_bug_from_inside_query")
539+
),
537540
rustc_attr!(TEST, rustc_dump_user_substs, Whitelisted, template!(Word)),
538541
rustc_attr!(TEST, rustc_if_this_changed, Whitelisted, template!(Word, List: "DepNode")),
539542
rustc_attr!(TEST, rustc_then_this_would_need, Whitelisted, template!(List: "DepNode")),

src/libsyntax_pos/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ symbols! {
234234
default_lib_allocator,
235235
default_type_parameter_fallback,
236236
default_type_params,
237+
delay_span_bug_from_inside_query,
237238
deny,
238239
deprecated,
239240
deref,

0 commit comments

Comments
 (0)