Skip to content

Commit 3997507

Browse files
committed
Resolve $crate in all hygienic contexts for pretty-pringing
Stop visiting AST to discover those contexts, just iterate through hygiene data instead
1 parent 4344a90 commit 3997507

File tree

8 files changed

+47
-59
lines changed

8 files changed

+47
-59
lines changed

src/librustc_resolve/build_reduced_graph.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,10 @@ impl<'a> Resolver<'a> {
758758
}
759759

760760
pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
761-
let def_id = self.macro_defs[&expansion];
761+
let def_id = match self.macro_defs.get(&expansion) {
762+
Some(def_id) => *def_id,
763+
None => return self.graph_root,
764+
};
762765
if let Some(id) = self.definitions.as_local_node_id(def_id) {
763766
self.local_macro_def_scopes[&id]
764767
} else if def_id.krate == CrateNum::BuiltinMacros {

src/librustc_resolve/macros.rs

+8-19
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,11 @@ use syntax::errors::DiagnosticBuilder;
1717
use syntax::ext::base::{self, Determinacy};
1818
use syntax::ext::base::{MacroKind, SyntaxExtension};
1919
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
20-
use syntax::ext::hygiene::Mark;
20+
use syntax::ext::hygiene::{self, Mark};
2121
use syntax::ext::tt::macro_rules;
2222
use syntax::feature_gate::{feature_err, emit_feature_err, is_builtin_attr_name};
2323
use syntax::feature_gate::{AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES};
2424
use syntax::symbol::{Symbol, kw, sym};
25-
use syntax::visit::Visitor;
2625
use syntax::util::lev_distance::find_best_match_for_name;
2726
use syntax_pos::{Span, DUMMY_SP};
2827
use errors::Applicability;
@@ -146,24 +145,14 @@ impl<'a> base::Resolver for Resolver<'a> {
146145
mark
147146
}
148147

149-
fn resolve_dollar_crates(&mut self, fragment: &AstFragment) {
150-
struct ResolveDollarCrates<'a, 'b> {
151-
resolver: &'a mut Resolver<'b>
152-
}
153-
impl<'a> Visitor<'a> for ResolveDollarCrates<'a, '_> {
154-
fn visit_ident(&mut self, ident: Ident) {
155-
if ident.name == kw::DollarCrate {
156-
let name = match self.resolver.resolve_crate_root(ident).kind {
157-
ModuleKind::Def(.., name) if name != kw::Invalid => name,
158-
_ => kw::Crate,
159-
};
160-
ident.span.ctxt().set_dollar_crate_name(name);
161-
}
148+
fn resolve_dollar_crates(&mut self) {
149+
hygiene::update_dollar_crate_names(|ctxt| {
150+
let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt));
151+
match self.resolve_crate_root(ident).kind {
152+
ModuleKind::Def(.., name) if name != kw::Invalid => name,
153+
_ => kw::Crate,
162154
}
163-
fn visit_mac(&mut self, _: &ast::Mac) {}
164-
}
165-
166-
fragment.visit_with(&mut ResolveDollarCrates { resolver: self });
155+
});
167156
}
168157

169158
fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,

src/libsyntax/ext/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ pub trait Resolver {
701701

702702
fn get_module_scope(&mut self, id: ast::NodeId) -> Mark;
703703

704-
fn resolve_dollar_crates(&mut self, fragment: &AstFragment);
704+
fn resolve_dollar_crates(&mut self);
705705
fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
706706
derives: &[Mark]);
707707
fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);

