Skip to content

Commit b49fbc9

Browse files
committed
expand: Tell built-in macros whether we are currently in forced expansion mode
1 parent 7e20323 commit b49fbc9

File tree

5 files changed

+42
-40
lines changed

5 files changed

+42
-40
lines changed

compiler/rustc_builtin_macros/src/cfg_accessible.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Implementation of the `#[cfg_accessible(path)]` attribute macro.
22
33
use rustc_ast as ast;
4-
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
4+
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
55
use rustc_feature::AttributeTemplate;
66
use rustc_parse::validate_attr;
77
use rustc_span::symbol::sym;
@@ -31,7 +31,7 @@ impl MultiItemModifier for Expander {
3131
fn expand(
3232
&self,
3333
ecx: &mut ExtCtxt<'_>,
34-
_span: Span,
34+
span: Span,
3535
meta_item: &ast::MetaItem,
3636
item: Annotatable,
3737
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
@@ -49,11 +49,14 @@ impl MultiItemModifier for Expander {
4949
None => return ExpandResult::Ready(Vec::new()),
5050
};
5151

52-
let failure_msg = "cannot determine whether the path is accessible or not";
5352
match ecx.resolver.cfg_accessible(ecx.current_expansion.id, path) {
5453
Ok(true) => ExpandResult::Ready(vec![item]),
5554
Ok(false) => ExpandResult::Ready(Vec::new()),
56-
Err(_) => ExpandResult::Retry(item, failure_msg.into()),
55+
Err(Indeterminate) if ecx.force_mode => {
56+
ecx.span_err(span, "cannot determine whether the path is accessible or not");
57+
ExpandResult::Ready(vec![item])
58+
}
59+
Err(Indeterminate) => ExpandResult::Retry(item),
5760
}
5861
}
5962
}

compiler/rustc_expand/src/base.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,7 @@ pub enum ExpandResult<T, U> {
251251
/// Expansion produced a result (possibly dummy).
252252
Ready(T),
253253
/// Expansion could not produce a result and needs to be retried.
254-
/// The string is an explanation that will be printed if we are stuck in an infinite retry loop.
255-
Retry(U, String),
254+
Retry(U),
256255
}
257256

258257
// `meta_item` is the attribute, and `item` is the item being modified.
@@ -919,6 +918,9 @@ pub struct ExtCtxt<'a> {
919918
pub root_path: PathBuf,
920919
pub resolver: &'a mut dyn ResolverExpand,
921920
pub current_expansion: ExpansionData,
921+
/// Error recovery mode entered when expansion is stuck
922+
/// (or during eager expansion, but that's a hack).
923+
pub force_mode: bool,
922924
pub expansions: FxHashMap<Span, Vec<String>>,
923925
/// Called directly after having parsed an external `mod foo;` in expansion.
924926
pub(super) extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>,
@@ -945,6 +947,7 @@ impl<'a> ExtCtxt<'a> {
945947
directory_ownership: DirectoryOwnership::Owned { relative: None },
946948
prior_type_ascription: None,
947949
},
950+
force_mode: false,
948951
expansions: FxHashMap::default(),
949952
}
950953
}

compiler/rustc_expand/src/expand.rs

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
404404
// Recursively expand all macro invocations in this AST fragment.
405405
pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragment {
406406
let orig_expansion_data = self.cx.current_expansion.clone();
407+
let orig_force_mode = self.cx.force_mode;
407408
self.cx.current_expansion.depth = 0;
408409

409410
// Collect all macro invocations and replace them with placeholders.
@@ -432,6 +433,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
432433
}
433434
invocations = mem::take(&mut undetermined_invocations);
434435
force = !mem::replace(&mut progress, false);
436+
if force && self.monotonic {
437+
self.cx.sess.delay_span_bug(
438+
invocations.last().unwrap().0.span(),
439+
"expansion entered force mode without producing any errors",
440+
);
441+
}
435442
continue;
436443
};
437444

@@ -460,18 +467,18 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
460467

