Skip to content
37 changes: 24 additions & 13 deletions src/librustc/hir/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ use crate::ty;

use self::Namespace::*;

/// Encodes if a `Def::Ctor` is the constructor of an enum variant or a struct.
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum CtorOf {
/// This `Def::Ctor` is a synthesized constructor of a tuple or unit struct.
Struct,
/// This `Def::Ctor` is a synthesized constructor of a tuple or unit variant.
Variant,
}

#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum CtorKind {
/// Constructor function automatically created by a tuple struct/variant.
Expand Down Expand Up @@ -37,9 +46,11 @@ pub enum NonMacroAttrKind {
pub enum Def {
// Type namespace
Mod(DefId),
Struct(DefId), // `DefId` refers to `NodeId` of the struct itself
/// `DefId` refers to the struct itself, `Def::Ctor` refers to its constructor if it exists.
Struct(DefId),
Union(DefId),
Enum(DefId),
/// `DefId` refers to the variant itself, `Def::Ctor` refers to its constructor if it exists.
Variant(DefId),
Trait(DefId),
/// `existential type Foo: Bar;`
Expand All @@ -61,8 +72,8 @@ pub enum Def {
Const(DefId),
ConstParam(DefId),
Static(DefId, bool /* is_mutbl */),
StructCtor(DefId, CtorKind), // `DefId` refers to `NodeId` of the struct's constructor
VariantCtor(DefId, CtorKind), // `DefId` refers to the enum variant
/// `DefId` refers to the struct or enum variant's constructor.
Ctor(DefId, CtorOf, CtorKind),
SelfCtor(DefId /* impl */), // `DefId` refers to the impl
Method(DefId),
AssociatedConst(DefId),
Expand Down Expand Up @@ -265,10 +276,9 @@ impl Def {
pub fn opt_def_id(&self) -> Option<DefId> {
match *self {
Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) |
Def::Variant(id) | Def::Ctor(id, ..) | Def::Enum(id) |
Def::TyAlias(id) | Def::TraitAlias(id) |
Def::AssociatedTy(id) | Def::TyParam(id) | Def::ConstParam(id) | Def::Struct(id) |
Def::StructCtor(id, ..) |
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
Def::AssociatedConst(id) | Def::Macro(id, ..) |
Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) => {
Expand Down Expand Up @@ -303,20 +313,21 @@ impl Def {
Def::Fn(..) => "function",
Def::Mod(..) => "module",
Def::Static(..) => "static",
Def::Variant(..) => "variant",
Def::VariantCtor(.., CtorKind::Fn) => "tuple variant",
Def::VariantCtor(.., CtorKind::Const) => "unit variant",
Def::VariantCtor(.., CtorKind::Fictive) => "struct variant",
Def::Enum(..) => "enum",
Def::Variant(..) => "variant",
Def::Ctor(_, CtorOf::Variant, CtorKind::Fn) => "tuple variant",
Def::Ctor(_, CtorOf::Variant, CtorKind::Const) => "unit variant",
Def::Ctor(_, CtorOf::Variant, CtorKind::Fictive) => "struct variant",
Def::Struct(..) => "struct",
Def::Ctor(_, CtorOf::Struct, CtorKind::Fn) => "tuple struct",
Def::Ctor(_, CtorOf::Struct, CtorKind::Const) => "unit struct",
Def::Ctor(_, CtorOf::Struct, CtorKind::Fictive) =>
bug!("impossible struct constructor"),
Def::Existential(..) => "existential type",
Def::TyAlias(..) => "type alias",
Def::TraitAlias(..) => "trait alias",
Def::AssociatedTy(..) => "associated type",
Def::AssociatedExistential(..) => "associated existential type",
Def::Struct(..) => "struct",
Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
Def::StructCtor(.., CtorKind::Const) => "unit struct",
Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
Def::SelfCtor(..) => "self constructor",
Def::Union(..) => "union",
Def::Trait(..) => "trait",
Expand Down
5 changes: 4 additions & 1 deletion src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
generics: &'v Generics,
parent_item_id: HirId) {
visitor.visit_ident(variant.node.ident);
visitor.visit_id(variant.node.id);
visitor.visit_variant_data(&variant.node.data,
variant.node.ident.name,
generics,
Expand Down Expand Up @@ -923,7 +924,9 @@ pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'


pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) {
visitor.visit_id(struct_definition.hir_id());
if let Some(ctor_hir_id) = struct_definition.ctor_hir_id() {
visitor.visit_id(ctor_hir_id);
}
walk_list!(visitor, visit_struct_field, struct_definition.fields());
}

Expand Down
20 changes: 6 additions & 14 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1615,9 +1615,11 @@ impl<'a> LoweringContext<'a> {
}

fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(v.node.id);
Spanned {
node: hir::VariantKind {
ident: v.node.ident,
id: hir_id,
attrs: self.lower_attrs(&v.node.attrs),
data: self.lower_variant_data(&v.node.data),
disr_expr: v.node.disr_expr.as_ref().map(|e| self.lower_anon_const(e)),
Expand Down Expand Up @@ -2669,19 +2671,10 @@ impl<'a> LoweringContext<'a> {

fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
match *vdata {
VariantData::Struct(ref fields, id, recovered) => {
let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(id);

hir::VariantData::Struct(
fields
.iter()
.enumerate()
.map(|f| self.lower_struct_field(f))
.collect(),
hir_id,
recovered,
)
},
VariantData::Struct(ref fields, recovered) => hir::VariantData::Struct(
fields.iter().enumerate().map(|f| self.lower_struct_field(f)).collect(),
recovered,
),
VariantData::Tuple(ref fields, id) => {
let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(id);

Expand All @@ -2696,7 +2689,6 @@ impl<'a> LoweringContext<'a> {
},
VariantData::Unit(id) => {
let LoweredNodeId { node_id: _, hir_id } = self.lower_node_id(id);

hir::VariantData::Unit(hir_id)
},
}
Expand Down
14 changes: 9 additions & 5 deletions src/librustc/hir/map/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,9 +360,9 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
this.insert(i.span, i.hir_id, Node::Item(i));
this.with_parent(i.hir_id, |this| {
if let ItemKind::Struct(ref struct_def, _) = i.node {
// If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() {
this.insert(i.span, struct_def.hir_id(), Node::StructCtor(struct_def));
// If this is a tuple or unit-like struct, register the constructor.
if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def));
}
}
intravisit::walk_item(this, i);
Expand Down Expand Up @@ -515,8 +515,12 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
}

fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: HirId) {
self.insert(v.span, v.node.data.hir_id(), Node::Variant(v));
self.with_parent(v.node.data.hir_id(), |this| {
self.insert(v.span, v.node.id, Node::Variant(v));
self.with_parent(v.node.id, |this| {
// Register the constructor of this variant.
if let Some(ctor_hir_id) = v.node.data.ctor_hir_id() {
this.insert(v.span, ctor_hir_id, Node::Ctor(&v.node.data));
}
intravisit::walk_variant(this, v, g, item_id);
});
}
Expand Down
18 changes: 10 additions & 8 deletions src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
self.with_parent(def, |this| {
match i.node {
ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
// If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() {
this.create_def(struct_def.id(),
DefPathData::StructCtor,
REGULAR_SPACE,
i.span);
// If this is a unit or tuple-like struct, register the constructor.
if let Some(ctor_hir_id) = struct_def.ctor_id() {
this.create_def(ctor_hir_id, DefPathData::Ctor, REGULAR_SPACE, i.span);
}
}
_ => {}
Expand Down Expand Up @@ -193,11 +190,16 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
}

fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
let def = self.create_def(v.node.data.id(),
let def = self.create_def(v.node.id,
DefPathData::EnumVariant(v.node.ident.as_interned_str()),
REGULAR_SPACE,
v.span);
self.with_parent(def, |this| visit::walk_variant(this, v, g, item_id));
self.with_parent(def, |this| {
if let Some(ctor_hir_id) = v.node.data.ctor_id() {
this.create_def(ctor_hir_id, DefPathData::Ctor, REGULAR_SPACE, v.span);
}
visit::walk_variant(this, v, g, item_id)
});
}

fn visit_variant_data(&mut self, data: &'a VariantData, _: Ident,
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/hir/map/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,8 @@ pub enum DefPathData {
EnumVariant(InternedString),
/// A struct field
Field(InternedString),
/// Implicit ctor for a tuple-like struct
StructCtor,
/// Implicit ctor for a unit or tuple-like struct or enum variant.
Ctor,
/// A constant expression (see {ast,hir}::AnonConst).
AnonConst,
/// An `impl Trait` type node
Expand Down Expand Up @@ -652,7 +652,7 @@ impl DefPathData {
CrateRoot |
Misc |
ClosureExpr |
StructCtor |
Ctor |
AnonConst |
ImplTrait => None
}
Expand Down Expand Up @@ -683,7 +683,7 @@ impl DefPathData {
Impl => "{{impl}}",
Misc => "{{misc}}",
ClosureExpr => "{{closure}}",
StructCtor => "{{constructor}}",
Ctor => "{{constructor}}",
AnonConst => "{{constant}}",
ImplTrait => "{{opaque}}",
};
Expand Down
39 changes: 24 additions & 15 deletions src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,12 +366,18 @@ impl<'hir> Map<'hir> {
}
}
Node::Variant(variant) => {
let def_id = self.local_def_id_from_hir_id(variant.node.data.hir_id());
let def_id = self.local_def_id_from_hir_id(variant.node.id);
Some(Def::Variant(def_id))
}
Node::StructCtor(variant) => {
let def_id = self.local_def_id_from_hir_id(variant.hir_id());
Some(Def::StructCtor(def_id, def::CtorKind::from_hir(variant)))
Node::Ctor(variant_data) => {
let ctor_of = match self.find(self.get_parent_node(node_id)) {
Some(Node::Item(..)) => def::CtorOf::Struct,
Some(Node::Variant(..)) => def::CtorOf::Variant,
_ => unreachable!(),
};
variant_data.ctor_hir_id()
.map(|hir_id| self.local_def_id_from_hir_id(hir_id))
.map(|def_id| Def::Ctor(def_id, ctor_of, def::CtorKind::from_hir(variant_data)))
}
Node::AnonConst(_) |
Node::Field(_) |
Expand Down Expand Up @@ -516,8 +522,7 @@ impl<'hir> Map<'hir> {
Node::AnonConst(_) => {
BodyOwnerKind::Const
}
Node::Variant(&Spanned { node: VariantKind { data: VariantData::Tuple(..), .. }, .. }) |
Node::StructCtor(..) |
Node::Ctor(..) |
Node::Item(&Item { node: ItemKind::Fn(..), .. }) |
Node::TraitItem(&TraitItem { node: TraitItemKind::Method(..), .. }) |
Node::ImplItem(&ImplItem { node: ImplItemKind::Method(..), .. }) => {
Expand Down Expand Up @@ -948,8 +953,8 @@ impl<'hir> Map<'hir> {
_ => bug!("struct ID bound to non-struct {}", self.hir_to_string(id))
}
}
Some(Node::StructCtor(data)) => data,
Some(Node::Variant(variant)) => &variant.node.data,
Some(Node::Ctor(data)) => data,
_ => bug!("expected struct or variant, found {}", self.hir_to_string(id))
}
}
Expand Down Expand Up @@ -993,7 +998,7 @@ impl<'hir> Map<'hir> {
Node::Lifetime(lt) => lt.name.ident().name,
Node::GenericParam(param) => param.name.ident().name,
Node::Binding(&Pat { node: PatKind::Binding(_, _, l, _), .. }) => l.name,
Node::StructCtor(_) => self.name(self.get_parent(id)),
Node::Ctor(..) => self.name(self.get_parent(id)),
_ => bug!("no name for {}", self.node_to_string(id))
}
}
Expand All @@ -1019,9 +1024,9 @@ impl<'hir> Map<'hir> {
Some(Node::Expr(ref e)) => Some(&*e.attrs),
Some(Node::Stmt(ref s)) => Some(s.node.attrs()),
Some(Node::GenericParam(param)) => Some(&param.attrs[..]),
// unit/tuple structs take the attributes straight from
// the struct definition.
Some(Node::StructCtor(_)) => return self.attrs(self.get_parent(id)),
// Unit/tuple structs/variants take the attributes straight from
// the struct/variant definition.
Some(Node::Ctor(..)) => return self.attrs(self.get_parent(id)),
_ => None
};
attrs.unwrap_or(&[])
Expand Down Expand Up @@ -1068,7 +1073,11 @@ impl<'hir> Map<'hir> {
Some(Node::Binding(pat)) => pat.span,
Some(Node::Pat(pat)) => pat.span,
Some(Node::Block(block)) => block.span,
Some(Node::StructCtor(_)) => self.expect_item(self.get_parent(id)).span,
Some(Node::Ctor(..)) => match self.find(self.get_parent_node(id)) {
Some(Node::Item(item)) => item.span,
Some(Node::Variant(variant)) => variant.span,
_ => unreachable!(),
}
Some(Node::Lifetime(lifetime)) => lifetime.span,
Some(Node::GenericParam(param)) => param.span,
Some(Node::Visibility(&Spanned {
Expand Down Expand Up @@ -1324,7 +1333,7 @@ impl<'a> print::State<'a> {
// these cases do not carry enough information in the
// hir_map to reconstruct their full structure for pretty
// printing.
Node::StructCtor(_) => bug!("cannot print isolated StructCtor"),
Node::Ctor(..) => bug!("cannot print isolated Ctor"),
Node::Local(a) => self.print_local_decl(&a),
Node::MacroDef(_) => bug!("cannot print MacroDef"),
Node::Crate => bug!("cannot print Crate"),
Expand Down Expand Up @@ -1443,8 +1452,8 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String {
Some(Node::Local(_)) => {
format!("local {}{}", map.node_to_pretty_string(id), id_str)
}
Some(Node::StructCtor(_)) => {
format!("struct_ctor {}{}", path_str(), id_str)
Some(Node::Ctor(..)) => {
format!("ctor {}{}", path_str(), id_str)
}
Some(Node::Lifetime(_)) => {
format!("lifetime {}{}", map.node_to_pretty_string(id), id_str)
Expand Down
Loading