Skip to content

Commit c646cda

Browse files
committed
Don't use gensym_if_underscore to resolve _ bindings
Instead generate unique `SyntaxContexts`
1 parent e35fbb3 commit c646cda

File tree

7 files changed

+56
-14
lines changed

7 files changed

+56
-14
lines changed

src/librustc/ich/impls_syntax.rs

+1
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::ExpnKind {
373373
Root,
374374
Macro(kind, descr),
375375
AstPass(kind),
376+
Underscore,
376377
Desugaring(kind)
377378
});
378379

src/librustc/lint/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,9 @@ pub fn provide(providers: &mut Providers<'_>) {
871871
pub fn in_external_macro(sess: &Session, span: Span) -> bool {
872872
let expn_data = span.ctxt().outer_expn_data();
873873
match expn_data.kind {
874-
ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
874+
ExpnKind::Root
875+
| ExpnKind::Underscore
876+
| ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
875877
ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
876878
ExpnKind::Macro(MacroKind::Bang, _) => {
877879
if expn_data.def_site.is_dummy() {

src/librustc_resolve/build_reduced_graph.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
406406
};
407407
match use_tree.kind {
408408
ast::UseTreeKind::Simple(rename, ..) => {
409-
let mut ident = use_tree.ident().gensym_if_underscore();
409+
let mut ident = use_tree.ident().unique_if_underscore();
410410
let mut module_path = prefix;
411411
let mut source = module_path.pop().unwrap();
412412
let mut type_ns_only = false;
@@ -584,7 +584,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
584584
let parent_scope = &self.parent_scope;
585585
let parent = parent_scope.module;
586586
let expansion = parent_scope.expansion;
587-
let ident = item.ident.gensym_if_underscore();
587+
let ident = item.ident.unique_if_underscore();
588588
let sp = item.span;
589589
let vis = self.resolve_visibility(&item.vis);
590590

@@ -849,10 +849,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
849849
fn build_reduced_graph_for_external_crate_res(&mut self, child: Export<NodeId>) {
850850
let parent = self.parent_scope.module;
851851
let Export { ident, res, vis, span } = child;
852-
// FIXME: We shouldn't create the gensym here, it should come from metadata,
853-
// but metadata cannot encode gensyms currently, so we create it here.
854-
// This is only a guess, two equivalent idents may incorrectly get different gensyms here.
855-
let ident = ident.gensym_if_underscore();
852+
// FIXME: We shouldn't create the SyntaxContext here, it should come from metadata,
853+
// but metadata doesn't encode hygiene information currently, so we create it here.
854+
// This is only a guess, two equivalent idents will get different SyntaxContexts here.
855+
let ident = ident.unique_if_underscore();
856856
let expansion = ExpnId::root(); // FIXME(jseyfried) intercrate hygiene
857857
// Record primary definitions.
858858
match res {

src/librustc_resolve/resolve_imports.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1340,7 +1340,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
13401340
// hygiene.
13411341
// FIXME: Implement actual cross-crate hygiene.
13421342
let is_good_import = binding.is_import() && !binding.is_ambiguity()
1343-
&& !ident.span.modern().from_expansion();
1343+
&& (!ident.span.from_expansion() || ident.name == kw::Underscore);
13441344
if is_good_import || binding.is_macro_def() {
13451345
let res = binding.res();
13461346
if res != Res::Err {
@@ -1350,8 +1350,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
13501350
}
13511351
}
13521352
reexports.push(Export {
1353-
ident: ident.modern(),
1354-
res: res,
1353+
ident,
1354+
res,
13551355
span: binding.span,
13561356
vis: binding.vis,
13571357
});
@@ -1418,6 +1418,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
14181418
}
14191419

14201420
if reexports.len() > 0 {
1421+
// Type pretty printing will prefer reexports that appear earlier
1422+
// in this map, so sort them to ensure that diagnostic output is
1423+
// stable.
1424+
reexports.sort_by_cached_key(|export| export.ident.as_str());
14211425
if let Some(def_id) = module.def_id() {
14221426
self.r.export_map.insert(def_id, reexports);
14231427
}

src/libsyntax_pos/hygiene.rs

+27-3
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,14 @@ impl HygieneData {
217217

218218
fn adjust(&self, ctxt: &mut SyntaxContext, expn_id: ExpnId) -> Option<ExpnId> {
219219
let mut scope = None;
220-
while !self.is_descendant_of(expn_id, self.outer_expn(*ctxt)) {
221-
scope = Some(self.remove_mark(ctxt).0);
220+
let mut outer = self.outer_expn(*ctxt);
221+
while !self.is_descendant_of(expn_id, outer) {
222+
if let ExpnData { kind: ExpnKind::Underscore, call_site, .. } = *self.expn_data(outer) {
223+
*ctxt = call_site.ctxt();
224+
} else {
225+
scope = Some(self.remove_mark(ctxt).0);
226+
}
227+
outer = self.outer_expn(*ctxt);
222228
}
223229
scope
224230
}
@@ -420,6 +426,21 @@ impl SyntaxContext {
420426
HygieneData::with(|data| data.marks(self))
421427
}
422428

429+
crate fn unique(base_span: Span) -> Self {
430+
HygieneData::with(|data| {
431+
// We store the original span as the call-site so that we can
432+
// recover it. We call `modern` here to save us calling it when we
433+
// access `call_site`.
434+
let modern = base_span.with_ctxt(data.modern(base_span.ctxt()));
435+
let expn_id = data.fresh_expn(Some(ExpnData::default(
436+
ExpnKind::Underscore,
437+
modern,
438+
data.expn_data(data.outer_expn(modern.ctxt())).edition,
439+
)));
440+
data.apply_mark(SyntaxContext::root(), expn_id, Transparency::Opaque)
441+
})
442+
}
443+
423444
/// Adjust this context for resolution in a scope created by the given expansion.
424445
/// For example, consider the following three resolutions of `f`:
425446
///
@@ -508,7 +529,7 @@ impl SyntaxContext {
508529
pub fn reverse_glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span)
509530
-> Option<Option<ExpnId>> {
510531
HygieneData::with(|data| {
511-
if data.adjust(self, expn_id).is_some() {
532+
if data.adjust(&mut {*self}, expn_id).is_some() {
512533
return None;
513534
}
514535

@@ -674,6 +695,8 @@ pub enum ExpnKind {
674695
Macro(MacroKind, Symbol),
675696
/// Transform done by the compiler on the AST.
676697
AstPass(AstPass),
698+
/// Generated by name resolution to give underscores unique identifiers.
699+
Underscore,
677700
/// Desugaring done by the compiler during HIR lowering.
678701
Desugaring(DesugaringKind)
679702
}
@@ -684,6 +707,7 @@ impl ExpnKind {
684707
ExpnKind::Root => kw::PathRoot,
685708
ExpnKind::Macro(_, descr) => descr,
686709
ExpnKind::AstPass(kind) => Symbol::intern(kind.descr()),
710+
ExpnKind::Underscore => kw::Underscore,
687711
ExpnKind::Desugaring(kind) => Symbol::intern(kind.descr()),
688712
}
689713
}

src/libsyntax_pos/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ impl Span {
443443
ExpnKind::Root => break,
444444
ExpnKind::Desugaring(..) => ("desugaring of ", ""),
445445
ExpnKind::AstPass(..) => ("", ""),
446+
ExpnKind::Underscore => ("", ""),
446447
ExpnKind::Macro(macro_kind, _) => match macro_kind {
447448
MacroKind::Bang => ("", "!"),
448449
MacroKind::Attr => ("#[", "]"),

src/libsyntax_pos/symbol.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::fmt;
1515
use std::hash::{Hash, Hasher};
1616
use std::str;
1717

18-
use crate::{Span, DUMMY_SP, GLOBALS};
18+
use crate::{Span, SyntaxContext, DUMMY_SP, GLOBALS};
1919

2020
#[cfg(test)]
2121
mod tests;
@@ -814,6 +814,16 @@ impl Ident {
814814
}
815815
}
816816

817+
/// If the name of this ident is "_", then return a new unique identifier.
818+
/// Otherwise returns `self` unmodified
819+
#[inline]
820+
pub fn unique_if_underscore(mut self) -> Ident {
821+
if self.name == kw::Underscore {
822+
self.span = self.span.with_ctxt(SyntaxContext::unique(self.span));
823+
}
824+
self
825+
}
826+
817827
/// Convert the name to a `LocalInternedString`. This is a slowish
818828
/// operation because it requires locking the symbol interner.
819829
pub fn as_str(self) -> LocalInternedString {

0 commit comments

Comments
 (0)