Skip to content

Commit

Permalink
Add with_{def_site,call_site,legacy}_ctxt, methods to Span
Browse files Browse the repository at this point in the history
Use these to create call-site spans for AST passes when needed.
  • Loading branch information
petrochenkov authored and matthewjasper committed Sep 5, 2019
1 parent 0b86782 commit c8cf9f5
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 117 deletions.
27 changes: 12 additions & 15 deletions src/librustc_resolve/macros.rs
Expand Up @@ -17,7 +17,7 @@ use syntax::edition::Edition;
use syntax::ext::base::{self, Indeterminate, SpecialDerives};
use syntax::ext::base::{MacroKind, SyntaxExtension};
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind, Transparency};
use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind};
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name};
use syntax::feature_gate::GateIssue;
Expand Down Expand Up @@ -131,23 +131,20 @@ impl<'a> base::Resolver for Resolver<'a> {
// Create a Span with modern hygiene with a definition site of the provided
// module, or a fake empty `#[no_implicit_prelude]` module if no module is
// provided.
fn span_for_ast_pass(
fn expansion_for_ast_pass(
&mut self,
base_span: Span,
call_site: Span,
pass: AstPass,
features: &[Symbol],
parent_module_id: Option<NodeId>,
) -> Span {
let span = base_span.fresh_expansion_with_transparency(
ExpnData::allow_unstable(
ExpnKind::AstPass(pass),
base_span,
self.session.edition(),
features.into(),
),
Transparency::Opaque,
);
let expn_id = span.ctxt().outer_expn();
) -> ExpnId {
let expn_id = ExpnId::fresh(Some(ExpnData::allow_unstable(
ExpnKind::AstPass(pass),
call_site,
self.session.edition(),
features.into(),
)));

let parent_scope = if let Some(module_id) = parent_module_id {
let parent_def_id = self.definitions.local_def_id(module_id);
self.definitions.add_parent_module_of_macro_def(expn_id, parent_def_id);
Expand All @@ -160,7 +157,7 @@ impl<'a> base::Resolver for Resolver<'a> {
self.empty_module
};
self.ast_transform_scopes.insert(expn_id, parent_scope);
span
expn_id
}

fn resolve_imports(&mut self) {
Expand Down
14 changes: 7 additions & 7 deletions src/libsyntax/ext/base.rs
Expand Up @@ -3,7 +3,7 @@ use crate::attr::{HasAttrs, Stability, Deprecation};
use crate::source_map::SourceMap;
use crate::edition::Edition;
use crate::ext::expand::{self, AstFragment, Invocation};
use crate::ext::hygiene::{ExpnId, Transparency};
use crate::ext::hygiene::ExpnId;
use crate::mut_visit::{self, MutVisitor};
use crate::parse::{self, parser, DirectoryOwnership};
use crate::parse::token;
Expand Down Expand Up @@ -658,13 +658,13 @@ pub trait Resolver {
extra_placeholders: &[NodeId]);
fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension);

fn span_for_ast_pass(
fn expansion_for_ast_pass(
&mut self,
span: Span,
call_site: Span,
pass: AstPass,
features: &[Symbol],
parent_module_id: Option<NodeId>,
) -> Span;
) -> ExpnId;

fn resolve_imports(&mut self);

Expand Down Expand Up @@ -750,20 +750,20 @@ impl<'a> ExtCtxt<'a> {
/// Equivalent of `Span::def_site` from the proc macro API,
/// except that the location is taken from the span passed as an argument.
pub fn with_def_site_ctxt(&self, span: Span) -> Span {
span.with_ctxt_from_mark(self.current_expansion.id, Transparency::Opaque)
span.with_def_site_ctxt(self.current_expansion.id)
}

/// Equivalent of `Span::call_site` from the proc macro API,
/// except that the location is taken from the span passed as an argument.
pub fn with_call_site_ctxt(&self, span: Span) -> Span {
span.with_ctxt_from_mark(self.current_expansion.id, Transparency::Transparent)
span.with_call_site_ctxt(self.current_expansion.id)
}

/// Span with a context reproducing `macro_rules` hygiene (hygienic locals, unhygienic items).
/// FIXME: This should be eventually replaced either with `with_def_site_ctxt` (preferably),
/// or with `with_call_site_ctxt` (where necessary).
pub fn with_legacy_ctxt(&self, span: Span) -> Span {
span.with_ctxt_from_mark(self.current_expansion.id, Transparency::SemiTransparent)
span.with_legacy_ctxt(self.current_expansion.id)
}

/// Returns span for the macro which originally caused the current expansion to happen.
Expand Down
3 changes: 2 additions & 1 deletion src/libsyntax_ext/proc_macro_harness.rs
Expand Up @@ -326,12 +326,13 @@ fn mk_decls(
custom_attrs: &[ProcMacroDef],
custom_macros: &[ProcMacroDef],
) -> P<ast::Item> {
let span = cx.resolver.span_for_ast_pass(
let expn_id = cx.resolver.expansion_for_ast_pass(
DUMMY_SP,
AstPass::ProcMacroHarness,
&[sym::rustc_attrs, sym::proc_macro_internals],
None,
);
let span = DUMMY_SP.with_def_site_ctxt(expn_id);

let proc_macro = Ident::new(sym::proc_macro, span);
let krate = cx.item(span,
Expand Down
8 changes: 5 additions & 3 deletions src/libsyntax_ext/standard_library_imports.rs
Expand Up @@ -28,19 +28,21 @@ pub fn inject(
&[sym::std]
};

let span = resolver.span_for_ast_pass(
let expn_id = resolver.expansion_for_ast_pass(
DUMMY_SP,
AstPass::StdImports,
&[sym::prelude_import],
None,
);
let span = DUMMY_SP.with_def_site_ctxt(expn_id);
let call_site = DUMMY_SP.with_call_site_ctxt(expn_id);

// .rev() to preserve ordering above in combination with insert(0, ...)
for &orig_name_sym in names.iter().rev() {
let (rename, orig_name) = if rust_2018 {
(Ident::new(kw::Underscore, span), Some(orig_name_sym))
} else {
(Ident::with_dummy_span(orig_name_sym), None)
(Ident::new(orig_name_sym, call_site), None)
};
krate.module.items.insert(0, P(ast::Item {
attrs: vec![attr::mk_attr_outer(
Expand All @@ -65,7 +67,7 @@ pub fn inject(
.collect()
} else {
[kw::PathRoot, name, sym::prelude, sym::v1].iter()
.map(|symbol| ast::PathSegment::from_ident(ast::Ident::with_dummy_span(*symbol)))
.map(|symbol| ast::PathSegment::from_ident(ast::Ident::new(*symbol, call_site)))
.collect()
};

Expand Down
10 changes: 6 additions & 4 deletions src/libsyntax_ext/test_harness.rs
Expand Up @@ -97,15 +97,16 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
};
// Create an identifier that will hygienically resolve the test
// case name, even in another module.
let sp = self.cx.ext_cx.resolver.span_for_ast_pass(
let expn_id = self.cx.ext_cx.resolver.expansion_for_ast_pass(
module.inner,
AstPass::TestHarness,
&[],
Some(parent),
);
let expn = sp.ctxt().outer_expn();
for test in &mut tests {
test.ident.span = test.ident.span.apply_mark(expn, Transparency::Opaque);
// See the comment on `mk_main` for why we're using
// `apply_mark` directly.
test.ident.span = test.ident.span.apply_mark(expn_id, Transparency::Opaque);
}
self.cx.test_cases.extend(tests);
}
Expand Down Expand Up @@ -207,12 +208,13 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
// #![main]
// test::test_main_static(&[..tests]);
// }
let sp = cx.ext_cx.resolver.span_for_ast_pass(
let expn_id = cx.ext_cx.resolver.expansion_for_ast_pass(
DUMMY_SP,
AstPass::TestHarness,
&[sym::main, sym::test, sym::rustc_attrs],
None,
);
let sp = DUMMY_SP.with_def_site_ctxt(expn_id);
let ecx = &cx.ext_cx;
let test_id = Ident::new(sym::test, sp);

Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax_pos/hygiene.rs
Expand Up @@ -360,7 +360,7 @@ impl SyntaxContext {
}

/// Extend a syntax context with a given expansion and transparency.
pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext {
crate fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext {
HygieneData::with(|data| data.apply_mark(self, expn_id, transparency))
}

Expand Down
19 changes: 19 additions & 0 deletions src/libsyntax_pos/lib.rs
Expand Up @@ -514,6 +514,25 @@ impl Span {
span.ctxt)
}

/// Equivalent of `Span::def_site` from the proc macro API,
/// except that the location is taken from the `self` span.
pub fn with_def_site_ctxt(self, expn_id: ExpnId) -> Span {
self.with_ctxt_from_mark(expn_id, Transparency::Opaque)
}

/// Equivalent of `Span::call_site` from the proc macro API,
/// except that the location is taken from the `self` span.
pub fn with_call_site_ctxt(&self, expn_id: ExpnId) -> Span {
self.with_ctxt_from_mark(expn_id, Transparency::Transparent)
}

/// Span with a context reproducing `macro_rules` hygiene (hygienic locals, unhygienic items).
/// FIXME: This should be eventually replaced either with `with_def_site_ctxt` (preferably),
/// or with `with_call_site_ctxt` (where necessary).
pub fn with_legacy_ctxt(&self, expn_id: ExpnId) -> Span {
self.with_ctxt_from_mark(expn_id, Transparency::SemiTransparent)
}

/// Produces a span with the same location as `self` and context produced by a macro with the
/// given ID and transparency, assuming that macro was defined directly and not produced by
/// some other macro (which is the case for built-in and procedural macros).
Expand Down
32 changes: 16 additions & 16 deletions src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
Expand Up @@ -2,80 +2,80 @@ PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ;
PRINT-BANG INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
Ident {
ident: "M",
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "$crate",
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
Punct {
ch: ':',
spacing: Joint,
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
Punct {
ch: ':',
spacing: Alone,
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
Ident {
ident: "S",
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
],
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
Punct {
ch: ';',
spacing: Alone,
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
]
PRINT-ATTR INPUT (DISPLAY): struct A(crate::S);
PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ;
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "struct",
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
Ident {
ident: "A",
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [
Ident {
ident: "$crate",
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
Punct {
ch: ':',
spacing: Joint,
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
Punct {
ch: ':',
spacing: Alone,
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
Ident {
ident: "S",
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
],
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
Punct {
ch: ';',
spacing: Alone,
span: #2 bytes(LO..HI),
span: #3 bytes(LO..HI),
},
]

0 comments on commit c8cf9f5

Please sign in to comment.