Auto merge of #42627 - michaelwoerister:no-ident-in-def-path, r=eddyb
incr.comp.: Don't use Ident in DefPath because that's unstable across compilation sessions Fixes https://github.com/rust-lang/rust/issues/42550. cc @jseyfried @nikomatsakis r? @eddyb
This commit is contained in:
commit
03abb1bd70
|
@ -2686,7 +2686,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
let parent_def = self.parent_def.unwrap();
|
let parent_def = self.parent_def.unwrap();
|
||||||
let def_id = {
|
let def_id = {
|
||||||
let defs = self.resolver.definitions();
|
let defs = self.resolver.definitions();
|
||||||
let def_path_data = DefPathData::Binding(Ident::with_empty_ctxt(name));
|
let def_path_data = DefPathData::Binding(name);
|
||||||
let def_index = defs
|
let def_index = defs
|
||||||
.create_def_with_parent(parent_def, id, def_path_data, REGULAR_SPACE, Mark::root());
|
.create_def_with_parent(parent_def, id, def_path_data, REGULAR_SPACE, Mark::root());
|
||||||
DefId::local(def_index)
|
DefId::local(def_index)
|
||||||
|
|
|
@ -15,6 +15,7 @@ use syntax::ast::*;
|
||||||
use syntax::ext::hygiene::Mark;
|
use syntax::ext::hygiene::Mark;
|
||||||
use syntax::visit;
|
use syntax::visit;
|
||||||
use syntax::symbol::keywords;
|
use syntax::symbol::keywords;
|
||||||
|
use syntax::symbol::Symbol;
|
||||||
|
|
||||||
use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE};
|
use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE};
|
||||||
|
|
||||||
|
@ -103,14 +104,14 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
DefPathData::Impl,
|
DefPathData::Impl,
|
||||||
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
|
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
|
||||||
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
|
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
|
||||||
DefPathData::TypeNs(i.ident.modern()),
|
DefPathData::TypeNs(i.ident.name),
|
||||||
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
|
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
|
||||||
return visit::walk_item(self, i);
|
return visit::walk_item(self, i);
|
||||||
}
|
}
|
||||||
ItemKind::Mod(..) => DefPathData::Module(i.ident.modern()),
|
ItemKind::Mod(..) => DefPathData::Module(i.ident.name),
|
||||||
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
|
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
|
||||||
DefPathData::ValueNs(i.ident.modern()),
|
DefPathData::ValueNs(i.ident.name),
|
||||||
ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.modern()),
|
ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name),
|
||||||
ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
|
ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
|
||||||
ItemKind::GlobalAsm(..) => DefPathData::Misc,
|
ItemKind::GlobalAsm(..) => DefPathData::Misc,
|
||||||
ItemKind::Use(ref view_path) => {
|
ItemKind::Use(ref view_path) => {
|
||||||
|
@ -138,13 +139,13 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
for v in &enum_definition.variants {
|
for v in &enum_definition.variants {
|
||||||
let variant_def_index =
|
let variant_def_index =
|
||||||
this.create_def(v.node.data.id(),
|
this.create_def(v.node.data.id(),
|
||||||
DefPathData::EnumVariant(v.node.name.modern()),
|
DefPathData::EnumVariant(v.node.name.name),
|
||||||
REGULAR_SPACE);
|
REGULAR_SPACE);
|
||||||
this.with_parent(variant_def_index, |this| {
|
this.with_parent(variant_def_index, |this| {
|
||||||
for (index, field) in v.node.data.fields().iter().enumerate() {
|
for (index, field) in v.node.data.fields().iter().enumerate() {
|
||||||
let ident = field.ident.map(Ident::modern)
|
let name = field.ident.map(|ident| ident.name)
|
||||||
.unwrap_or_else(|| Ident::from_str(&index.to_string()));
|
.unwrap_or_else(|| Symbol::intern(&index.to_string()));
|
||||||
this.create_def(field.id, DefPathData::Field(ident), REGULAR_SPACE);
|
this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref expr) = v.node.disr_expr {
|
if let Some(ref expr) = v.node.disr_expr {
|
||||||
|
@ -162,9 +163,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (index, field) in struct_def.fields().iter().enumerate() {
|
for (index, field) in struct_def.fields().iter().enumerate() {
|
||||||
let ident = field.ident.map(Ident::modern)
|
let name = field.ident.map(|ident| ident.name)
|
||||||
.unwrap_or_else(|| Ident::from_str(&index.to_string()));
|
.unwrap_or_else(|| Symbol::intern(&index.to_string()));
|
||||||
this.create_def(field.id, DefPathData::Field(ident), REGULAR_SPACE);
|
this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -175,7 +176,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
|
fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
|
||||||
let def = self.create_def(foreign_item.id,
|
let def = self.create_def(foreign_item.id,
|
||||||
DefPathData::ValueNs(foreign_item.ident.modern()),
|
DefPathData::ValueNs(foreign_item.ident.name),
|
||||||
REGULAR_SPACE);
|
REGULAR_SPACE);
|
||||||
|
|
||||||
self.with_parent(def, |this| {
|
self.with_parent(def, |this| {
|
||||||
|
@ -186,7 +187,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
fn visit_generics(&mut self, generics: &'a Generics) {
|
fn visit_generics(&mut self, generics: &'a Generics) {
|
||||||
for ty_param in generics.ty_params.iter() {
|
for ty_param in generics.ty_params.iter() {
|
||||||
self.create_def(ty_param.id,
|
self.create_def(ty_param.id,
|
||||||
DefPathData::TypeParam(ty_param.ident.modern()),
|
DefPathData::TypeParam(ty_param.ident.name),
|
||||||
REGULAR_SPACE);
|
REGULAR_SPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,8 +197,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
fn visit_trait_item(&mut self, ti: &'a TraitItem) {
|
fn visit_trait_item(&mut self, ti: &'a TraitItem) {
|
||||||
let def_data = match ti.node {
|
let def_data = match ti.node {
|
||||||
TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
|
TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
|
||||||
DefPathData::ValueNs(ti.ident.modern()),
|
DefPathData::ValueNs(ti.ident.name),
|
||||||
TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.modern()),
|
TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name),
|
||||||
TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
|
TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -214,8 +215,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
|
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
|
||||||
let def_data = match ii.node {
|
let def_data = match ii.node {
|
||||||
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
|
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
|
||||||
DefPathData::ValueNs(ii.ident.modern()),
|
DefPathData::ValueNs(ii.ident.name),
|
||||||
ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.modern()),
|
ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name),
|
||||||
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
|
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -236,7 +237,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false),
|
PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false),
|
||||||
PatKind::Ident(_, id, _) => {
|
PatKind::Ident(_, id, _) => {
|
||||||
let def = self.create_def(pat.id,
|
let def = self.create_def(pat.id,
|
||||||
DefPathData::Binding(id.node.modern()),
|
DefPathData::Binding(id.node.name),
|
||||||
REGULAR_SPACE);
|
REGULAR_SPACE);
|
||||||
self.parent_def = Some(def);
|
self.parent_def = Some(def);
|
||||||
}
|
}
|
||||||
|
@ -281,7 +282,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||||
|
|
||||||
fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) {
|
fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) {
|
||||||
self.create_def(def.lifetime.id,
|
self.create_def(def.lifetime.id,
|
||||||
DefPathData::LifetimeDef(def.lifetime.ident.modern()),
|
DefPathData::LifetimeDef(def.lifetime.ident.name),
|
||||||
REGULAR_SPACE);
|
REGULAR_SPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,8 @@ use rustc_data_structures::stable_hasher::StableHasher;
|
||||||
use serialize::{Encodable, Decodable, Encoder, Decoder};
|
use serialize::{Encodable, Decodable, Encoder, Decoder};
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use syntax::ast::{self, Ident};
|
use syntax::ast;
|
||||||
use syntax::ext::hygiene::{Mark, SyntaxContext};
|
use syntax::ext::hygiene::Mark;
|
||||||
use syntax::symbol::{Symbol, InternedString};
|
use syntax::symbol::{Symbol, InternedString};
|
||||||
use ty::TyCtxt;
|
use ty::TyCtxt;
|
||||||
use util::nodemap::NodeMap;
|
use util::nodemap::NodeMap;
|
||||||
|
@ -248,7 +248,39 @@ impl DefKey {
|
||||||
// and the special "root_parent" below.
|
// and the special "root_parent" below.
|
||||||
0u8.hash(&mut hasher);
|
0u8.hash(&mut hasher);
|
||||||
parent_hash.hash(&mut hasher);
|
parent_hash.hash(&mut hasher);
|
||||||
self.disambiguated_data.hash(&mut hasher);
|
|
||||||
|
let DisambiguatedDefPathData {
|
||||||
|
ref data,
|
||||||
|
disambiguator,
|
||||||
|
} = self.disambiguated_data;
|
||||||
|
|
||||||
|
::std::mem::discriminant(data).hash(&mut hasher);
|
||||||
|
match *data {
|
||||||
|
DefPathData::TypeNs(name) |
|
||||||
|
DefPathData::ValueNs(name) |
|
||||||
|
DefPathData::Module(name) |
|
||||||
|
DefPathData::MacroDef(name) |
|
||||||
|
DefPathData::TypeParam(name) |
|
||||||
|
DefPathData::LifetimeDef(name) |
|
||||||
|
DefPathData::EnumVariant(name) |
|
||||||
|
DefPathData::Binding(name) |
|
||||||
|
DefPathData::Field(name) |
|
||||||
|
DefPathData::GlobalMetaData(name) => {
|
||||||
|
(*name.as_str()).hash(&mut hasher);
|
||||||
|
}
|
||||||
|
|
||||||
|
DefPathData::Impl |
|
||||||
|
DefPathData::CrateRoot |
|
||||||
|
DefPathData::Misc |
|
||||||
|
DefPathData::ClosureExpr |
|
||||||
|
DefPathData::StructCtor |
|
||||||
|
DefPathData::Initializer |
|
||||||
|
DefPathData::ImplTrait |
|
||||||
|
DefPathData::Typeof => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
disambiguator.hash(&mut hasher);
|
||||||
|
|
||||||
DefPathHash(hasher.finish())
|
DefPathHash(hasher.finish())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,7 +386,7 @@ impl DefPath {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)]
|
||||||
pub enum DefPathData {
|
pub enum DefPathData {
|
||||||
// Root: these should only be used for the root nodes, because
|
// Root: these should only be used for the root nodes, because
|
||||||
// they are treated specially by the `def_path` function.
|
// they are treated specially by the `def_path` function.
|
||||||
|
@ -368,31 +400,31 @@ pub enum DefPathData {
|
||||||
/// An impl
|
/// An impl
|
||||||
Impl,
|
Impl,
|
||||||
/// Something in the type NS
|
/// Something in the type NS
|
||||||
TypeNs(Ident),
|
TypeNs(Symbol),
|
||||||
/// Something in the value NS
|
/// Something in the value NS
|
||||||
ValueNs(Ident),
|
ValueNs(Symbol),
|
||||||
/// A module declaration
|
/// A module declaration
|
||||||
Module(Ident),
|
Module(Symbol),
|
||||||
/// A macro rule
|
/// A macro rule
|
||||||
MacroDef(Ident),
|
MacroDef(Symbol),
|
||||||
/// A closure expression
|
/// A closure expression
|
||||||
ClosureExpr,
|
ClosureExpr,
|
||||||
|
|
||||||
// Subportions of items
|
// Subportions of items
|
||||||
/// A type parameter (generic parameter)
|
/// A type parameter (generic parameter)
|
||||||
TypeParam(Ident),
|
TypeParam(Symbol),
|
||||||
/// A lifetime definition
|
/// A lifetime definition
|
||||||
LifetimeDef(Ident),
|
LifetimeDef(Symbol),
|
||||||
/// A variant of a enum
|
/// A variant of a enum
|
||||||
EnumVariant(Ident),
|
EnumVariant(Symbol),
|
||||||
/// A struct field
|
/// A struct field
|
||||||
Field(Ident),
|
Field(Symbol),
|
||||||
/// Implicit ctor for a tuple-like struct
|
/// Implicit ctor for a tuple-like struct
|
||||||
StructCtor,
|
StructCtor,
|
||||||
/// Initializer for a const
|
/// Initializer for a const
|
||||||
Initializer,
|
Initializer,
|
||||||
/// Pattern binding
|
/// Pattern binding
|
||||||
Binding(Ident),
|
Binding(Symbol),
|
||||||
/// An `impl Trait` type node.
|
/// An `impl Trait` type node.
|
||||||
ImplTrait,
|
ImplTrait,
|
||||||
/// A `typeof` type node.
|
/// A `typeof` type node.
|
||||||
|
@ -401,7 +433,7 @@ pub enum DefPathData {
|
||||||
/// GlobalMetaData identifies a piece of crate metadata that is global to
|
/// GlobalMetaData identifies a piece of crate metadata that is global to
|
||||||
/// a whole crate (as opposed to just one item). GlobalMetaData components
|
/// a whole crate (as opposed to just one item). GlobalMetaData components
|
||||||
/// are only supposed to show up right below the crate root.
|
/// are only supposed to show up right below the crate root.
|
||||||
GlobalMetaData(Ident)
|
GlobalMetaData(Symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug,
|
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug,
|
||||||
|
@ -604,19 +636,19 @@ impl Definitions {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DefPathData {
|
impl DefPathData {
|
||||||
pub fn get_opt_ident(&self) -> Option<Ident> {
|
pub fn get_opt_name(&self) -> Option<Symbol> {
|
||||||
use self::DefPathData::*;
|
use self::DefPathData::*;
|
||||||
match *self {
|
match *self {
|
||||||
TypeNs(ident) |
|
TypeNs(name) |
|
||||||
ValueNs(ident) |
|
ValueNs(name) |
|
||||||
Module(ident) |
|
Module(name) |
|
||||||
MacroDef(ident) |
|
MacroDef(name) |
|
||||||
TypeParam(ident) |
|
TypeParam(name) |
|
||||||
LifetimeDef(ident) |
|
LifetimeDef(name) |
|
||||||
EnumVariant(ident) |
|
EnumVariant(name) |
|
||||||
Binding(ident) |
|
Binding(name) |
|
||||||
Field(ident) |
|
Field(name) |
|
||||||
GlobalMetaData(ident) => Some(ident),
|
GlobalMetaData(name) => Some(name),
|
||||||
|
|
||||||
Impl |
|
Impl |
|
||||||
CrateRoot |
|
CrateRoot |
|
||||||
|
@ -629,24 +661,20 @@ impl DefPathData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_opt_name(&self) -> Option<ast::Name> {
|
|
||||||
self.get_opt_ident().map(|ident| ident.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_interned_str(&self) -> InternedString {
|
pub fn as_interned_str(&self) -> InternedString {
|
||||||
use self::DefPathData::*;
|
use self::DefPathData::*;
|
||||||
let s = match *self {
|
let s = match *self {
|
||||||
TypeNs(ident) |
|
TypeNs(name) |
|
||||||
ValueNs(ident) |
|
ValueNs(name) |
|
||||||
Module(ident) |
|
Module(name) |
|
||||||
MacroDef(ident) |
|
MacroDef(name) |
|
||||||
TypeParam(ident) |
|
TypeParam(name) |
|
||||||
LifetimeDef(ident) |
|
LifetimeDef(name) |
|
||||||
EnumVariant(ident) |
|
EnumVariant(name) |
|
||||||
Binding(ident) |
|
Binding(name) |
|
||||||
Field(ident) |
|
Field(name) |
|
||||||
GlobalMetaData(ident) => {
|
GlobalMetaData(name) => {
|
||||||
return ident.name.as_str();
|
return name.as_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// note that this does not show up in user printouts
|
// note that this does not show up in user printouts
|
||||||
|
@ -669,29 +697,6 @@ impl DefPathData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for DefPathData {}
|
|
||||||
impl PartialEq for DefPathData {
|
|
||||||
fn eq(&self, other: &DefPathData) -> bool {
|
|
||||||
::std::mem::discriminant(self) == ::std::mem::discriminant(other) &&
|
|
||||||
self.get_opt_ident() == other.get_opt_ident()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::hash::Hash for DefPathData {
|
|
||||||
fn hash<H: ::std::hash::Hasher>(&self, hasher: &mut H) {
|
|
||||||
::std::mem::discriminant(self).hash(hasher);
|
|
||||||
if let Some(ident) = self.get_opt_ident() {
|
|
||||||
if ident.ctxt == SyntaxContext::empty() && ident.name == ident.name.interned() {
|
|
||||||
ident.name.as_str().hash(hasher)
|
|
||||||
} else {
|
|
||||||
// FIXME(jseyfried) implement stable hashing for idents with macros 2.0 hygiene info
|
|
||||||
ident.hash(hasher)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// We define the GlobalMetaDataKind enum with this macro because we want to
|
// We define the GlobalMetaDataKind enum with this macro because we want to
|
||||||
// make sure that we exhaustively iterate over all variants when registering
|
// make sure that we exhaustively iterate over all variants when registering
|
||||||
// the corresponding DefIndices in the DefTable.
|
// the corresponding DefIndices in the DefTable.
|
||||||
|
@ -712,7 +717,7 @@ macro_rules! define_global_metadata_kind {
|
||||||
definitions.create_def_with_parent(
|
definitions.create_def_with_parent(
|
||||||
CRATE_DEF_INDEX,
|
CRATE_DEF_INDEX,
|
||||||
ast::DUMMY_NODE_ID,
|
ast::DUMMY_NODE_ID,
|
||||||
DefPathData::GlobalMetaData(instance.ident()),
|
DefPathData::GlobalMetaData(instance.name()),
|
||||||
DefIndexAddressSpace::High,
|
DefIndexAddressSpace::High,
|
||||||
Mark::root()
|
Mark::root()
|
||||||
);
|
);
|
||||||
|
@ -726,7 +731,7 @@ macro_rules! define_global_metadata_kind {
|
||||||
let def_key = DefKey {
|
let def_key = DefKey {
|
||||||
parent: Some(CRATE_DEF_INDEX),
|
parent: Some(CRATE_DEF_INDEX),
|
||||||
disambiguated_data: DisambiguatedDefPathData {
|
disambiguated_data: DisambiguatedDefPathData {
|
||||||
data: DefPathData::GlobalMetaData(self.ident()),
|
data: DefPathData::GlobalMetaData(self.name()),
|
||||||
disambiguator: 0,
|
disambiguator: 0,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -734,7 +739,7 @@ macro_rules! define_global_metadata_kind {
|
||||||
def_path_table.key_to_index[&def_key]
|
def_path_table.key_to_index[&def_key]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ident(&self) -> Ident {
|
fn name(&self) -> Symbol {
|
||||||
|
|
||||||
let string = match *self {
|
let string = match *self {
|
||||||
$(
|
$(
|
||||||
|
@ -744,7 +749,7 @@ macro_rules! define_global_metadata_kind {
|
||||||
)*
|
)*
|
||||||
};
|
};
|
||||||
|
|
||||||
Ident::from_str(string)
|
Symbol::intern(string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue