Skip to content

Commit af3d9e5

Browse files
authoredOct 15, 2019
Rollup merge of #64623 - matthewjasper:underscore-imports, r=petrochenkov
Remove last uses of gensyms Underscore bindings now use unique `SyntaxContext`s to avoid collisions. This was the last use of gensyms in the compiler, so this PR also removes them. closes #49300 cc #60869 r? @petrochenkov
·
1.88.01.40.0
2 parents fcef4b1 + 4198df1 commit af3d9e5

File tree

12 files changed

+247
-154
lines changed

12 files changed

+247
-154
lines changed
 

‎src/librustc/ty/print/pretty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1483,7 +1483,7 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
14831483
}
14841484

14851485
// Replace any anonymous late-bound regions with named
1486-
// variants, using gensym'd identifiers, so that we can
1486+
// variants, using new unique identifiers, so that we can
14871487
// clearly differentiate between named and unnamed regions in
14881488
// the output. We'll probably want to tweak this over time to
14891489
// decide just how much information to give.

‎src/librustc_resolve/build_reduced_graph.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ impl<'a> Resolver<'a> {
9494
where T: ToNameBinding<'a>,
9595
{
9696
let binding = def.to_name_binding(self.arenas);
97-
if let Err(old_binding) = self.try_define(parent, ident, ns, binding) {
97+
let key = self.new_key(ident, ns);
98+
if let Err(old_binding) = self.try_define(parent, key, binding) {
9899
self.report_conflict(parent, ident, ns, old_binding, &binding);
99100
}
100101
}
@@ -349,9 +350,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
349350

350351
self.r.indeterminate_imports.push(directive);
351352
match directive.subclass {
353+
// Don't add unresolved underscore imports to modules
354+
SingleImport { target: Ident { name: kw::Underscore, .. }, .. } => {}
352355
SingleImport { target, type_ns_only, .. } => {
353356
self.r.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
354-
let mut resolution = this.resolution(current_module, target, ns).borrow_mut();
357+
let key = this.new_key(target, ns);
358+
let mut resolution = this.resolution(current_module, key).borrow_mut();
355359
resolution.add_single_import(directive);
356360
});
357361
}
@@ -407,7 +411,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
407411
};
408412
match use_tree.kind {
409413
ast::UseTreeKind::Simple(rename, ..) => {
410-
let mut ident = use_tree.ident().gensym_if_underscore();
414+
let mut ident = use_tree.ident();
411415
let mut module_path = prefix;
412416
let mut source = module_path.pop().unwrap();
413417
let mut type_ns_only = false;
@@ -585,7 +589,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
585589
let parent_scope = &self.parent_scope;
586590
let parent = parent_scope.module;
587591
let expansion = parent_scope.expansion;
588-
let ident = item.ident.gensym_if_underscore();
592+
let ident = item.ident;
589593
let sp = item.span;
590594
let vis = self.resolve_visibility(&item.vis);
591595

@@ -851,10 +855,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
851855
fn build_reduced_graph_for_external_crate_res(&mut self, child: Export<NodeId>) {
852856
let parent = self.parent_scope.module;
853857
let Export { ident, res, vis, span } = child;
854-
// FIXME: We shouldn't create the gensym here, it should come from metadata,
855-
// but metadata cannot encode gensyms currently, so we create it here.
856-
// This is only a guess, two equivalent idents may incorrectly get different gensyms here.
857-
let ident = ident.gensym_if_underscore();
858858
let expansion = ExpnId::root(); // FIXME(jseyfried) intercrate hygiene
859859
// Record primary definitions.
860860
match res {

‎src/librustc_resolve/diagnostics.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,11 @@ impl<'a> Resolver<'a> {
8080
names: &mut Vec<TypoSuggestion>,
8181
filter_fn: &impl Fn(Res) -> bool,
8282
) {
83-
for (&(ident, _), resolution) in self.resolutions(module).borrow().iter() {
83+
for (key, resolution) in self.resolutions(module).borrow().iter() {
8484
if let Some(binding) = resolution.borrow().binding {
8585
let res = binding.res();
8686
if filter_fn(res) {
87-
names.push(TypoSuggestion::from_res(ident.name, res));
87+
names.push(TypoSuggestion::from_res(key.ident.name, res));
8888
}
8989
}
9090
}
@@ -849,7 +849,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
849849
}
850850

851851
let resolutions = self.r.resolutions(crate_module).borrow();
852-
let resolution = resolutions.get(&(ident, MacroNS))?;
852+
let resolution = resolutions.get(&self.r.new_key(ident, MacroNS))?;
853853
let binding = resolution.borrow().binding()?;
854854
if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {
855855
let module_name = crate_module.kind.name().unwrap();

‎src/librustc_resolve/lib.rs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,22 @@ impl ModuleKind {
432432
}
433433
}
434434

435-
type Resolutions<'a> = RefCell<FxIndexMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>;
435+
/// A key that identifies a binding in a given `Module`.
436+
///
437+
/// Multiple bindings in the same module can have the same key (in a valid
438+
/// program) if all but one of them come from glob imports.
439+
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
440+
struct BindingKey {
441+
/// The identifier for the binding, aways the `modern` version of the
442+
/// identifier.
443+
ident: Ident,
444+
ns: Namespace,
445+
/// 0 if ident is not `_`, otherwise a value that's unique to the specific
446+
/// `_` in the expanded AST that introduced this binding.
447+
disambiguator: u32,
448+
}
449+
450+
type Resolutions<'a> = RefCell<FxIndexMap<BindingKey, &'a RefCell<NameResolution<'a>>>>;
436451

437452
/// One node in the tree of modules.
438453
pub struct ModuleData<'a> {
@@ -492,8 +507,8 @@ impl<'a> ModuleData<'a> {
492507
fn for_each_child<R, F>(&'a self, resolver: &mut R, mut f: F)
493508
where R: AsMut<Resolver<'a>>, F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>)
494509
{
495-
for (&(ident, ns), name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
496-
name_resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding));
510+
for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
511+
name_resolution.borrow().binding.map(|binding| f(resolver, key.ident, key.ns, binding));
497512
}
498513
}
499514

@@ -882,6 +897,7 @@ pub struct Resolver<'a> {
882897
module_map: FxHashMap<DefId, Module<'a>>,
883898
extern_module_map: FxHashMap<DefId, Module<'a>>,
884899
binding_parent_modules: FxHashMap<PtrKey<'a, NameBinding<'a>>, Module<'a>>,
900+
underscore_disambiguator: u32,
885901

886902
/// Maps glob imports to the names of items actually imported.
887903
pub glob_map: GlobMap,
@@ -1160,6 +1176,7 @@ impl<'a> Resolver<'a> {
11601176
extern_crate_map: Default::default(),
11611177
export_map: FxHashMap::default(),
11621178
trait_map: Default::default(),
1179+
underscore_disambiguator: 0,
11631180
empty_module,
11641181
module_map,
11651182
block_map: Default::default(),
@@ -1284,6 +1301,17 @@ impl<'a> Resolver<'a> {
12841301
self.arenas.alloc_module(module)
12851302
}
12861303

1304+
fn new_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
1305+
let ident = ident.modern();
1306+
let disambiguator = if ident.name == kw::Underscore {
1307+
self.underscore_disambiguator += 1;
1308+
self.underscore_disambiguator
1309+
} else {
1310+
0
1311+
};
1312+
BindingKey { ident, ns, disambiguator }
1313+
}
1314+
12871315
fn resolutions(&mut self, module: Module<'a>) -> &'a Resolutions<'a> {
12881316
if module.populate_on_access.get() {
12891317
module.populate_on_access.set(false);
@@ -1292,9 +1320,9 @@ impl<'a> Resolver<'a> {
12921320
&module.lazy_resolutions
12931321
}
12941322

1295-
fn resolution(&mut self, module: Module<'a>, ident: Ident, ns: Namespace)
1323+
fn resolution(&mut self, module: Module<'a>, key: BindingKey)
12961324
-> &'a RefCell<NameResolution<'a>> {
1297-
*self.resolutions(module).borrow_mut().entry((ident.modern(), ns))
1325+
*self.resolutions(module).borrow_mut().entry(key)
12981326
.or_insert_with(|| self.arenas.alloc_name_resolution())
12991327
}
13001328

‎src/librustc_resolve/resolve_imports.rs

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, ParentScope
77
use crate::Determinacy::{self, *};
88
use crate::Namespace::{self, TypeNS, MacroNS};
99
use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
10-
use crate::{Resolver, ResolutionError, Segment, ModuleKind};
10+
use crate::{Resolver, ResolutionError, BindingKey, Segment, ModuleKind};
1111
use crate::{names_to_string, module_to_string};
1212
use crate::diagnostics::Suggestion;
1313

@@ -235,7 +235,8 @@ impl<'a> Resolver<'a> {
235235
}
236236
};
237237

238-
let resolution = self.resolution(module, ident, ns)
238+
let key = self.new_key(ident, ns);
239+
let resolution = self.resolution(module, key)
239240
.try_borrow_mut()
240241
.map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports.
241242

@@ -447,17 +448,16 @@ impl<'a> Resolver<'a> {
447448
}
448449

449450
// Define the name or return the existing binding if there is a collision.
450-
pub fn try_define(
451+
crate fn try_define(
451452
&mut self,
452453
module: Module<'a>,
453-
ident: Ident,
454-
ns: Namespace,
454+
key: BindingKey,
455455
binding: &'a NameBinding<'a>,
456456
) -> Result<(), &'a NameBinding<'a>> {
457457
let res = binding.res();
458-
self.check_reserved_macro_name(ident, res);
458+
self.check_reserved_macro_name(key.ident, res);
459459
self.set_binding_parent_module(binding, module);
460-
self.update_resolution(module, ident, ns, |this, resolution| {
460+
self.update_resolution(module, key, |this, resolution| {
461461
if let Some(old_binding) = resolution.binding {
462462
if res == Res::Err {
463463
// Do not override real bindings with `Res::Err`s from error recovery.
@@ -479,8 +479,9 @@ impl<'a> Resolver<'a> {
479479
} else {
480480
(binding, old_binding)
481481
};
482-
if glob_binding.res() != nonglob_binding.res() &&
483-
ns == MacroNS && nonglob_binding.expansion != ExpnId::root() {
482+
if glob_binding.res() != nonglob_binding.res()
483+
&& key.ns == MacroNS && nonglob_binding.expansion != ExpnId::root()
484+
{
484485
resolution.binding = Some(this.ambiguity(
485486
AmbiguityKind::GlobVsExpanded,
486487
nonglob_binding,
@@ -499,9 +500,9 @@ impl<'a> Resolver<'a> {
499500
DUPLICATE_MACRO_EXPORTS,
500501
CRATE_NODE_ID,
501502
binding.span,
502-
&format!("a macro named `{}` has already been exported", ident),
503+
&format!("a macro named `{}` has already been exported", key.ident),
503504
BuiltinLintDiagnostics::DuplicatedMacroExports(
504-
ident, old_binding.span, binding.span));
505+
key.ident, old_binding.span, binding.span));
505506

506507
resolution.binding = Some(binding);
507508
} else {
@@ -531,17 +532,17 @@ impl<'a> Resolver<'a> {
531532
// Use `f` to mutate the resolution of the name in the module.
532533
// If the resolution becomes a success, define it in the module's glob importers.
533534
fn update_resolution<T, F>(
534-
&mut self, module: Module<'a>,
535-
ident: Ident,
536-
ns: Namespace,
535+
&mut self,
536+
module: Module<'a>,
537+
key: BindingKey,
537538
f: F,
538539
) -> T
539540
where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T
540541
{
541542
// Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
542543
// during which the resolution might end up getting re-defined via a glob cycle.
543544
let (binding, t) = {
544-
let resolution = &mut *self.resolution(module, ident, ns).borrow_mut();
545+
let resolution = &mut *self.resolution(module, key).borrow_mut();
545546
let old_binding = resolution.binding();
546547

547548
let t = f(self, resolution);
@@ -558,15 +559,16 @@ impl<'a> Resolver<'a> {
558559

559560
// Define `binding` in `module`s glob importers.
560561
for directive in module.glob_importers.borrow_mut().iter() {
561-
let mut ident = ident.modern();
562+
let mut ident = key.ident;
562563
let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) {
563564
Some(Some(def)) => self.macro_def_scope(def),
564565
Some(None) => directive.parent_scope.module,
565566
None => continue,
566567
};
567568
if self.is_accessible_from(binding.vis, scope) {
568569
let imported_binding = self.import(binding, directive);
569-
let _ = self.try_define(directive.parent_scope.module, ident, ns, imported_binding);
570+
let key = BindingKey { ident, ..key };
571+
let _ = self.try_define(directive.parent_scope.module, key, imported_binding);
570572
}
571573
}
572574

@@ -580,7 +582,8 @@ impl<'a> Resolver<'a> {
580582
let dummy_binding = self.dummy_binding;
581583
let dummy_binding = self.import(dummy_binding, directive);
582584
self.per_ns(|this, ns| {
583-
let _ = this.try_define(directive.parent_scope.module, target, ns, dummy_binding);
585+
let key = this.new_key(target, ns);
586+
let _ = this.try_define(directive.parent_scope.module, key, dummy_binding);
584587
// Consider erroneous imports used to avoid duplicate diagnostics.
585588
this.record_use(target, ns, dummy_binding, false);
586589
});
@@ -820,8 +823,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
820823
let parent = directive.parent_scope.module;
821824
match source_bindings[ns].get() {
822825
Err(Undetermined) => indeterminate = true,
826+
// Don't update the resolution, because it was never added.
827+
Err(Determined) if target.name == kw::Underscore => {}
823828
Err(Determined) => {
824-
this.update_resolution(parent, target, ns, |_, resolution| {
829+
let key = this.new_key(target, ns);
830+
this.update_resolution(parent, key, |_, resolution| {
825831
resolution.single_imports.remove(&PtrKey(directive));
826832
});
827833
}
@@ -1052,7 +1058,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
10521058
_ => None,
10531059
};
10541060
let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
1055-
let names = resolutions.filter_map(|(&(ref i, _), resolution)| {
1061+
let names = resolutions.filter_map(|(BindingKey { ident: i, .. }, resolution)| {
10561062
if *i == ident { return None; } // Never suggest the same name
10571063
match *resolution.borrow() {
10581064
NameResolution { binding: Some(name_binding), .. } => {
@@ -1301,19 +1307,18 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
13011307

13021308
// Ensure that `resolutions` isn't borrowed during `try_define`,
13031309
// since it might get updated via a glob cycle.
1304-
let bindings = self.r.resolutions(module).borrow().iter().filter_map(|(ident, resolution)| {
1305-
resolution.borrow().binding().map(|binding| (*ident, binding))
1310+
let bindings = self.r.resolutions(module).borrow().iter().filter_map(|(key, resolution)| {
1311+
resolution.borrow().binding().map(|binding| (*key, binding))
13061312
}).collect::<Vec<_>>();
1307-
for ((mut ident, ns), binding) in bindings {
1308-
let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) {
1313+
for (mut key, binding) in bindings {
1314+
let scope = match key.ident.span.reverse_glob_adjust(module.expansion, directive.span) {
13091315
Some(Some(def)) => self.r.macro_def_scope(def),
13101316
Some(None) => directive.parent_scope.module,
13111317
None => continue,
13121318
};
13131319
if self.r.is_accessible_from(binding.pseudo_vis(), scope) {
13141320
let imported_binding = self.r.import(binding, directive);
1315-
let _ =
1316-
self.r.try_define(directive.parent_scope.module, ident, ns, imported_binding);
1321+
let _ = self.r.try_define(directive.parent_scope.module, key, imported_binding);
13171322
}
13181323
}
13191324

@@ -1329,29 +1334,23 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
13291334

13301335
let mut reexports = Vec::new();
13311336

1332-
for (&(ident, ns), resolution) in self.r.resolutions(module).borrow().iter() {
1333-
let resolution = &mut *resolution.borrow_mut();
1334-
let binding = match resolution.binding {
1335-
Some(binding) => binding,
1336-
None => continue,
1337-
};
1338-
1337+
module.for_each_child(self.r, |this, ident, ns, binding| {
13391338
// Filter away ambiguous imports and anything that has def-site
13401339
// hygiene.
13411340
// FIXME: Implement actual cross-crate hygiene.
13421341
let is_good_import = binding.is_import() && !binding.is_ambiguity()
1343-
&& !ident.span.modern().from_expansion();
1342+
&& !ident.span.from_expansion();
13441343
if is_good_import || binding.is_macro_def() {
13451344
let res = binding.res();
13461345
if res != Res::Err {
13471346
if let Some(def_id) = res.opt_def_id() {
13481347
if !def_id.is_local() {
1349-
self.r.cstore.export_macros_untracked(def_id.krate);
1348+
this.cstore.export_macros_untracked(def_id.krate);
13501349
}
13511350
}
13521351
reexports.push(Export {
1353-
ident: ident.modern(),
1354-
res: res,
1352+
ident,
1353+
res,
13551354
span: binding.span,
13561355
vis: binding.vis,
13571356
});
@@ -1360,7 +1359,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
13601359

13611360
if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind {
13621361
if ns == TypeNS && orig_binding.is_variant() &&
1363-
!orig_binding.vis.is_at_least(binding.vis, &*self) {
1362+
!orig_binding.vis.is_at_least(binding.vis, &*this) {
13641363
let msg = match directive.subclass {
13651364
ImportDirectiveSubclass::SingleImport { .. } => {
13661365
format!("variant `{}` is private and cannot be re-exported",
@@ -1372,41 +1371,42 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
13721371
let error_id = (DiagnosticMessageId::ErrorId(0), // no code?!
13731372
Some(binding.span),
13741373
msg.clone());
1375-
let fresh = self.r.session.one_time_diagnostics
1374+
let fresh = this.session.one_time_diagnostics
13761375
.borrow_mut().insert(error_id);
13771376
if !fresh {
1378-
continue;
1377+
return;
13791378
}
13801379
msg
13811380
},
13821381
ref s @ _ => bug!("unexpected import subclass {:?}", s)
13831382
};
1384-
let mut err = self.r.session.struct_span_err(binding.span, &msg);
1383+
let mut err = this.session.struct_span_err(binding.span, &msg);
13851384

13861385
let imported_module = match directive.imported_module.get() {
13871386
Some(ModuleOrUniformRoot::Module(module)) => module,
13881387
_ => bug!("module should exist"),
13891388
};
13901389
let parent_module = imported_module.parent.expect("parent should exist");
1391-
let resolutions = self.r.resolutions(parent_module).borrow();
1390+
let resolutions = this.resolutions(parent_module).borrow();
13921391
let enum_path_segment_index = directive.module_path.len() - 1;
13931392
let enum_ident = directive.module_path[enum_path_segment_index].ident;
13941393

1395-
let enum_resolution = resolutions.get(&(enum_ident, TypeNS))
1394+
let key = this.new_key(enum_ident, TypeNS);
1395+
let enum_resolution = resolutions.get(&key)
13961396
.expect("resolution should exist");
13971397
let enum_span = enum_resolution.borrow()
13981398
.binding.expect("binding should exist")
13991399
.span;
1400-
let enum_def_span = self.r.session.source_map().def_span(enum_span);
1401-
let enum_def_snippet = self.r.session.source_map()
1400+
let enum_def_span = this.session.source_map().def_span(enum_span);
1401+
let enum_def_snippet = this.session.source_map()
14021402
.span_to_snippet(enum_def_span).expect("snippet should exist");
14031403
// potentially need to strip extant `crate`/`pub(path)` for suggestion
14041404
let after_vis_index = enum_def_snippet.find("enum")
14051405
.expect("`enum` keyword should exist in snippet");
14061406
let suggestion = format!("pub {}",
14071407
&enum_def_snippet[after_vis_index..]);
14081408

1409-
self.r.session
1409+
this.session
14101410
.diag_span_suggestion_once(&mut err,
14111411
DiagnosticMessageId::ErrorId(0),
14121412
enum_def_span,
@@ -1415,7 +1415,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
14151415
err.emit();
14161416
}
14171417
}
1418-
}
1418+
});
14191419

14201420
if reexports.len() > 0 {
14211421
if let Some(def_id) = module.def_id() {

‎src/libsyntax/ext/proc_macro_server.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,7 @@ impl Ident {
334334
if !Self::is_valid(&string) {
335335
panic!("`{:?}` is not a valid identifier", string)
336336
}
337-
// Get rid of gensyms to conservatively check rawness on the string contents only.
338-
if is_raw && !sym.as_interned_str().as_symbol().can_be_raw() {
337+
if is_raw && !sym.can_be_raw() {
339338
panic!("`{}` cannot be a raw identifier", string);
340339
}
341340
Ident { sym, is_raw, span }

‎src/libsyntax_pos/symbol.rs

Lines changed: 9 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -808,25 +808,13 @@ impl Ident {
808808
Ident::new(self.name, self.span.modern_and_legacy())
809809
}
810810

811-
/// Transforms an underscore identifier into one with the same name, but
812-
/// gensymed. Leaves non-underscore identifiers unchanged.
813-
pub fn gensym_if_underscore(self) -> Ident {
814-
if self.name == kw::Underscore {
815-
let name = with_interner(|interner| interner.gensymed(self.name));
816-
Ident::new(name, self.span)
817-
} else {
818-
self
819-
}
820-
}
821-
822811
/// Convert the name to a `LocalInternedString`. This is a slowish
823812
/// operation because it requires locking the symbol interner.
824813
pub fn as_str(self) -> LocalInternedString {
825814
self.name.as_str()
826815
}
827816

828-
/// Convert the name to an `InternedString`. This is a slowish operation
829-
/// because it requires locking the symbol interner.
817+
/// Convert the name to an `InternedString`.
830818
pub fn as_interned_str(self) -> InternedString {
831819
self.name.as_interned_str()
832820
}
@@ -881,26 +869,9 @@ impl UseSpecializedDecodable for Ident {
881869
}
882870
}
883871

884-
/// A symbol is an interned or gensymed string. A gensym is a symbol that is
885-
/// never equal to any other symbol.
872+
/// An interned string.
886873
///
887-
/// Conceptually, a gensym can be thought of as a normal symbol with an
888-
/// invisible unique suffix. Gensyms are useful when creating new identifiers
889-
/// that must not match any existing identifiers, e.g. during macro expansion
890-
/// and syntax desugaring. Because gensyms should always be identifiers, all
891-
/// gensym operations are on `Ident` rather than `Symbol`. (Indeed, in the
892-
/// future the gensym-ness may be moved from `Symbol` to hygiene data.)
893-
///
894-
/// Examples:
895-
/// ```
896-
/// assert_eq!(Ident::from_str("_"), Ident::from_str("_"))
897-
/// assert_ne!(Ident::from_str("_").gensym_if_underscore(), Ident::from_str("_"))
898-
/// assert_ne!(
899-
/// Ident::from_str("_").gensym_if_underscore(),
900-
/// Ident::from_str("_").gensym_if_underscore(),
901-
/// )
902-
/// ```
903-
/// Internally, a symbol is implemented as an index, and all operations
874+
/// Internally, a `Symbol` is implemented as an index, and all operations
904875
/// (including hashing, equality, and ordering) operate on that index. The use
905876
/// of `rustc_index::newtype_index!` means that `Option<Symbol>` only takes up 4 bytes,
906877
/// because `rustc_index::newtype_index!` reserves the last 256 values for tagging purposes.
@@ -951,12 +922,9 @@ impl Symbol {
951922
})
952923
}
953924

954-
/// Convert to an `InternedString`. This is a slowish operation because it
955-
/// requires locking the symbol interner.
925+
/// Convert to an `InternedString`.
956926
pub fn as_interned_str(self) -> InternedString {
957-
with_interner(|interner| InternedString {
958-
symbol: interner.interned(self)
959-
})
927+
InternedString { symbol: self }
960928
}
961929

962930
pub fn as_u32(self) -> u32 {
@@ -966,12 +934,7 @@ impl Symbol {
966934

967935
impl fmt::Debug for Symbol {
968936
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
969-
let is_gensymed = with_interner(|interner| interner.is_gensymed(*self));
970-
if is_gensymed {
971-
write!(f, "{}({:?})", self, self.0)
972-
} else {
973-
write!(f, "{}", self)
974-
}
937+
fmt::Display::fmt(self, f)
975938
}
976939
}
977940

@@ -994,15 +957,11 @@ impl Decodable for Symbol {
994957
}
995958

996959
// The `&'static str`s in this type actually point into the arena.
997-
//
998-
// Note that normal symbols are indexed upward from 0, and gensyms are indexed
999-
// downward from SymbolIndex::MAX_AS_U32.
1000960
#[derive(Default)]
1001961
pub struct Interner {
1002962
arena: DroplessArena,
1003963
names: FxHashMap<&'static str, Symbol>,
1004964
strings: Vec<&'static str>,
1005-
gensyms: Vec<Symbol>,
1006965
}
1007966

1008967
impl Interner {
@@ -1035,34 +994,10 @@ impl Interner {
1035994
self.names.insert(string, name);
1036995
name
1037996
}
1038-
1039-
fn interned(&self, symbol: Symbol) -> Symbol {
1040-
if (symbol.0.as_usize()) < self.strings.len() {
1041-
symbol
1042-
} else {
1043-
self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]
1044-
}
1045-
}
1046-
1047-
fn gensymed(&mut self, symbol: Symbol) -> Symbol {
1048-
self.gensyms.push(symbol);
1049-
Symbol::new(SymbolIndex::MAX_AS_U32 - self.gensyms.len() as u32 + 1)
1050-
}
1051-
1052-
fn is_gensymed(&mut self, symbol: Symbol) -> bool {
1053-
symbol.0.as_usize() >= self.strings.len()
1054-
}
1055-
1056997
// Get the symbol as a string. `Symbol::as_str()` should be used in
1057998
// preference to this function.
1058999
pub fn get(&self, symbol: Symbol) -> &str {
1059-
match self.strings.get(symbol.0.as_usize()) {
1060-
Some(string) => string,
1061-
None => {
1062-
let symbol = self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize];
1063-
self.strings[symbol.0.as_usize()]
1064-
}
1065-
}
1000+
self.strings[symbol.0.as_usize()]
10661001
}
10671002
}
10681003

@@ -1223,19 +1158,12 @@ impl fmt::Display for LocalInternedString {
12231158
}
12241159
}
12251160

1226-
/// An alternative to `Symbol` that is focused on string contents. It has two
1227-
/// main differences to `Symbol`.
1161+
/// An alternative to `Symbol` that is focused on string contents.
12281162
///
1229-
/// First, its implementations of `Hash`, `PartialOrd` and `Ord` work with the
1163+
/// Its implementations of `Hash`, `PartialOrd` and `Ord` work with the
12301164
/// string chars rather than the symbol integer. This is useful when hash
12311165
/// stability is required across compile sessions, or a guaranteed sort
12321166
/// ordering is required.
1233-
///
1234-
/// Second, gensym-ness is irrelevant. E.g.:
1235-
/// ```
1236-
/// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x"))
1237-
/// assert_eq!(Symbol::gensym("x").as_interned_str(), Symbol::gensym("x").as_interned_str())
1238-
/// ```
12391167
#[derive(Clone, Copy, PartialEq, Eq)]
12401168
pub struct InternedString {
12411169
symbol: Symbol,

‎src/libsyntax_pos/symbol/tests.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,6 @@ fn interner_tests() {
1414
assert_eq!(i.intern("cat"), Symbol::new(1));
1515
// dog is still at zero
1616
assert_eq!(i.intern("dog"), Symbol::new(0));
17-
let z = i.intern("zebra");
18-
assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32));
19-
// gensym of same string gets new number:
20-
assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32 - 1));
21-
// gensym of *existing* string gets new number:
22-
let d = i.intern("dog");
23-
assert_eq!(i.gensymed(d), Symbol::new(SymbolIndex::MAX_AS_U32 - 2));
2417
}
2518

2619
#[test]
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Make sure that underscore imports with different contexts can exist in the
2+
// same scope.
3+
4+
// check-pass
5+
6+
#![feature(decl_macro)]
7+
8+
mod x {
9+
pub use std::ops::Deref as _;
10+
}
11+
12+
macro n() {
13+
pub use crate::x::*;
14+
}
15+
16+
#[macro_export]
17+
macro_rules! p {
18+
() => { pub use crate::x::*; }
19+
}
20+
21+
macro m($y:ident) {
22+
mod $y {
23+
crate::n!(); // Reexport of `Deref` should not be imported in `main`
24+
crate::p!(); // Reexport of `Deref` should be imported into `main`
25+
}
26+
}
27+
28+
m!(y);
29+
30+
fn main() {
31+
use crate::y::*;
32+
(&()).deref();
33+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Make sure that underscore imports have the same hygiene considerations as
2+
// other imports.
3+
4+
#![feature(decl_macro)]
5+
6+
mod x {
7+
pub use std::ops::Deref as _;
8+
}
9+
10+
11+
macro glob_import() {
12+
pub use crate::x::*;
13+
}
14+
15+
macro underscore_import() {
16+
use std::ops::DerefMut as _;
17+
}
18+
19+
mod y {
20+
crate::glob_import!();
21+
crate::underscore_import!();
22+
}
23+
24+
macro create_module($y:ident) {
25+
mod $y {
26+
crate::glob_import!();
27+
crate::underscore_import!();
28+
}
29+
}
30+
31+
create_module!(z);
32+
33+
fn main() {
34+
use crate::y::*;
35+
use crate::z::*;
36+
glob_import!();
37+
underscore_import!();
38+
(&()).deref(); //~ ERROR no method named `deref`
39+
(&mut ()).deref_mut(); //~ ERROR no method named `deref_mut`
40+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error[E0599]: no method named `deref` found for type `&()` in the current scope
2+
--> $DIR/hygiene.rs:38:11
3+
|
4+
LL | (&()).deref();
5+
| ^^^^^ method not found in `&()`
6+
|
7+
= help: items from traits can only be used if the trait is in scope
8+
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
9+
|
10+
LL | use std::ops::Deref;
11+
|
12+
13+
error[E0599]: no method named `deref_mut` found for type `&mut ()` in the current scope
14+
--> $DIR/hygiene.rs:39:15
15+
|
16+
LL | (&mut ()).deref_mut();
17+
| ^^^^^^^^^ method not found in `&mut ()`
18+
|
19+
= help: items from traits can only be used if the trait is in scope
20+
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
21+
|
22+
LL | use std::ops::DerefMut;
23+
|
24+
25+
error: aborting due to 2 previous errors
26+
27+
For more information about this error, try `rustc --explain E0599`.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Check that macro expanded underscore imports behave as expected
2+
3+
// check-pass
4+
5+
#![feature(decl_macro, rustc_attrs)]
6+
7+
mod x {
8+
pub use std::ops::Not as _;
9+
}
10+
11+
macro m() {
12+
mod w {
13+
mod y {
14+
pub use std::ops::Deref as _;
15+
}
16+
use crate::x::*;
17+
use self::y::*;
18+
use std::ops::DerefMut as _;
19+
fn f() {
20+
false.not();
21+
(&()).deref();
22+
(&mut ()).deref_mut();
23+
}
24+
}
25+
}
26+
27+
#[rustc_macro_transparency = "transparent"]
28+
macro n() {
29+
mod z {
30+
pub use std::ops::Deref as _;
31+
}
32+
use crate::x::*;
33+
use crate::z::*;
34+
use std::ops::DerefMut as _;
35+
fn f() {
36+
false.not();
37+
(&()).deref();
38+
(&mut ()).deref_mut();
39+
}
40+
}
41+
42+
m!();
43+
n!();
44+
45+
fn main() {}

0 commit comments

Comments
 (0)
Please sign in to comment.