Skip to content
Permalink
Browse files

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.
  • Loading branch information...
petrochenkov committed Jul 7, 2019
1 parent dcd30a4 commit eac900ac87828d6a4813f0c4a870bcdb439d1175
@@ -408,6 +408,7 @@ impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
});

impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnKind {
Root,
Macro(kind, descr),
Desugaring(kind)
});
@@ -885,7 +885,7 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
};

match info.kind {
ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
ExpnKind::Desugaring(_) => true, // well, it's "external"
ExpnKind::Macro(MacroKind::Bang, _) => {
if info.def_site.is_dummy() {
@@ -5,7 +5,7 @@ use crate::source_map::{dummy_spanned, respan};
use crate::config::StripUnconfigured;
use crate::ext::base::*;
use crate::ext::derive::{add_derived_markers, collect_derives};
use crate::ext::hygiene::{Mark, SyntaxContext};
use crate::ext::hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnKind};
use crate::ext::placeholders::{placeholder, PlaceholderExpander};
use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
use crate::mut_visit::*;
@@ -847,7 +847,17 @@ struct InvocationCollector<'a, 'b> {

impl<'a, 'b> InvocationCollector<'a, 'b> {
fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> AstFragment {
let mark = Mark::fresh(self.cx.current_expansion.mark, None);
// Expansion info for all the collected invocations is set upon their resolution,
// with exception of the "derive container" case which is not resolved and can get
// its expansion info immediately.
let expn_info = match &kind {
InvocationKind::Attr { attr: None, item, .. } => Some(ExpnInfo::default(
ExpnKind::Macro(MacroKind::Attr, sym::derive),
item.span(), self.cx.parse_sess.edition,
)),
_ => None,
};
let mark = Mark::fresh(self.cx.current_expansion.mark, expn_info);
self.invocations.push(Invocation {
kind,
fragment_kind,
@@ -59,6 +59,9 @@ pub struct Mark(u32);
#[derive(Debug)]
struct MarkData {
parent: Mark,
/// Each mark should have an associated expansion info, but sometimes there's a delay between
/// creation of a mark and obtaining its info (e.g. macros are collected first and then
/// resolved later), so we use an `Option` here.
expn_info: Option<ExpnInfo>,
}

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

impl HygieneData {
crate fn new() -> Self {
crate fn new(edition: Edition) -> Self {
HygieneData {
marks: vec![MarkData {
parent: Mark::root(),
expn_info: None,
expn_info: Some(ExpnInfo::default(ExpnKind::Root, DUMMY_SP, edition)),
}],
syntax_contexts: vec![SyntaxContextData {
outer_mark: Mark::root(),
@@ -183,7 +186,15 @@ impl HygieneData {
}

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

fn is_descendant_of(&self, mut mark: Mark, ancestor: Mark) -> bool {
@@ -670,6 +681,8 @@ impl ExpnInfo {
/// Expansion kind.
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum ExpnKind {
/// No expansion, aka root expansion. Only `Mark::root()` has this kind.
Root,
/// Expansion produced by a macro.
/// FIXME: Some code injected by the compiler before HIR lowering also gets this kind.
Macro(MacroKind, Symbol),
@@ -680,6 +693,7 @@ pub enum ExpnKind {
impl ExpnKind {
pub fn descr(&self) -> Symbol {
match *self {
ExpnKind::Root => kw::PathRoot,
ExpnKind::Macro(_, descr) => descr,
ExpnKind::Desugaring(kind) => Symbol::intern(kind.descr()),
}
@@ -60,7 +60,7 @@ impl Globals {
Globals {
symbol_interner: Lock::new(symbol::Interner::fresh()),
span_interner: Lock::new(span_encoding::SpanInterner::default()),
hygiene_data: Lock::new(hygiene::HygieneData::new()),
hygiene_data: Lock::new(hygiene::HygieneData::new(edition)),
edition,
}
}
@@ -442,6 +442,7 @@ impl Span {
// Don't print recursive invocations.
if !info.call_site.source_equal(&prev_span) {
let (pre, post) = match info.kind {
ExpnKind::Root => break,
ExpnKind::Desugaring(..) => ("desugaring of ", ""),
ExpnKind::Macro(macro_kind, _) => match macro_kind {
MacroKind::Bang => ("", "!"),

0 comments on commit eac900a

Please sign in to comment.
You can’t perform that action at this time.