461468
let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data;
462469
self.cx.current_expansion = invoc.expansion_data.clone();
470+
self.cx.force_mode = force;
463471

464472
// FIXME(jseyfried): Refactor out the following logic
465473
let (expanded_fragment, new_invocations) = match res {
466474
InvocationRes::Single(ext) => match self.expand_invoc(invoc, &ext.kind) {
467475
ExpandResult::Ready(fragment) => self.collect_invocations(fragment, &[]),
468-
ExpandResult::Retry(invoc, explanation) => {
476+
ExpandResult::Retry(invoc) => {
469477
if force {
470-
// We are stuck, stop retrying and produce a dummy fragment.
471-
let span = invoc.span();
472-
self.cx.span_err(span, &explanation);
473-
let fragment = invoc.fragment_kind.dummy(span);
474-
self.collect_invocations(fragment, &[])
478+
self.cx.span_bug(
479+
invoc.span(),
480+
"expansion entered force mode but is still stuck",
481+
);
475482
} else {
476483
// Cannot expand, will retry this invocation later.
477484
undetermined_invocations
@@ -526,6 +533,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
526533
}
527534

528535
self.cx.current_expansion = orig_expansion_data;
536+
self.cx.force_mode = orig_force_mode;
529537

530538
// Finally incorporate all the expanded macros into the input AST fragment.
531539
let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
@@ -735,20 +743,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
735743
Ok(meta) => {
736744
let items = match expander.expand(self.cx, span, &meta, item) {
737745
ExpandResult::Ready(items) => items,
738-
ExpandResult::Retry(item, explanation) => {
746+
ExpandResult::Retry(item) => {
739747
// Reassemble the original invocation for retrying.
740-
return ExpandResult::Retry(
741-
Invocation {
742-
kind: InvocationKind::Attr {
743-
attr,
744-
item,
745-
derives,
746-
after_derive,
747-
},
748-
..invoc
748+
return ExpandResult::Retry(Invocation {
749+
kind: InvocationKind::Attr {
750+
attr,
751+
item,
752+
derives,
753+
after_derive,
749754
},
750-
explanation,
751-
);
755+
..invoc
756+
});
752757
}
753758
};
754759
fragment_kind.expect_from_annotatables(items)
@@ -781,15 +786,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
781786
let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path };
782787
let items = match expander.expand(self.cx, span, &meta, item) {
783788
ExpandResult::Ready(items) => items,
784-
ExpandResult::Retry(item, explanation) => {
789+
ExpandResult::Retry(item) => {
785790
// Reassemble the original invocation for retrying.
786-
return ExpandResult::Retry(
787-
Invocation {
788-
kind: InvocationKind::Derive { path: meta.path, item },
789-
..invoc
790-
},
791-
explanation,
792-
);
791+
return ExpandResult::Retry(Invocation {
792+
kind: InvocationKind::Derive { path: meta.path, item },
793+
..invoc
794+
});
793795
}
794796
};
795797
fragment_kind.expect_from_annotatables(items)

src/test/ui/conditional-compilation/cfg_accessible-stuck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![feature(cfg_accessible)]
22

3-
#[cfg_accessible(Z)] //~ ERROR cannot determine whether the path is accessible or not
3+
#[cfg_accessible(Z)] // OK, recovered after the other `cfg_accessible` produces an error.
44
struct S;
55

66
#[cfg_accessible(S)] //~ ERROR cannot determine whether the path is accessible or not

src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,5 @@ error: cannot determine whether the path is accessible or not
44
LL | #[cfg_accessible(S)]
55
| ^^^^^^^^^^^^^^^^^^^^
66

7-
error: cannot determine whether the path is accessible or not
8-
--> $DIR/cfg_accessible-stuck.rs:3:1
9-
|
10-
LL | #[cfg_accessible(Z)]
11-
| ^^^^^^^^^^^^^^^^^^^^
12-
13-
error: aborting due to 2 previous errors
7+
error: aborting due to previous error
148

0 commit comments

Comments
 (0)