1
Fork 0

hygiene: Remove Options from functions returning ExpnInfo

The expansion info is not optional and should always exist
This commit is contained in:
Vadim Petrochenkov 2019-08-11 03:00:05 +03:00
parent 6cb28b6617
commit 73dee258c1
14 changed files with 98 additions and 155 deletions

View file

@ -9,7 +9,6 @@ use errors::Applicability;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use syntax::ast::{Ident, Item, ItemKind}; use syntax::ast::{Ident, Item, ItemKind};
use syntax::symbol::{sym, Symbol}; use syntax::symbol::{sym, Symbol};
use syntax_pos::ExpnInfo;
declare_tool_lint! { declare_tool_lint! {
pub rustc::DEFAULT_HASH_TYPES, pub rustc::DEFAULT_HASH_TYPES,
@ -228,9 +227,10 @@ impl EarlyLintPass for LintPassImpl {
if let ItemKind::Impl(_, _, _, _, Some(lint_pass), _, _) = &item.node { if let ItemKind::Impl(_, _, _, _, Some(lint_pass), _, _) = &item.node {
if let Some(last) = lint_pass.path.segments.last() { if let Some(last) = lint_pass.path.segments.last() {
if last.ident.name == sym::LintPass { if last.ident.name == sym::LintPass {
match &lint_pass.path.span.ctxt().outer_expn_info() { let expn_info = lint_pass.path.span.ctxt().outer_expn_info();
Some(info) if is_lint_pass_expansion(info) => {} let call_site = expn_info.call_site;
_ => { if expn_info.kind.descr() != sym::impl_lint_pass &&
call_site.ctxt().outer_expn_info().kind.descr() != sym::declare_lint_pass {
cx.struct_span_lint( cx.struct_span_lint(
LINT_PASS_IMPL_WITHOUT_MACRO, LINT_PASS_IMPL_WITHOUT_MACRO,
lint_pass.path.span, lint_pass.path.span,
@ -244,14 +244,3 @@ impl EarlyLintPass for LintPassImpl {
} }
} }
} }
}
fn is_lint_pass_expansion(expn_info: &ExpnInfo) -> bool {
if expn_info.kind.descr() == sym::impl_lint_pass {
true
} else if let Some(info) = expn_info.call_site.ctxt().outer_expn_info() {
info.kind.descr() == sym::declare_lint_pass
} else {
false
}
}

View file

@ -885,21 +885,16 @@ pub fn provide(providers: &mut Providers<'_>) {
/// This is used to test whether a lint should not even begin to figure out whether it should /// This is used to test whether a lint should not even begin to figure out whether it should
/// be reported on the current node. /// be reported on the current node.
pub fn in_external_macro(sess: &Session, span: Span) -> bool { pub fn in_external_macro(sess: &Session, span: Span) -> bool {
let info = match span.ctxt().outer_expn_info() { let expn_info = span.ctxt().outer_expn_info();
Some(info) => info, match expn_info.kind {
// no ExpnInfo means this span doesn't come from a macro
None => return false,
};
match info.kind {
ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false, ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
ExpnKind::Desugaring(_) => true, // well, it's "external" ExpnKind::Desugaring(_) => true, // well, it's "external"
ExpnKind::Macro(MacroKind::Bang, _) => { ExpnKind::Macro(MacroKind::Bang, _) => {
if info.def_site.is_dummy() { if expn_info.def_site.is_dummy() {
// dummy span for the def_site means it's an external macro // dummy span for the def_site means it's an external macro
return true; return true;
} }
match sess.source_map().span_to_snippet(info.def_site) { match sess.source_map().span_to_snippet(expn_info.def_site) {
Ok(code) => !code.starts_with("macro_rules"), Ok(code) => !code.starts_with("macro_rules"),
// no snippet = external macro or compiler-builtin expansion // no snippet = external macro or compiler-builtin expansion
Err(_) => true, Err(_) => true,
@ -911,10 +906,8 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
/// Returns whether `span` originates in a derive macro's expansion /// Returns whether `span` originates in a derive macro's expansion
pub fn in_derive_expansion(span: Span) -> bool { pub fn in_derive_expansion(span: Span) -> bool {
if let Some(info) = span.ctxt().outer_expn_info() { if let ExpnKind::Macro(MacroKind::Derive, _) = span.ctxt().outer_expn_info().kind {
if let ExpnKind::Macro(MacroKind::Derive, _) = info.kind {
return true; return true;
} }
}
false false
} }

View file

@ -36,7 +36,7 @@ use errors::{Applicability, DiagnosticBuilder};
use std::fmt; use std::fmt;
use syntax::ast; use syntax::ast;
use syntax::symbol::sym; use syntax::symbol::sym;
use syntax_pos::{DUMMY_SP, Span, ExpnInfo, ExpnKind}; use syntax_pos::{DUMMY_SP, Span, ExpnKind};
impl<'a, 'tcx> InferCtxt<'a, 'tcx> { impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn report_fulfillment_errors(&self, pub fn report_fulfillment_errors(&self,
@ -61,9 +61,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// We want to ignore desugarings here: spans are equivalent even // We want to ignore desugarings here: spans are equivalent even
// if one is the result of a desugaring and the other is not. // if one is the result of a desugaring and the other is not.
let mut span = error.obligation.cause.span; let mut span = error.obligation.cause.span;
if let Some(ExpnInfo { kind: ExpnKind::Desugaring(_), def_site, .. }) let expn_info = span.ctxt().outer_expn_info();
= span.ctxt().outer_expn_info() { if let ExpnKind::Desugaring(_) = expn_info.kind {
span = def_site; span = expn_info.call_site;
} }
error_map.entry(span).or_default().push( error_map.entry(span).or_default().push(

View file

@ -820,7 +820,6 @@ where
TAG_NO_EXPANSION_INFO.encode(self) TAG_NO_EXPANSION_INFO.encode(self)
} else { } else {
let (expn_id, expn_info) = span_data.ctxt.outer_expn_with_info(); let (expn_id, expn_info) = span_data.ctxt.outer_expn_with_info();
if let Some(expn_info) = expn_info {
if let Some(pos) = self.expn_info_shorthands.get(&expn_id).cloned() { if let Some(pos) = self.expn_info_shorthands.get(&expn_id).cloned() {
TAG_EXPANSION_INFO_SHORTHAND.encode(self)?; TAG_EXPANSION_INFO_SHORTHAND.encode(self)?;
pos.encode(self) pos.encode(self)
@ -830,9 +829,6 @@ where
self.expn_info_shorthands.insert(expn_id, pos); self.expn_info_shorthands.insert(expn_id, pos);
expn_info.encode(self) expn_info.encode(self)
} }
} else {
TAG_NO_EXPANSION_INFO.encode(self)
}
} }
} }
} }

View file

@ -1775,10 +1775,7 @@ impl SharedEmitterMain {
} }
} }
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg)) => { Ok(SharedEmitterMessage::InlineAsmError(cookie, msg)) => {
match ExpnId::from_u32(cookie).expn_info() { sess.span_err(ExpnId::from_u32(cookie).expn_info().call_site, &msg)
Some(ei) => sess.span_err(ei.call_site, &msg),
None => sess.err(&msg),
}
} }
Ok(SharedEmitterMessage::AbortIfErrors) => { Ok(SharedEmitterMessage::AbortIfErrors) => {
sess.abort_if_errors(); sess.abort_if_errors();

View file

@ -517,8 +517,7 @@ impl EarlyLintPass for UnusedParens {
// trigger in situations that macro authors shouldn't have to care about, e.g., // trigger in situations that macro authors shouldn't have to care about, e.g.,
// when a parenthesized token tree matched in one macro expansion is matched as // when a parenthesized token tree matched in one macro expansion is matched as
// an expression in another and used as a fn/method argument (Issue #47775) // an expression in another and used as a fn/method argument (Issue #47775)
if e.span.ctxt().outer_expn_info() if e.span.ctxt().outer_expn_info().call_site.from_expansion() {
.map_or(false, |info| info.call_site.from_expansion()) {
return; return;
} }
let msg = format!("{} argument", call_kind); let msg = format!("{} argument", call_kind);

View file

@ -346,8 +346,7 @@ impl<'a> Resolver<'a> {
// Possibly apply the macro helper hack // Possibly apply the macro helper hack
if kind == Some(MacroKind::Bang) && path.len() == 1 && if kind == Some(MacroKind::Bang) && path.len() == 1 &&
path[0].ident.span.ctxt().outer_expn_info() path[0].ident.span.ctxt().outer_expn_info().local_inner_macros {
.map_or(false, |info| info.local_inner_macros) {
let root = Ident::new(kw::DollarCrate, path[0].ident.span); let root = Ident::new(kw::DollarCrate, path[0].ident.span);
path.insert(0, Segment::from_ident(root)); path.insert(0, Segment::from_ident(root));
} }

View file

@ -756,10 +756,7 @@ impl<'a> ExtCtxt<'a> {
pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess } pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
pub fn cfg(&self) -> &ast::CrateConfig { &self.parse_sess.config } pub fn cfg(&self) -> &ast::CrateConfig { &self.parse_sess.config }
pub fn call_site(&self) -> Span { pub fn call_site(&self) -> Span {
match self.current_expansion.id.expn_info() { self.current_expansion.id.expn_info().call_site
Some(expn_info) => expn_info.call_site,
None => DUMMY_SP,
}
} }
pub fn backtrace(&self) -> SyntaxContext { pub fn backtrace(&self) -> SyntaxContext {
SyntaxContext::root().apply_mark(self.current_expansion.id) SyntaxContext::root().apply_mark(self.current_expansion.id)
@ -772,17 +769,13 @@ impl<'a> ExtCtxt<'a> {
let mut ctxt = self.backtrace(); let mut ctxt = self.backtrace();
let mut last_macro = None; let mut last_macro = None;
loop { loop {
if ctxt.outer_expn_info().map_or(None, |info| { let expn_info = ctxt.outer_expn_info();
if info.kind.descr() == sym::include {
// Stop going up the backtrace once include! is encountered // Stop going up the backtrace once include! is encountered
return None; if expn_info.is_root() || expn_info.kind.descr() == sym::include {
} break;
ctxt = info.call_site.ctxt();
last_macro = Some(info.call_site);
Some(())
}).is_none() {
break
} }
ctxt = expn_info.call_site.ctxt();
last_macro = Some(expn_info.call_site);
} }
last_macro last_macro
} }

View file

@ -475,7 +475,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
} }
if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
let info = self.cx.current_expansion.id.expn_info().unwrap(); let info = self.cx.current_expansion.id.expn_info();
let suggested_limit = self.cx.ecfg.recursion_limit * 2; let suggested_limit = self.cx.ecfg.recursion_limit * 2;
let mut err = self.cx.struct_span_err(info.call_site, let mut err = self.cx.struct_span_err(info.call_site,
&format!("recursion limit reached while expanding the macro `{}`", &format!("recursion limit reached while expanding the macro `{}`",

View file

@ -362,7 +362,7 @@ pub(crate) struct Rustc<'a> {
impl<'a> Rustc<'a> { impl<'a> Rustc<'a> {
pub fn new(cx: &'a ExtCtxt<'_>) -> Self { pub fn new(cx: &'a ExtCtxt<'_>) -> Self {
// No way to determine def location for a proc macro right now, so use call location. // No way to determine def location for a proc macro right now, so use call location.
let location = cx.current_expansion.id.expn_info().unwrap().call_site; let location = cx.current_expansion.id.expn_info().call_site;
let to_span = |transparency| { let to_span = |transparency| {
location.with_ctxt( location.with_ctxt(
SyntaxContext::root() SyntaxContext::root()
@ -677,7 +677,7 @@ impl server::Span for Rustc<'_> {
self.sess.source_map().lookup_char_pos(span.lo()).file self.sess.source_map().lookup_char_pos(span.lo()).file
} }
fn parent(&mut self, span: Self::Span) -> Option<Self::Span> { fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
span.ctxt().outer_expn_info().map(|i| i.call_site) span.parent()
} }
fn source(&mut self, span: Self::Span) -> Self::Span { fn source(&mut self, span: Self::Span) -> Self::Span {
span.source_callsite() span.source_callsite()

View file

@ -13,7 +13,6 @@ mod generics;
use crate::ast::{self, AttrStyle, Attribute, Arg, BindingMode, StrStyle, SelfKind}; use crate::ast::{self, AttrStyle, Attribute, Arg, BindingMode, StrStyle, SelfKind};
use crate::ast::{FnDecl, Ident, IsAsync, MacDelimiter, Mutability, TyKind}; use crate::ast::{FnDecl, Ident, IsAsync, MacDelimiter, Mutability, TyKind};
use crate::ast::{Visibility, VisibilityKind, Unsafety, CrateSugar}; use crate::ast::{Visibility, VisibilityKind, Unsafety, CrateSugar};
use crate::ext::hygiene::SyntaxContext;
use crate::source_map::{self, respan}; use crate::source_map::{self, respan};
use crate::parse::{SeqSep, literal, token}; use crate::parse::{SeqSep, literal, token};
use crate::parse::lexer::UnmatchedBrace; use crate::parse::lexer::UnmatchedBrace;

View file

@ -31,12 +31,13 @@ mod tests;
/// otherwise return the call site span up to the `enclosing_sp` by /// otherwise return the call site span up to the `enclosing_sp` by
/// following the `expn_info` chain. /// following the `expn_info` chain.
pub fn original_sp(sp: Span, enclosing_sp: Span) -> Span { pub fn original_sp(sp: Span, enclosing_sp: Span) -> Span {
let call_site1 = sp.ctxt().outer_expn_info().map(|ei| ei.call_site); let expn_info1 = sp.ctxt().outer_expn_info();
let call_site2 = enclosing_sp.ctxt().outer_expn_info().map(|ei| ei.call_site); let expn_info2 = enclosing_sp.ctxt().outer_expn_info();
match (call_site1, call_site2) { if expn_info1.is_root() ||
(None, _) => sp, !expn_info2.is_root() && expn_info1.call_site == expn_info2.call_site {
(Some(call_site1), Some(call_site2)) if call_site1 == call_site2 => sp, sp
(Some(call_site1), _) => original_sp(call_site1, enclosing_sp), } else {
original_sp(expn_info1.call_site, enclosing_sp)
} }
} }

View file

@ -112,8 +112,8 @@ impl ExpnId {
} }
#[inline] #[inline]
pub fn expn_info(self) -> Option<ExpnInfo> { pub fn expn_info(self) -> ExpnInfo {
HygieneData::with(|data| data.expn_info(self).cloned()) HygieneData::with(|data| data.expn_info(self).clone())
} }
#[inline] #[inline]
@ -139,12 +139,9 @@ impl ExpnId {
#[inline] #[inline]
pub fn looks_like_proc_macro_derive(self) -> bool { pub fn looks_like_proc_macro_derive(self) -> bool {
HygieneData::with(|data| { HygieneData::with(|data| {
if data.default_transparency(self) == Transparency::Opaque { let expn_info = data.expn_info(self);
if let Some(expn_info) = data.expn_info(self) {
if let ExpnKind::Macro(MacroKind::Derive, _) = expn_info.kind { if let ExpnKind::Macro(MacroKind::Derive, _) = expn_info.kind {
return true; return expn_info.default_transparency == Transparency::Opaque;
}
}
} }
false false
}) })
@ -190,16 +187,9 @@ impl HygieneData {
self.expn_data[expn_id.0 as usize].parent self.expn_data[expn_id.0 as usize].parent
} }
fn expn_info(&self, expn_id: ExpnId) -> Option<&ExpnInfo> { fn expn_info(&self, expn_id: ExpnId) -> &ExpnInfo {
if expn_id != ExpnId::root() { self.expn_data[expn_id.0 as usize].expn_info.as_ref()
Some(self.expn_data[expn_id.0 as usize].expn_info.as_ref() .expect("no expansion info for an expansion ID")
.expect("no expansion info for an expansion ID"))
} 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 expn_id: ExpnId, ancestor: ExpnId) -> bool { fn is_descendant_of(&self, mut expn_id: ExpnId, ancestor: ExpnId) -> bool {
@ -212,12 +202,6 @@ impl HygieneData {
true true
} }
fn default_transparency(&self, expn_id: ExpnId) -> Transparency {
self.expn_info(expn_id).map_or(
Transparency::SemiTransparent, |einfo| einfo.default_transparency
)
}
fn modern(&self, ctxt: SyntaxContext) -> SyntaxContext { fn modern(&self, ctxt: SyntaxContext) -> SyntaxContext {
self.syntax_context_data[ctxt.0 as usize].opaque self.syntax_context_data[ctxt.0 as usize].opaque
} }
@ -256,11 +240,7 @@ impl HygieneData {
fn walk_chain(&self, mut span: Span, to: SyntaxContext) -> Span { fn walk_chain(&self, mut span: Span, to: SyntaxContext) -> Span {
while span.from_expansion() && span.ctxt() != to { while span.from_expansion() && span.ctxt() != to {
if let Some(info) = self.expn_info(self.outer_expn(span.ctxt())) { span = self.expn_info(self.outer_expn(span.ctxt())).call_site;
span = info.call_site;
} else {
break;
}
} }
span span
} }
@ -275,7 +255,9 @@ impl HygieneData {
fn apply_mark(&mut self, ctxt: SyntaxContext, expn_id: ExpnId) -> SyntaxContext { fn apply_mark(&mut self, ctxt: SyntaxContext, expn_id: ExpnId) -> SyntaxContext {
assert_ne!(expn_id, ExpnId::root()); assert_ne!(expn_id, ExpnId::root());
self.apply_mark_with_transparency(ctxt, expn_id, self.default_transparency(expn_id)) self.apply_mark_with_transparency(
ctxt, expn_id, self.expn_info(expn_id).default_transparency
)
} }
fn apply_mark_with_transparency(&mut self, ctxt: SyntaxContext, expn_id: ExpnId, fn apply_mark_with_transparency(&mut self, ctxt: SyntaxContext, expn_id: ExpnId,
@ -285,8 +267,7 @@ impl HygieneData {
return self.apply_mark_internal(ctxt, expn_id, transparency); return self.apply_mark_internal(ctxt, expn_id, transparency);
} }
let call_site_ctxt = let call_site_ctxt = self.expn_info(expn_id).call_site.ctxt();
self.expn_info(expn_id).map_or(SyntaxContext::root(), |info| info.call_site.ctxt());
let mut call_site_ctxt = if transparency == Transparency::SemiTransparent { let mut call_site_ctxt = if transparency == Transparency::SemiTransparent {
self.modern(call_site_ctxt) self.modern(call_site_ctxt)
} else { } else {
@ -581,17 +562,17 @@ impl SyntaxContext {
/// `ctxt.outer_expn_info()` is equivalent to but faster than /// `ctxt.outer_expn_info()` is equivalent to but faster than
/// `ctxt.outer_expn().expn_info()`. /// `ctxt.outer_expn().expn_info()`.
#[inline] #[inline]
pub fn outer_expn_info(self) -> Option<ExpnInfo> { pub fn outer_expn_info(self) -> ExpnInfo {
HygieneData::with(|data| data.expn_info(data.outer_expn(self)).cloned()) HygieneData::with(|data| data.expn_info(data.outer_expn(self)).clone())
} }
/// `ctxt.outer_expn_with_info()` is equivalent to but faster than /// `ctxt.outer_expn_with_info()` is equivalent to but faster than
/// `{ let outer = ctxt.outer_expn(); (outer, outer.expn_info()) }`. /// `{ let outer = ctxt.outer_expn(); (outer, outer.expn_info()) }`.
#[inline] #[inline]
pub fn outer_expn_with_info(self) -> (ExpnId, Option<ExpnInfo>) { pub fn outer_expn_with_info(self) -> (ExpnId, ExpnInfo) {
HygieneData::with(|data| { HygieneData::with(|data| {
let outer = data.outer_expn(self); let outer = data.outer_expn(self);
(outer, data.expn_info(outer).cloned()) (outer, data.expn_info(outer).clone())
}) })
} }
@ -681,6 +662,11 @@ impl ExpnInfo {
..ExpnInfo::default(kind, call_site, edition) ..ExpnInfo::default(kind, call_site, edition)
} }
} }
#[inline]
pub fn is_root(&self) -> bool {
if let ExpnKind::Root = self.kind { true } else { false }
}
} }
/// Expansion kind. /// Expansion kind.

View file

@ -355,20 +355,20 @@ impl Span {
/// Returns the source span -- this is either the supplied span, or the span for /// Returns the source span -- this is either the supplied span, or the span for
/// the macro callsite that expanded to it. /// the macro callsite that expanded to it.
pub fn source_callsite(self) -> Span { pub fn source_callsite(self) -> Span {
self.ctxt().outer_expn_info().map(|info| info.call_site.source_callsite()).unwrap_or(self) let expn_info = self.ctxt().outer_expn_info();
if !expn_info.is_root() { expn_info.call_site.source_callsite() } else { self }
} }
/// The `Span` for the tokens in the previous macro expansion from which `self` was generated, /// The `Span` for the tokens in the previous macro expansion from which `self` was generated,
/// if any. /// if any.
pub fn parent(self) -> Option<Span> { pub fn parent(self) -> Option<Span> {
self.ctxt().outer_expn_info().map(|i| i.call_site) let expn_info = self.ctxt().outer_expn_info();
if !expn_info.is_root() { Some(expn_info.call_site) } else { None }
} }
/// Edition of the crate from which this span came. /// Edition of the crate from which this span came.
pub fn edition(self) -> edition::Edition { pub fn edition(self) -> edition::Edition {
self.ctxt().outer_expn_info().map_or_else(|| { self.ctxt().outer_expn_info().edition
Edition::from_session()
}, |einfo| einfo.edition)
} }
#[inline] #[inline]
@ -387,49 +387,39 @@ impl Span {
/// else returns the `ExpnInfo` for the macro definition /// else returns the `ExpnInfo` for the macro definition
/// corresponding to the source callsite. /// corresponding to the source callsite.
pub fn source_callee(self) -> Option<ExpnInfo> { pub fn source_callee(self) -> Option<ExpnInfo> {
fn source_callee(info: ExpnInfo) -> ExpnInfo { fn source_callee(expn_info: ExpnInfo) -> ExpnInfo {
match info.call_site.ctxt().outer_expn_info() { let next_expn_info = expn_info.call_site.ctxt().outer_expn_info();
Some(info) => source_callee(info), if !next_expn_info.is_root() { source_callee(next_expn_info) } else { expn_info }
None => info,
} }
} let expn_info = self.ctxt().outer_expn_info();
self.ctxt().outer_expn_info().map(source_callee) if !expn_info.is_root() { Some(source_callee(expn_info)) } else { None }
} }
/// Checks if a span is "internal" to a macro in which `#[unstable]` /// Checks if a span is "internal" to a macro in which `#[unstable]`
/// items can be used (that is, a macro marked with /// items can be used (that is, a macro marked with
/// `#[allow_internal_unstable]`). /// `#[allow_internal_unstable]`).
pub fn allows_unstable(&self, feature: Symbol) -> bool { pub fn allows_unstable(&self, feature: Symbol) -> bool {
match self.ctxt().outer_expn_info() { self.ctxt().outer_expn_info().allow_internal_unstable.map_or(false, |features| {
Some(info) => info features.iter().any(|&f| {
.allow_internal_unstable
.map_or(false, |features| features.iter().any(|&f|
f == feature || f == sym::allow_internal_unstable_backcompat_hack f == feature || f == sym::allow_internal_unstable_backcompat_hack
)), })
None => false, })
}
} }
/// Checks if this span arises from a compiler desugaring of kind `kind`. /// Checks if this span arises from a compiler desugaring of kind `kind`.
pub fn is_desugaring(&self, kind: DesugaringKind) -> bool { pub fn is_desugaring(&self, kind: DesugaringKind) -> bool {
match self.ctxt().outer_expn_info() { match self.ctxt().outer_expn_info().kind {
Some(info) => match info.kind {
ExpnKind::Desugaring(k) => k == kind, ExpnKind::Desugaring(k) => k == kind,
_ => false, _ => false,
},
None => false,
} }
} }
/// Returns the compiler desugaring that created this span, or `None` /// Returns the compiler desugaring that created this span, or `None`
/// if this span is not from a desugaring. /// if this span is not from a desugaring.
pub fn desugaring_kind(&self) -> Option<DesugaringKind> { pub fn desugaring_kind(&self) -> Option<DesugaringKind> {
match self.ctxt().outer_expn_info() { match self.ctxt().outer_expn_info().kind {
Some(info) => match info.kind {
ExpnKind::Desugaring(k) => Some(k), ExpnKind::Desugaring(k) => Some(k),
_ => None _ => None
},
None => None
} }
} }
@ -437,16 +427,17 @@ impl Span {
/// can be used without triggering the `unsafe_code` lint /// can be used without triggering the `unsafe_code` lint
// (that is, a macro marked with `#[allow_internal_unsafe]`). // (that is, a macro marked with `#[allow_internal_unsafe]`).
pub fn allows_unsafe(&self) -> bool { pub fn allows_unsafe(&self) -> bool {
match self.ctxt().outer_expn_info() { self.ctxt().outer_expn_info().allow_internal_unsafe
Some(info) => info.allow_internal_unsafe,
None => false,
}
} }
pub fn macro_backtrace(mut self) -> Vec<MacroBacktrace> { pub fn macro_backtrace(mut self) -> Vec<MacroBacktrace> {
let mut prev_span = DUMMY_SP; let mut prev_span = DUMMY_SP;
let mut result = vec![]; let mut result = vec![];
while let Some(info) = self.ctxt().outer_expn_info() { loop {
let info = self.ctxt().outer_expn_info();
if info.is_root() {
break;
}
// Don't print recursive invocations. // Don't print recursive invocations.
if !info.call_site.source_equal(&prev_span) { if !info.call_site.source_equal(&prev_span) {
let (pre, post) = match info.kind { let (pre, post) = match info.kind {