Hygienize librustc_typeck.

This commit is contained in:
Jeffrey Seyfried 2017-03-24 23:03:15 +00:00
parent 1f175fa35d
commit bfa2ef62a1
14 changed files with 170 additions and 61 deletions

View file

@ -47,7 +47,7 @@ use hir::def_id::{DefIndex, DefId, CRATE_DEF_INDEX};
use hir::def::{Def, PathResolution};
use rustc_data_structures::indexed_vec::IndexVec;
use session::Session;
use util::nodemap::{DefIdMap, NodeMap};
use util::nodemap::{DefIdMap, FxHashMap, NodeMap};
use std::collections::BTreeMap;
use std::fmt::Debug;
@ -77,6 +77,7 @@ pub struct LoweringContext<'a> {
// a definition, then we can properly create the def id.
parent_def: Option<DefIndex>,
resolver: &'a mut Resolver,
name_map: FxHashMap<Ident, Name>,
/// The items being lowered are collected here.
items: BTreeMap<NodeId, hir::Item>,
@ -126,6 +127,7 @@ pub fn lower_crate(sess: &Session,
sess: sess,
parent_def: None,
resolver: resolver,
name_map: FxHashMap(),
items: BTreeMap::new(),
trait_items: BTreeMap::new(),
impl_items: BTreeMap::new(),
@ -495,6 +497,14 @@ impl<'a> LoweringContext<'a> {
}
}
fn lower_ident(&mut self, ident: Ident) -> Name {
let ident = ident.modern();
if ident.ctxt == SyntaxContext::empty() {
return ident.name;
}
*self.name_map.entry(ident).or_insert_with(|| Symbol::from_ident(ident))
}
fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned<Name>> {
o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
}
@ -546,7 +556,7 @@ impl<'a> LoweringContext<'a> {
fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding {
hir::TypeBinding {
id: self.lower_node_id(b.id),
name: b.ident.name,
name: self.lower_ident(b.ident),
ty: self.lower_ty(&b.ty),
span: b.span,
}
@ -844,7 +854,7 @@ impl<'a> LoweringContext<'a> {
}
hir::PathSegment {
name: segment.identifier.name,
name: self.lower_ident(segment.identifier),
parameters: parameters,
}
}
@ -941,7 +951,7 @@ impl<'a> LoweringContext<'a> {
}
fn lower_ty_param(&mut self, tp: &TyParam, add_bounds: &[TyParamBound]) -> hir::TyParam {
let mut name = tp.ident.name;
let mut name = self.lower_ident(tp.ident);
// Don't expose `Self` (recovered "keyword used as ident" parse error).
// `rustc::ty` expects `Self` to be only used for a trait's `Self`.
@ -1137,7 +1147,11 @@ impl<'a> LoweringContext<'a> {
hir::StructField {
span: f.span,
id: self.lower_node_id(f.id),
name: f.ident.map(|ident| ident.name).unwrap_or(Symbol::intern(&index.to_string())),
name: self.lower_ident(match f.ident {
Some(ident) => ident,
// FIXME(jseyfried) positional field hygiene
None => Ident { name: Symbol::intern(&index.to_string()), ctxt: f.span.ctxt },
}),
vis: self.lower_visibility(&f.vis, None),
ty: self.lower_ty(&f.ty),
attrs: self.lower_attrs(&f.attrs),
@ -1146,7 +1160,7 @@ impl<'a> LoweringContext<'a> {
fn lower_field(&mut self, f: &Field) -> hir::Field {
hir::Field {
name: respan(f.ident.span, f.ident.node.name),
name: respan(f.ident.span, self.lower_ident(f.ident.node)),
expr: P(self.lower_expr(&f.expr)),
span: f.span,
is_shorthand: f.is_shorthand,
@ -1371,7 +1385,7 @@ impl<'a> LoweringContext<'a> {
self.with_parent_def(i.id, |this| {
hir::TraitItem {
id: this.lower_node_id(i.id),
name: i.ident.name,
name: this.lower_ident(i.ident),
attrs: this.lower_attrs(&i.attrs),
node: match i.node {
TraitItemKind::Const(ref ty, ref default) => {
@ -1421,7 +1435,7 @@ impl<'a> LoweringContext<'a> {
};
hir::TraitItemRef {
id: hir::TraitItemId { node_id: i.id },
name: i.ident.name,
name: self.lower_ident(i.ident),
span: i.span,
defaultness: self.lower_defaultness(Defaultness::Default, has_default),
kind: kind,
@ -1432,7 +1446,7 @@ impl<'a> LoweringContext<'a> {
self.with_parent_def(i.id, |this| {
hir::ImplItem {
id: this.lower_node_id(i.id),
name: i.ident.name,
name: this.lower_ident(i.ident),
attrs: this.lower_attrs(&i.attrs),
vis: this.lower_visibility(&i.vis, None),
defaultness: this.lower_defaultness(i.defaultness, true /* [1] */),
@ -1461,7 +1475,7 @@ impl<'a> LoweringContext<'a> {
fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
hir::ImplItemRef {
id: hir::ImplItemId { node_id: i.id },
name: i.ident.name,
name: self.lower_ident(i.ident),
span: i.span,
vis: self.lower_visibility(&i.vis, Some(i.id)),
defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
@ -1655,7 +1669,7 @@ impl<'a> LoweringContext<'a> {
Spanned {
span: f.span,
node: hir::FieldPat {
name: f.node.ident.name,
name: self.lower_ident(f.node.ident),
pat: self.lower_pat(&f.node.pat),
is_shorthand: f.node.is_shorthand,
},
@ -1825,7 +1839,7 @@ impl<'a> LoweringContext<'a> {
ExprKind::MethodCall(i, ref tps, ref args) => {
let tps = tps.iter().map(|x| self.lower_ty(x)).collect();
let args = args.iter().map(|x| self.lower_expr(x)).collect();
hir::ExprMethodCall(respan(i.span, i.node.name), tps, args)
hir::ExprMethodCall(respan(i.span, self.lower_ident(i.node)), tps, args)
}
ExprKind::Binary(binop, ref lhs, ref rhs) => {
let binop = self.lower_binop(binop);
@ -1924,7 +1938,8 @@ impl<'a> LoweringContext<'a> {
P(self.lower_expr(er)))
}
ExprKind::Field(ref el, ident) => {
hir::ExprField(P(self.lower_expr(el)), respan(ident.span, ident.node.name))
hir::ExprField(P(self.lower_expr(el)),
respan(ident.span, self.lower_ident(ident.node)))
}
ExprKind::TupField(ref el, ident) => {
hir::ExprTupField(P(self.lower_expr(el)), ident)
@ -2643,10 +2658,8 @@ impl<'a> LoweringContext<'a> {
let def_id = {
let defs = self.resolver.definitions();
let def_path_data = DefPathData::Binding(name.as_str());
let def_index = defs.create_def_with_parent(parent_def,
id,
def_path_data,
REGULAR_SPACE);
let def_index = defs
.create_def_with_parent(parent_def, id, def_path_data, REGULAR_SPACE, Mark::root());
DefId::local(def_index)
};

View file

@ -22,6 +22,7 @@ use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE};
pub struct DefCollector<'a> {
definitions: &'a mut Definitions,
parent_def: Option<DefIndex>,
expansion: Mark,
pub visit_macro_invoc: Option<&'a mut FnMut(MacroInvocationData)>,
}
@ -32,9 +33,10 @@ pub struct MacroInvocationData {
}
impl<'a> DefCollector<'a> {
pub fn new(definitions: &'a mut Definitions) -> Self {
pub fn new(definitions: &'a mut Definitions, expansion: Mark) -> Self {
DefCollector {
definitions: definitions,
expansion: expansion,
parent_def: None,
visit_macro_invoc: None,
}
@ -54,7 +56,8 @@ impl<'a> DefCollector<'a> {
-> DefIndex {
let parent_def = self.parent_def.unwrap();
debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
self.definitions.create_def_with_parent(parent_def, node_id, data, address_space)
self.definitions
.create_def_with_parent(parent_def, node_id, data, address_space, self.expansion)
}
pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {

View file

@ -24,6 +24,7 @@ use serialize::{Encodable, Decodable, Encoder, Decoder};
use std::fmt::Write;
use std::hash::Hash;
use syntax::ast;
use syntax::ext::hygiene::Mark;
use syntax::symbol::{Symbol, InternedString};
use ty::TyCtxt;
use util::nodemap::NodeMap;
@ -180,6 +181,8 @@ pub struct Definitions {
node_to_def_index: NodeMap<DefIndex>,
def_index_to_node: [Vec<ast::NodeId>; 2],
pub(super) node_to_hir_id: IndexVec<ast::NodeId, hir::HirId>,
macro_def_scopes: FxHashMap<Mark, DefId>,
expansions: FxHashMap<DefIndex, Mark>,
}
// Unfortunately we have to provide a manual impl of Clone because of the
@ -194,6 +197,8 @@ impl Clone for Definitions {
self.def_index_to_node[1].clone(),
],
node_to_hir_id: self.node_to_hir_id.clone(),
macro_def_scopes: self.macro_def_scopes.clone(),
expansions: self.expansions.clone(),
}
}
}
@ -379,6 +384,8 @@ impl Definitions {
node_to_def_index: NodeMap(),
def_index_to_node: [vec![], vec![]],
node_to_hir_id: IndexVec::new(),
macro_def_scopes: FxHashMap(),
expansions: FxHashMap(),
}
}
@ -472,7 +479,8 @@ impl Definitions {
parent: DefIndex,
node_id: ast::NodeId,
data: DefPathData,
address_space: DefIndexAddressSpace)
address_space: DefIndexAddressSpace,
expansion: Mark)
-> DefIndex {
debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})",
parent, node_id, data);
@ -510,6 +518,7 @@ impl Definitions {
assert_eq!(index.as_array_index(),
self.def_index_to_node[address_space.index()].len());
self.def_index_to_node[address_space.index()].push(node_id);
self.expansions.insert(index, expansion);
debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
self.node_to_def_index.insert(node_id, index);
@ -525,6 +534,18 @@ impl Definitions {
"Trying initialize NodeId -> HirId mapping twice");
self.node_to_hir_id = mapping;
}
pub fn expansion(&self, index: DefIndex) -> Mark {
self.expansions[&index]
}
pub fn macro_def_scope(&self, mark: Mark) -> DefId {
self.macro_def_scopes[&mark]
}
pub fn add_macro_def_scope(&mut self, mark: Mark, scope: DefId) {
self.macro_def_scopes.insert(mark, scope);
}
}
impl DefPathData {

View file

@ -637,14 +637,15 @@ impl<'hir> Map<'hir> {
/// Returns the NodeId of `id`'s nearest module parent, or `id` itself if no
/// module parent is in this map.
pub fn get_module_parent(&self, id: NodeId) -> NodeId {
match self.walk_parent_nodes(id, |node| match *node {
pub fn get_module_parent(&self, id: NodeId) -> DefId {
let id = match self.walk_parent_nodes(id, |node| match *node {
NodeItem(&Item { node: Item_::ItemMod(_), .. }) => true,
_ => false,
}) {
Ok(id) => id,
Err(id) => id,
}
};
self.local_def_id(id)
}
/// Returns the nearest enclosing scope. A scope is an item or block.

View file

@ -45,8 +45,9 @@ use std::rc::Rc;
use std::slice;
use std::vec::IntoIter;
use std::mem;
use syntax::ast::{self, DUMMY_NODE_ID, Name, NodeId};
use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId};
use syntax::attr;
use syntax::ext::hygiene::{Mark, SyntaxContext};
use syntax::symbol::{Symbol, InternedString};
use syntax_pos::{DUMMY_SP, Span};
use rustc_const_math::ConstInt;
@ -268,7 +269,7 @@ impl Visibility {
def => Visibility::Restricted(def.def_id()),
},
hir::Inherited => {
Visibility::Restricted(tcx.hir.local_def_id(tcx.hir.get_module_parent(id)))
Visibility::Restricted(tcx.hir.get_module_parent(id))
}
}
}
@ -1823,17 +1824,22 @@ impl<'a, 'gcx, 'tcx> AdtDef {
impl<'a, 'gcx, 'tcx> VariantDef {
#[inline]
pub fn find_field_named(&self,
name: ast::Name)
-> Option<&FieldDef> {
self.fields.iter().find(|f| f.name == name)
pub fn find_field_named(&self, name: ast::Name) -> Option<&FieldDef> {
self.index_of_field_named(name).map(|index| &self.fields[index])
}
#[inline]
pub fn index_of_field_named(&self,
name: ast::Name)
-> Option<usize> {
self.fields.iter().position(|f| f.name == name)
pub fn index_of_field_named(&self, name: ast::Name) -> Option<usize> {
if let Some(index) = self.fields.iter().position(|f| f.name == name) {
return Some(index);
}
let mut ident = name.to_ident();
while ident.ctxt != SyntaxContext::empty() {
ident.ctxt.remove_mark();
if let Some(field) = self.fields.iter().position(|f| f.name.to_ident() == ident) {
return Some(field);
}
}
None
}
#[inline]
@ -2257,10 +2263,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}
}
pub fn vis_is_accessible_from(self, vis: Visibility, block: NodeId) -> bool {
vis.is_accessible_from(self.hir.local_def_id(self.hir.get_module_parent(block)), self)
}
pub fn item_name(self, id: DefId) -> ast::Name {
if let Some(id) = self.hir.as_local_node_id(id) {
self.hir.name(id)
@ -2372,6 +2374,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
Err(self.sess.cstore.crate_name(impl_did.krate))
}
}
pub fn adjust(self, name: Name, scope: DefId, block: NodeId) -> (Ident, DefId) {
self.adjust_ident(name.to_ident(), scope, block)
}
pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ident, DefId) {
let expansion = match scope.krate {
LOCAL_CRATE => self.hir.definitions().expansion(scope.index),
_ => Mark::root(),
};
let scope = match ident.ctxt.adjust(expansion) {
Some(macro_def) => self.hir.definitions().macro_def_scope(macro_def),
None => self.hir.get_module_parent(block),
};
(ident, scope)
}
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {

View file

@ -154,7 +154,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
}
}
let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(scrut.id));
let module = self.tcx.hir.get_module_parent(scrut.id);
MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| {
let mut have_errors = false;
@ -182,7 +182,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
// Then, if the match has no arms, check whether the scrutinee
// is uninhabited.
let pat_ty = self.tables.node_id_to_type(scrut.id);
let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(scrut.id));
let module = self.tcx.hir.get_module_parent(scrut.id);
if inlined_arms.is_empty() {
let scrutinee_is_uninhabited = if self.tcx.sess.features.borrow().never_type {
pat_ty.is_uninhabited_from(module, self.tcx)
@ -231,7 +231,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
"local binding"
};
let module = self.tcx.hir.local_def_id(self.tcx.hir.get_module_parent(pat.id));
let module = self.tcx.hir.get_module_parent(pat.id);
MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| {
let mut patcx = PatternContext::new(self.tcx, self.tables);
let pattern = patcx.lower_pattern(pat);

View file

@ -1320,7 +1320,7 @@ impl<'a> Resolver<'a> {
module_map.insert(DefId::local(CRATE_DEF_INDEX), graph_root);
let mut definitions = Definitions::new();
DefCollector::new(&mut definitions)
DefCollector::new(&mut definitions, Mark::root())
.collect_root(crate_name, &session.local_crate_disambiguator().as_str());
let mut invocations = FxHashMap();

View file

@ -158,7 +158,7 @@ impl<'a> base::Resolver for Resolver<'a> {
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]) {
let invocation = self.invocations[&mark];
self.collect_def_ids(invocation, expansion);
self.collect_def_ids(mark, invocation, expansion);
self.current_module = invocation.module.get();
self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
@ -290,7 +290,12 @@ impl<'a> base::Resolver for Resolver<'a> {
Err(determinacy) => return Err(determinacy),
},
};
self.macro_defs.insert(invoc.expansion_data.mark, def.def_id());
let normal_module_def_id =
self.macro_def_scope(invoc.expansion_data.mark).normal_ancestor_id;
self.definitions.add_macro_def_scope(invoc.expansion_data.mark, normal_module_def_id);
self.unused_macros.remove(&def.def_id());
let ext = self.get_macro(def);
if ext.is_modern() {
@ -665,7 +670,10 @@ impl<'a> Resolver<'a> {
}
}
fn collect_def_ids(&mut self, invocation: &'a InvocationData<'a>, expansion: &Expansion) {
fn collect_def_ids(&mut self,
mark: Mark,
invocation: &'a InvocationData<'a>,
expansion: &Expansion) {
let Resolver { ref mut invocations, arenas, graph_root, .. } = *self;
let InvocationData { def_index, const_expr, .. } = *invocation;
@ -681,7 +689,7 @@ impl<'a> Resolver<'a> {
});
};
let mut def_collector = DefCollector::new(&mut self.definitions);
let mut def_collector = DefCollector::new(&mut self.definitions, mark);
def_collector.visit_macro_invoc = Some(visit_macro_invoc);
def_collector.with_parent(def_index, |def_collector| {
if const_expr {

View file

@ -891,7 +891,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
let item = tcx.associated_items(trait_did).find(|i| i.name == assoc_name)
.expect("missing associated type");
let def = Def::AssociatedTy(item.def_id);
if !tcx.vis_is_accessible_from(item.vis, ref_id) {
let def_scope = tcx.adjust(assoc_name, item.container.id(), ref_id).1;
if !item.vis.is_accessible_from(def_scope, tcx) {
let msg = format!("{} `{}` is private", def.kind_name(), assoc_name);
tcx.sess.span_err(span, &msg);
}

View file

@ -338,6 +338,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
/// and return it, or `None`, if no such item was defined there.
pub fn associated_item(&self, def_id: DefId, item_name: ast::Name)
-> Option<ty::AssociatedItem> {
self.tcx.associated_items(def_id).find(|item| item.name == item_name)
let ident = self.tcx.adjust(item_name, def_id, self.body_id).0;
self.tcx.associated_items(def_id).find(|item| item.name.to_ident() == ident)
}
}

View file

@ -371,7 +371,13 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
fn push_inherent_candidate(&mut self, xform_self_ty: Ty<'tcx>, item: ty::AssociatedItem,
kind: CandidateKind<'tcx>, import_id: Option<ast::NodeId>) {
if self.tcx.vis_is_accessible_from(item.vis, self.body_id) {
let is_accessible = if let LookingFor::MethodName(name) = self.looking_for {
let def_scope = self.tcx.adjust(name, item.container.id(), self.body_id).1;
item.vis.is_accessible_from(def_scope, self.tcx)
} else {
true
};
if is_accessible {
self.inherent_candidates.push(Candidate { xform_self_ty, item, kind, import_id });
} else if self.private_candidate.is_none() {
self.private_candidate = Some(item.def());
@ -380,7 +386,13 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
fn push_extension_candidate(&mut self, xform_self_ty: Ty<'tcx>, item: ty::AssociatedItem,
kind: CandidateKind<'tcx>, import_id: Option<ast::NodeId>) {
if self.tcx.vis_is_accessible_from(item.vis, self.body_id) {
let is_accessible = if let LookingFor::MethodName(name) = self.looking_for {
let def_scope = self.tcx.adjust(name, item.container.id(), self.body_id).1;
item.vis.is_accessible_from(def_scope, self.tcx)
} else {
true
};
if is_accessible {
self.extension_candidates.push(Candidate { xform_self_ty, item, kind, import_id });
} else if self.private_candidate.is_none() {
self.private_candidate = Some(item.def());

View file

@ -195,8 +195,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
};
let field_ty = field.ty(tcx, substs);
if tcx.vis_is_accessible_from(field.vis, self.body_id) {
let scope = self.tcx.hir.get_module_parent(self.body_id);
if field.vis.is_accessible_from(scope, self.tcx) {
if self.is_fn_ty(&field_ty, span) {
err.help(&format!("use `({0}.{1})(...)` if you \
meant to call the function \

View file

@ -2916,9 +2916,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
match base_t.sty {
ty::TyAdt(base_def, substs) if !base_def.is_enum() => {
debug!("struct named {:?}", base_t);
if let Some(field) = base_def.struct_variant().find_field_named(field.node) {
let (ident, def_scope) =
self.tcx.adjust(field.node, base_def.did, self.body_id);
let fields = &base_def.struct_variant().fields;
if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
let field_ty = self.field_ty(expr.span, field, substs);
if self.tcx.vis_is_accessible_from(field.vis, self.body_id) {
if field.vis.is_accessible_from(def_scope, self.tcx) {
autoderef.finalize(lvalue_pref, base);
self.apply_autoderef_adjustment(base.id, autoderefs, base_t);
@ -3024,16 +3027,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if !tuple_like { continue }
debug!("tuple struct named {:?}", base_t);
base_def.struct_variant().fields.get(idx.node).and_then(|field| {
let ident = ast::Ident {
name: Symbol::intern(&idx.node.to_string()),
ctxt: idx.span.ctxt.modern(),
};
let (ident, def_scope) =
self.tcx.adjust_ident(ident, base_def.did, self.body_id);
let fields = &base_def.struct_variant().fields;
if let Some(field) = fields.iter().find(|f| f.name.to_ident() == ident) {
let field_ty = self.field_ty(expr.span, field, substs);
private_candidate = Some((base_def.did, field_ty));
if self.tcx.vis_is_accessible_from(field.vis, self.body_id) {
if field.vis.is_accessible_from(def_scope, self.tcx) {
self.tcx.check_stability(field.did, expr.id, expr.span);
Some(field_ty)
} else {
private_candidate = Some((base_def.did, field_ty));
None
}
})
} else {
None
}
}
ty::TyTuple(ref v, _) => {
tuple_like = true;
@ -3142,7 +3154,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let mut remaining_fields = FxHashMap();
for field in &variant.fields {
remaining_fields.insert(field.name, field);
remaining_fields.insert(field.name.to_ident(), field);
}
let mut seen_fields = FxHashMap();
@ -3154,7 +3166,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let final_field_type;
let field_type_hint;
if let Some(v_field) = remaining_fields.remove(&field.name.node) {
let ident = tcx.adjust(field.name.node, variant.did, self.body_id).0;
if let Some(v_field) = remaining_fields.remove(&ident) {
final_field_type = self.field_ty(field.span, v_field, substs);
field_type_hint = self.field_ty(field.span, v_field, hint_substs);
@ -3205,7 +3218,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let mut displayable_field_names = remaining_fields
.keys()
.map(|x| x.as_str())
.map(|ident| ident.name.as_str())
.collect::<Vec<_>>();
displayable_field_names.sort();

View file

@ -16,7 +16,7 @@
//! DOI=10.1017/S0956796812000093 http://dx.doi.org/10.1017/S0956796812000093
use Span;
use symbol::Symbol;
use symbol::{Ident, Symbol};
use serialize::{Encodable, Decodable, Encoder, Decoder};
use std::cell::RefCell;
@ -106,6 +106,7 @@ struct HygieneData {
marks: Vec<MarkData>,
syntax_contexts: Vec<SyntaxContextData>,
markings: HashMap<(SyntaxContext, Mark), SyntaxContext>,
idents: HashMap<Symbol, Ident>,
}
impl HygieneData {
@ -114,6 +115,7 @@ impl HygieneData {
marks: vec![MarkData::default()],
syntax_contexts: vec![SyntaxContextData::default()],
markings: HashMap::new(),
idents: HashMap::new(),
}
}
@ -348,3 +350,19 @@ impl Decodable for SyntaxContext {
Ok(SyntaxContext::empty()) // FIXME(jseyfried) intercrate hygiene
}
}
impl Symbol {
pub fn from_ident(ident: Ident) -> Symbol {
HygieneData::with(|data| {
let symbol = Symbol::gensym(&ident.name.as_str());
data.idents.insert(symbol, ident);
symbol
})
}
pub fn to_ident(self) -> Ident {
HygieneData::with(|data| {
data.idents.get(&self).cloned().unwrap_or(Ident::with_empty_ctxt(self))
})
}
}