Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate DefIds for variants and their constructors #59382

Merged
merged 9 commits into from
Mar 25, 2019
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