about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/ich/impls_syntax.rs1
-rw-r--r--src/librustc/lint/mod.rs2
-rw-r--r--src/libsyntax/ext/expand.rs14
-rw-r--r--src/libsyntax_pos/hygiene.rs20
-rw-r--r--src/libsyntax_pos/lib.rs3
5 files changed, 33 insertions, 7 deletions
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 69e8c355019..e0e7988a744 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -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)
 });
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 3c8b0041a98..e76c2493200 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -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() {
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 39a8a7af2a3..9a6252779e0 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -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,
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index b72da042d04..5df14439230 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -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()),
         }
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 9258b71518f..5ccfe5f0b8b 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -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 => ("", "!"),