Skip to content

Commit eac900a

Browse files
committed
hygiene: Make sure each Mark has an associated expansion info
The root expansion was missing one. Expansions created for "derive containers" (see one of the next commits for the description) also didn't get expansion info.
1 parent dcd30a4 commit eac900a

File tree

5 files changed

+33
-7
lines changed

5 files changed

+33
-7
lines changed

src/librustc/ich/impls_syntax.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
408408
});
409409

410410
impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnKind {
411+
Root,
411412
Macro(kind, descr),
412413
Desugaring(kind)
413414
});

src/librustc/lint/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,7 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
885885
};
886886

887887
match info.kind {
888-
ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
888+
ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
889889
ExpnKind::Desugaring(_) => true, // well, it's "external"
890890
ExpnKind::Macro(MacroKind::Bang, _) => {
891891
if info.def_site.is_dummy() {

src/libsyntax/ext/expand.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::source_map::{dummy_spanned, respan};
55
use crate::config::StripUnconfigured;
66
use crate::ext::base::*;
77
use crate::ext::derive::{add_derived_markers, collect_derives};
8-
use crate::ext::hygiene::{Mark, SyntaxContext};
8+
use crate::ext::hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnKind};
99
use crate::ext::placeholders::{placeholder, PlaceholderExpander};
1010
use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
1111
use crate::mut_visit::*;
@@ -847,7 +847,17 @@ struct InvocationCollector<'a, 'b> {
847847

848848
impl<'a, 'b> InvocationCollector<'a, 'b> {
849849
fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
850-
let mark = Mark::fresh(self.cx.current_expansion.mark, None);
850+
// Expansion info for all the collected invocations is set upon their resolution,
851+
// with exception of the "derive container" case which is not resolved and can get
852+
// its expansion info immediately.
853+
let expn_info = match &kind {
854+
InvocationKind::Attr { attr: None, item, .. } => Some(ExpnInfo::default(
855+
ExpnKind::Macro(MacroKind::Attr, sym::derive),
856+
item.span(), self.cx.parse_sess.edition,
857+
)),
858+
_ => None,
859+
};
860+
let mark = Mark::fresh(self.cx.current_expansion.mark, expn_info);
851861
self.invocations.push(Invocation {
852862
kind,
853863
fragment_kind,

src/libsyntax_pos/hygiene.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ pub struct Mark(u32);
5959
#[derive(Debug)]
6060
struct MarkData {
6161
parent: Mark,
62+
/// Each mark should have an associated expansion info, but sometimes there's a delay between
63+
/// creation of a mark and obtaining its info (e.g. macros are collected first and then
64+
/// resolved later), so we use an `Option` here.
6265
expn_info: Option<ExpnInfo>,
6366
}
6467

@@ -155,11 +158,11 @@ crate struct HygieneData {
155158
}
156159

157160
impl HygieneData {
158-
crate fn new() -> Self {
161+
crate fn new(edition: Edition) -> Self {
159162
HygieneData {
160163
marks: vec![MarkData {
161164
parent: Mark::root(),
162-
expn_info: None,
165+
expn_info: Some(ExpnInfo::default(ExpnKind::Root, DUMMY_SP, edition)),
163166
}],
164167
syntax_contexts: vec![SyntaxContextData {
165168
outer_mark: Mark::root(),
@@ -183,7 +186,15 @@ impl HygieneData {
183186
}
184187

185188
fn expn_info(&self, mark: Mark) -> Option<&ExpnInfo> {
186-
self.marks[mark.0 as usize].expn_info.as_ref()
189+
if mark != Mark::root() {
190+
Some(self.marks[mark.0 as usize].expn_info.as_ref()
191+
.expect("no expansion info for a mark"))
192+
} else {
193+
// FIXME: Some code relies on `expn_info().is_none()` meaning "no expansion".
194+
// Introduce a method for checking for "no expansion" instead and always return
195+
// `ExpnInfo` from this function instead of the `Option`.
196+
None
197+
}
187198
}
188199

189200
fn is_descendant_of(&self, mut mark: Mark, ancestor: Mark) -> bool {
@@ -670,6 +681,8 @@ impl ExpnInfo {
670681
/// Expansion kind.
671682
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
672683
pub enum ExpnKind {
684+
/// No expansion, aka root expansion. Only `Mark::root()` has this kind.
685+
Root,
673686
/// Expansion produced by a macro.
674687
/// FIXME: Some code injected by the compiler before HIR lowering also gets this kind.
675688
Macro(MacroKind, Symbol),
@@ -680,6 +693,7 @@ pub enum ExpnKind {
680693
impl ExpnKind {
681694
pub fn descr(&self) -> Symbol {
682695
match *self {
696+
ExpnKind::Root => kw::PathRoot,
683697
ExpnKind::Macro(_, descr) => descr,
684698
ExpnKind::Desugaring(kind) => Symbol::intern(kind.descr()),
685699
}

src/libsyntax_pos/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl Globals {
6060
Globals {
6161
symbol_interner: Lock::new(symbol::Interner::fresh()),
6262
span_interner: Lock::new(span_encoding::SpanInterner::default()),
63-
hygiene_data: Lock::new(hygiene::HygieneData::new()),
63+
hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
6464
edition,
6565
}
6666
}
@@ -442,6 +442,7 @@ impl Span {
442442
// Don't print recursive invocations.
443443
if !info.call_site.source_equal(&prev_span) {
444444
let (pre, post) = match info.kind {
445+
ExpnKind::Root => break,
445446
ExpnKind::Desugaring(..) => ("desugaring of ", ""),
446447
ExpnKind::Macro(macro_kind, _) => match macro_kind {
447448
MacroKind::Bang => ("", "!"),

0 commit comments

Comments
 (0)