src/libsyntax/ext/expand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
429429
fn collect_invocations(&mut self, mut fragment: AstFragment, derives: &[Mark])
430430
-> (AstFragment, Vec<Invocation>) {
431431
// Resolve `$crate`s in the fragment for pretty-printing.
432-
self.cx.resolver.resolve_dollar_crates(&fragment);
432+
self.cx.resolver.resolve_dollar_crates();
433433

434434
let invocations = {
435435
let mut collector = InvocationCollector {

src/libsyntax_pos/hygiene.rs

+18-12
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use crate::symbol::{kw, Symbol};
3333
use serialize::{Encodable, Decodable, Encoder, Decoder};
3434
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
3535
use rustc_data_structures::sync::Lrc;
36-
use std::{fmt, mem};
36+
use std::fmt;
3737

3838
/// A SyntaxContext represents a chain of macro expansions (represented by marks).
3939
#[derive(Clone, Copy, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
@@ -387,6 +387,23 @@ pub fn walk_chain(span: Span, to: SyntaxContext) -> Span {
387387
HygieneData::with(|data| data.walk_chain(span, to))
388388
}
389389

390+
pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symbol) {
391+
// The new contexts that need updating are at the end of the list and have `$crate` as a name.
392+
let (len, to_update) = HygieneData::with(|data| (
393+
data.syntax_contexts.len(),
394+
data.syntax_contexts.iter().rev()
395+
.take_while(|scdata| scdata.dollar_crate_name == kw::DollarCrate).count()
396+
));
397+
// The callback must be called from outside of the `HygieneData` lock,
398+
// since it will try to acquire it too.
399+
let range_to_update = len - to_update .. len;
400+
let names: Vec<_> =
401+
range_to_update.clone().map(|idx| get_name(SyntaxContext::from_u32(idx as u32))).collect();
402+
HygieneData::with(|data| range_to_update.zip(names.into_iter()).for_each(|(idx, name)| {
403+
data.syntax_contexts[idx].dollar_crate_name = name;
404+
}))
405+
}
406+
390407
impl SyntaxContext {
391408
#[inline]
392409
pub const fn empty() -> Self {
@@ -614,17 +631,6 @@ impl SyntaxContext {
614631
pub fn dollar_crate_name(self) -> Symbol {
615632
HygieneData::with(|data| data.syntax_contexts[self.0 as usize].dollar_crate_name)
616633
}
617-
618-
pub fn set_dollar_crate_name(self, dollar_crate_name: Symbol) {
619-
HygieneData::with(|data| {
620-
let prev_dollar_crate_name = mem::replace(
621-
&mut data.syntax_contexts[self.0 as usize].dollar_crate_name, dollar_crate_name
622-
);
623-
assert!(dollar_crate_name == prev_dollar_crate_name ||
624-
prev_dollar_crate_name == kw::DollarCrate,
625-
"$crate name is reset for a syntax context");
626-
})
627-
}
628634
}
629635

630636
impl fmt::Debug for SyntaxContext {

src/test/ui/proc-macro/dollar-crate-issue-62325.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
//~ ERROR expected type, found `$`
2-
1+
// check-pass
32
// edition:2018
43
// aux-build:test-macros.rs
54

src/test/ui/proc-macro/dollar-crate-issue-62325.stderr

-4
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,56 @@
1-
PRINT-ATTR INPUT (DISPLAY): struct A(identity!($crate :: S));
2-
PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( identity ! ( $ crate :: S ) ) ;
1+
PRINT-ATTR INPUT (DISPLAY): struct A(identity!(crate :: S));
2+
PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ( identity ! ( crate :: S ) ) ;
33
PRINT-ATTR INPUT (DEBUG): TokenStream [
44
Ident {
55
ident: "struct",
6-
span: #0 bytes(0..0),
6+
span: #2 bytes(LO..HI),
77
},
88
Ident {
99
ident: "A",
10-
span: #0 bytes(0..0),
10+
span: #2 bytes(LO..HI),
1111
},
1212
Group {
1313
delimiter: Parenthesis,
1414
stream: TokenStream [
1515
Ident {
1616
ident: "identity",
17-
span: #0 bytes(0..0),
17+
span: #2 bytes(LO..HI),
1818
},
1919
Punct {
2020
ch: '!',
2121
spacing: Alone,
22-
span: #0 bytes(0..0),
22+
span: #2 bytes(LO..HI),
2323
},
2424
Group {
2525
delimiter: Parenthesis,
2626
stream: TokenStream [
27-
Punct {
28-
ch: '$',
29-
spacing: Alone,
30-
span: #0 bytes(0..0),
31-
},
3227
Ident {
33-
ident: "crate",
34-
span: #0 bytes(0..0),
28+
ident: "$crate",
29+
span: #2 bytes(LO..HI),
3530
},
3631
Punct {
3732
ch: ':',
3833
spacing: Joint,
39-
span: #0 bytes(0..0),
34+
span: #2 bytes(LO..HI),
4035
},
4136
Punct {
4237
ch: ':',
4338
spacing: Alone,
44-
span: #0 bytes(0..0),
39+
span: #2 bytes(LO..HI),
4540
},
4641
Ident {
4742
ident: "S",
48-
span: #0 bytes(0..0),
43+
span: #2 bytes(LO..HI),
4944
},
5045
],
51-
span: #0 bytes(0..0),
46+
span: #2 bytes(LO..HI),
5247
},
5348
],
54-
span: #0 bytes(0..0),
49+
span: #2 bytes(LO..HI),
5550
},
5651
Punct {
5752
ch: ';',
5853
spacing: Alone,
59-
span: #0 bytes(0..0),
54+
span: #2 bytes(LO..HI),
6055
},
6156
]

0 commit comments

Comments
 (0)