diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index b45fc3ffd82..87a6065bb75 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -37,9 +37,13 @@ pub enum NonMacroAttrKind { pub enum Def { // Type namespace Mod(DefId), - Struct(DefId), // `DefId` refers to `NodeId` of the struct itself + /// `DefId` refers to `NodeId` of the struct. `Def::VariantCtor` represents the constructor of + /// a struct. + Struct(DefId), Union(DefId), Enum(DefId), + /// `DefId` refers to the `NodeId` of the variant. `Def::VariantCtor` represents the + /// constructor of an enum variant. Variant(DefId), Trait(DefId), /// `existential type Foo: Bar;` @@ -61,8 +65,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 `NodeId` of the struct or enum variant's constructor. + Ctor(hir::CtorOf, DefId, CtorKind), SelfCtor(DefId /* impl */), // `DefId` refers to the impl Method(DefId), AssociatedConst(DefId), @@ -265,10 +269,9 @@ impl Def { pub fn opt_def_id(&self) -> Option { 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) => { @@ -303,20 +306,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(hir::CtorOf::Variant, _, CtorKind::Fn) => "tuple variant", + Def::Ctor(hir::CtorOf::Variant, _, CtorKind::Const) => "unit variant", + Def::Ctor(hir::CtorOf::Variant, _, CtorKind::Fictive) => "struct variant", + Def::Struct(..) => "struct", + Def::Ctor(hir::CtorOf::Struct, _, CtorKind::Fn) => "tuple struct", + Def::Ctor(hir::CtorOf::Struct, _, CtorKind::Const) => "unit struct", + Def::Ctor(hir::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", diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 977830315e2..bce528189ad 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -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, @@ -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()); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 2251e67233c..8db90035c8e 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -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)), @@ -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); @@ -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) }, } diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index e88f9e60702..e7cd8f11353 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -360,9 +360,11 @@ 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(hir::CtorOf::Struct, struct_def)); } } intravisit::walk_item(this, i); @@ -515,8 +517,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(hir::CtorOf::Variant, &v.node.data)); + } intravisit::walk_variant(this, v, g, item_id); }); } diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 12760f8b982..2c92d907201 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -158,9 +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(), + // 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::StructCtor, REGULAR_SPACE, i.span); @@ -193,11 +193,19 @@ 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::VariantCtor, + REGULAR_SPACE, + v.span); + } + visit::walk_variant(this, v, g, item_id) + }); } fn visit_variant_data(&mut self, data: &'a VariantData, _: Ident, diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index dca4ce4aef8..dc23b55c1fc 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -366,8 +366,10 @@ pub enum DefPathData { EnumVariant(InternedString), /// A struct field Field(InternedString), - /// Implicit ctor for a tuple-like struct + /// Implicit ctor for a unit or tuple-like struct StructCtor, + /// Implicit ctor for a unit or tuple-like enum variant + VariantCtor, /// A constant expression (see {ast,hir}::AnonConst). AnonConst, /// An `impl Trait` type node @@ -653,6 +655,7 @@ impl DefPathData { Misc | ClosureExpr | StructCtor | + VariantCtor | AnonConst | ImplTrait => None } @@ -683,7 +686,8 @@ impl DefPathData { Impl => "{{impl}}", Misc => "{{misc}}", ClosureExpr => "{{closure}}", - StructCtor => "{{constructor}}", + StructCtor => "{{struct constructor}}", + VariantCtor => "{{variant constructor}}", AnonConst => "{{constant}}", ImplTrait => "{{opaque}}", }; diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 3e8da882eed..ce0246dec71 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -366,12 +366,15 @@ 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(ctor_of, variant_data) => { + variant_data.ctor_hir_id() + .map(|hir_id| self.local_def_id_from_hir_id(hir_id)) + .map(|def_id| Def::Ctor( + ctor_of, def_id, def::CtorKind::from_hir(variant_data), + )) } Node::AnonConst(_) | Node::Field(_) | @@ -516,8 +519,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(..), .. }) => { @@ -948,8 +950,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)) } } @@ -993,7 +995,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)) } } @@ -1019,9 +1021,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(¶m.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(&[]) @@ -1068,7 +1070,10 @@ 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(CtorOf::Struct, _)) => + self.expect_item(self.get_parent(id)).span, + Some(Node::Ctor(CtorOf::Variant, _)) => + self.expect_variant(self.node_to_hir_id(self.get_parent_node(id))).span, Some(Node::Lifetime(lifetime)) => lifetime.span, Some(Node::GenericParam(param)) => param.span, Some(Node::Visibility(&Spanned { @@ -1324,7 +1329,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"), @@ -1443,8 +1448,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) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 823de08874e..6ce7c347c99 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2049,9 +2049,14 @@ pub struct EnumDef { #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct VariantKind { + /// Name of the variant. #[stable_hasher(project(name))] pub ident: Ident, + /// Attributes of the variant. pub attrs: HirVec, + /// Id of the variant (not the constructor, see `VariantData::ctor_hir_id()`). + pub id: HirId, + /// Fields and constructor id of the variant. pub data: VariantData, /// Explicit discriminant (e.g., `Foo = 1`). pub disr_expr: Option, @@ -2063,7 +2068,7 @@ pub type Variant = Spanned; pub enum UseKind { /// One import, e.g., `use foo::bar` or `use foo::bar as baz`. /// Also produced for each element of a list `use`, e.g. - // `use foo::{a, b}` lowers to `use foo::a; use foo::b;`. + /// `use foo::{a, b}` lowers to `use foo::a; use foo::b;`. Single, /// Glob import, e.g., `use foo::*`. @@ -2170,38 +2175,41 @@ impl StructField { } } -/// Fields and Ids of enum variants and structs -/// -/// For enum variants: `NodeId` represents both an Id of the variant itself (relevant for all -/// variant kinds) and an Id of the variant's constructor (not relevant for `Struct`-variants). -/// One shared Id can be successfully used for these two purposes. -/// Id of the whole enum lives in `Item`. -/// -/// For structs: `NodeId` represents an Id of the structure's constructor, so it is not actually -/// used for `Struct`-structs (but still present). Structures don't have an analogue of "Id of -/// the variant itself" from enum variants. -/// Id of the whole struct lives in `Item`. +/// Fields and constructor ids of enum variants and structs #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum VariantData { - Struct(HirVec, HirId, /* recovered */ bool), + /// Struct variant. + /// + /// e.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`. + Struct(HirVec, /* recovered */ bool), + /// Tuple variant. + /// + /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`. Tuple(HirVec, HirId), + /// Unit variant. + /// + /// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`. Unit(HirId), } impl VariantData { + /// Return the fields of this variant. pub fn fields(&self) -> &[StructField] { match *self { VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, ..) => fields, _ => &[], } } - pub fn hir_id(&self) -> HirId { + + /// Return the `HirId` of this variant's constructor, if it has one. + pub fn ctor_hir_id(&self) -> Option { match *self { - VariantData::Struct(_, hir_id, _) - | VariantData::Tuple(_, hir_id) - | VariantData::Unit(hir_id) => hir_id, + VariantData::Struct(_, _) => None, + VariantData::Tuple(_, hir_id) | VariantData::Unit(hir_id) => Some(hir_id), } } + + /// Does this `VariantData` represent a `Struct`-struct/variant? pub fn is_struct(&self) -> bool { if let VariantData::Struct(..) = *self { true @@ -2209,6 +2217,8 @@ impl VariantData { false } } + + /// Does this `VariantData` represent a tuple struct/variant? pub fn is_tuple(&self) -> bool { if let VariantData::Tuple(..) = *self { true @@ -2216,6 +2226,8 @@ impl VariantData { false } } + + /// Does this `VariantData` represent a unit struct/variant? pub fn is_unit(&self) -> bool { if let VariantData::Unit(..) = *self { true @@ -2574,6 +2586,15 @@ impl CodegenFnAttrs { } } +/// Encodes if a `Node::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 `Node::Ctor` is a synthesized constructor of a tuple or unit struct. + Struct, + /// This `Node::Ctor` is a synthesized constructor of a tuple or unit variant. + Variant, +} + #[derive(Copy, Clone, Debug)] pub enum Node<'hir> { Item(&'hir Item), @@ -2594,8 +2615,9 @@ pub enum Node<'hir> { Local(&'hir Local), MacroDef(&'hir MacroDef), - /// StructCtor represents a tuple struct. - StructCtor(&'hir VariantData), + /// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants + /// with synthesized constructors. + Ctor(CtorOf, &'hir VariantData), Lifetime(&'hir Lifetime), GenericParam(&'hir GenericParam), diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index 18a3d6708db..b859a0f389e 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -55,7 +55,7 @@ impl hir::Pat { PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) | PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => { match path.def { - Def::Variant(..) | Def::VariantCtor(..) => true, + Def::Variant(..) => true, _ => false } } @@ -125,8 +125,8 @@ impl hir::Pat { PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) | PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => { match path.def { - Def::Variant(id) | - Def::VariantCtor(id, ..) => variants.push(id), + Def::Variant(id) => variants.push(id), + Def::Ctor(hir::CtorOf::Variant, id, _) => variants.push(id), _ => () } } diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 9761ee31353..94f1d9c2710 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -917,7 +917,7 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { v: &'tcx hir::Variant, g: &'tcx hir::Generics, item_id: hir::HirId) { - self.with_lint_attrs(v.node.data.hir_id(), &v.node.attrs, |cx| { + self.with_lint_attrs(v.node.id, &v.node.attrs, |cx| { run_lints!(cx, check_variant, v, g); hir_visit::walk_variant(cx, v, g, item_id); run_lints!(cx, check_variant_post, v, g); @@ -1073,7 +1073,9 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> item_id: ast::NodeId, _: Span) { run_early_pass!(self, check_struct_def, s, ident, g, item_id); - self.check_id(s.id()); + if let Some(ctor_hir_id) = s.ctor_id() { + self.check_id(ctor_hir_id); + } ast_visit::walk_struct_def(self, s); run_early_pass!(self, check_struct_def_post, s, ident, g, item_id); } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 03ed62f2a0d..e96fe3d3b77 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -803,7 +803,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'a, 'tcx> { v: &'tcx hir::Variant, g: &'tcx hir::Generics, item_id: hir::HirId) { - self.with_lint_attrs(v.node.data.hir_id(), &v.node.attrs, |builder| { + self.with_lint_attrs(v.node.id, &v.node.attrs, |builder| { intravisit::walk_variant(builder, v, g, item_id); }) } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index ccec4bd1432..786d339e876 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -54,8 +54,7 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn check_def_id(&mut self, def_id: DefId) { if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) { - if should_explore(self.tcx, hir_id) || - self.struct_constructors.contains_key(&hir_id) { + if should_explore(self.tcx, hir_id) || self.struct_constructors.contains_key(&hir_id) { self.worklist.push(hir_id); } self.live_symbols.insert(hir_id); @@ -77,10 +76,17 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { _ if self.in_pat => (), Def::PrimTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) | Def::Local(..) | Def::Upvar(..) => {} - Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => { - if let Some(enum_id) = self.tcx.parent(variant_id) { - self.check_def_id(enum_id); + Def::Ctor(hir::CtorOf::Variant, ctor_def_id, ..) => { + let variant_id = self.tcx.parent(ctor_def_id).unwrap(); + let enum_id = self.tcx.parent(variant_id).unwrap(); + self.check_def_id(enum_id); + if !self.ignore_variant_stack.contains(&ctor_def_id) { + self.check_def_id(variant_id); } + } + Def::Variant(variant_id) => { + let enum_id = self.tcx.parent(variant_id).unwrap(); + self.check_def_id(enum_id); if !self.ignore_variant_stack.contains(&variant_id) { self.check_def_id(variant_id); } @@ -360,9 +366,16 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { self.worklist.push(item.hir_id); } match item.node { - hir::ItemKind::Enum(ref enum_def, _) if allow_dead_code => { - self.worklist.extend(enum_def.variants.iter() - .map(|variant| variant.node.data.hir_id())); + hir::ItemKind::Enum(ref enum_def, _) => { + if allow_dead_code { + self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id)); + } + + for variant in &enum_def.variants { + if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() { + self.struct_constructors.insert(ctor_hir_id, variant.node.id); + } + } } hir::ItemKind::Trait(.., ref trait_item_refs) => { for trait_item_ref in trait_item_refs { @@ -392,7 +405,9 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { } } hir::ItemKind::Struct(ref variant_data, _) => { - self.struct_constructors.insert(variant_data.hir_id(), item.hir_id); + if let Some(ctor_hir_id) = variant_data.ctor_hir_id() { + self.struct_constructors.insert(ctor_hir_id, item.hir_id); + } } _ => () } @@ -484,9 +499,9 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { } fn should_warn_about_variant(&mut self, variant: &hir::VariantKind) -> bool { - !self.symbol_is_live(variant.data.hir_id()) + !self.symbol_is_live(variant.id) && !has_allow_dead_code_or_lang_attr(self.tcx, - variant.data.hir_id(), + variant.id, &variant.attrs) } @@ -583,7 +598,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { g: &'tcx hir::Generics, id: hir::HirId) { if self.should_warn_about_variant(&variant.node) { - self.warn_dead_code(variant.node.data.hir_id(), variant.span, variant.node.ident.name, + self.warn_dead_code(variant.node.id, variant.span, variant.node.ident.name, "variant", "constructed"); } else { intravisit::walk_variant(self, variant, g, id); diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 8ada67efaaf..a60a145dd21 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -14,7 +14,7 @@ use crate::hir::def_id::DefId; use crate::infer::InferCtxt; use crate::middle::mem_categorization as mc; use crate::middle::region; -use crate::ty::{self, TyCtxt, adjustment}; +use crate::ty::{self, DefIdTree, TyCtxt, adjustment}; use crate::hir::{self, PatKind}; use rustc_data_structures::sync::Lrc; @@ -902,14 +902,20 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { }; let def = mc.tables.qpath_def(qpath, pat.hir_id); match def { - Def::Variant(variant_did) | - Def::VariantCtor(variant_did, ..) => { + Def::Ctor(hir::CtorOf::Variant, variant_ctor_did, ..) => { + let variant_did = mc.tcx.parent(variant_ctor_did).unwrap(); + let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did); + + debug!("variantctor downcast_cmt={:?} pat={:?}", downcast_cmt, pat); + delegate.matched_pat(pat, &downcast_cmt, match_mode); + } + Def::Variant(variant_did) => { let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did); debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat); delegate.matched_pat(pat, &downcast_cmt, match_mode); } - Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) | + Def::Struct(..) | Def::Ctor(..) | Def::Union(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => { debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat); delegate.matched_pat(pat, &cmt_pat, match_mode); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index b36d2a57cb3..aa582d48bb6 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -215,7 +215,7 @@ impl<'tcx> cmt_<'tcx> { }; let variant_def = match self.cat { Categorization::Downcast(_, variant_did) => { - adt_def.variant_with_id(variant_did) + adt_def.variant_with_variant_id(variant_did) } _ => { assert_eq!(adt_def.variants.len(), 1); @@ -704,7 +704,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { hir_id, expr_ty, def); match def { - Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) | Def::ConstParam(..) | + Def::Ctor(..) | Def::Const(..) | Def::ConstParam(..) | Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => { Ok(self.cat_rvalue_node(hir_id, span, expr_ty)) } @@ -1274,12 +1274,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { debug!("access to unresolvable pattern {:?}", pat); return Err(()) } - Def::VariantCtor(def_id, CtorKind::Fn) => { - let enum_def = self.tcx.parent(def_id).unwrap(); - (self.cat_downcast_if_needed(pat, cmt, def_id), - self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len()) + Def::Ctor(hir::CtorOf::Variant, variant_ctor_did, CtorKind::Fn) => { + let variant_did = self.tcx.parent(variant_ctor_did).unwrap(); + let enum_did = self.tcx.parent(variant_did).unwrap(); + (self.cat_downcast_if_needed(pat, cmt, variant_did), + self.tcx.adt_def(enum_did) + .variant_with_ctor_id(variant_ctor_did).fields.len()) } - Def::StructCtor(_, CtorKind::Fn) | Def::SelfCtor(..) => { + Def::Ctor(hir::CtorOf::Struct, _, CtorKind::Fn) | Def::SelfCtor(..) => { let ty = self.pat_ty_unadjusted(&pat)?; match ty.sty { ty::Adt(adt_def, _) => { @@ -1314,8 +1316,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { debug!("access to unresolvable pattern {:?}", pat); return Err(()) } - Def::Variant(variant_did) | - Def::VariantCtor(variant_did, ..) => { + Def::Ctor(hir::CtorOf::Variant, variant_ctor_did, _) => { + let variant_did = self.tcx.parent(variant_ctor_did).unwrap(); + self.cat_downcast_if_needed(pat, cmt, variant_did) + } + Def::Variant(variant_did) => { self.cat_downcast_if_needed(pat, cmt, variant_did) } _ => cmt, diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index a7294dbf07c..b57f96f2d46 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -311,7 +311,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { // Nothing to recurse on for these Node::ForeignItem(_) | Node::Variant(_) | - Node::StructCtor(_) | + Node::Ctor(..) | Node::Field(_) | Node::Ty(_) | Node::MacroDef(_) => {} diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 72c90b25860..772c6ab4745 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -258,8 +258,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { self.in_trait_impl = true; } hir::ItemKind::Struct(ref sd, _) => { - if !sd.is_struct() { - self.annotate(sd.hir_id(), &i.attrs, i.span, AnnotationKind::Required, |_| {}) + if let Some(ctor_hir_id) = sd.ctor_hir_id() { + self.annotate(ctor_hir_id, &i.attrs, i.span, AnnotationKind::Required, |_| {}) } } _ => {} @@ -289,8 +289,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) { - self.annotate(var.node.data.hir_id(), &var.node.attrs, var.span, AnnotationKind::Required, - |v| { intravisit::walk_variant(v, var, g, item_id) }) + self.annotate(var.node.id, &var.node.attrs, var.span, AnnotationKind::Required, + |v| { + if let Some(ctor_hir_id) = var.node.data.ctor_hir_id() { + v.annotate(ctor_hir_id, &var.node.attrs, var.span, AnnotationKind::Required, + |_| {}); + } + + intravisit::walk_variant(v, var, g, item_id) + }) } fn visit_struct_field(&mut self, s: &'tcx StructField) { @@ -364,7 +371,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { } fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: HirId) { - self.check_missing_stability(var.node.data.hir_id(), var.span, "variant"); + self.check_missing_stability(var.node.id, var.span, "variant"); intravisit::walk_variant(self, var, g, item_id); } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 9f2027e7d05..b54b92b798e 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2405,12 +2405,13 @@ impl<'tcx> Debug for Rvalue<'tcx> { AggregateKind::Adt(adt_def, variant, substs, _user_ty, _) => { let variant_def = &adt_def.variants[variant]; + let did = variant_def.variant_did_or_parent_struct_did(); let f = &mut *fmt; ty::tls::with(|tcx| { let substs = tcx.lift(&substs).expect("could not lift for printing"); FmtPrinter::new(tcx, f, Namespace::ValueNS) - .print_def_path(variant_def.did, substs)?; + .print_def_path(did, substs)?; Ok(()) })?; diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index f5f2ec38bdf..ef232c06921 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1077,23 +1077,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { _ => ArgKind::empty() }).collect::>()) } - Node::Variant(&hir::Variant { - span, - node: hir::VariantKind { - data: hir::VariantData::Tuple(ref fields, ..), - .. - }, - .. - }) => { - (self.tcx.sess.source_map().def_span(span), - fields.iter().map(|field| - ArgKind::Arg(field.ident.to_string(), "_".to_string()) - ).collect::>()) - } - Node::StructCtor(ref variant_data) => { - (self.tcx.sess.source_map().def_span( - self.tcx.hir().span_by_hir_id(variant_data.hir_id())), - vec![ArgKind::empty(); variant_data.fields().len()]) + Node::Ctor(_, ref variant_data) => { + let span = variant_data.ctor_hir_id() + .map(|hir_id| self.tcx.hir().span_by_hir_id(hir_id)) + .unwrap_or(DUMMY_SP); + let span = self.tcx.sess.source_map().def_span(span); + + (span, vec![ArgKind::empty(); variant_data.fields().len()]) } _ => panic!("non-FnLike node found: {:?}", node), } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 995e85fc5f4..84ce826c6a5 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -150,8 +150,7 @@ impl<'tcx> InstanceDef<'tcx> { _ => return true }; match tcx.def_key(def_id).disambiguated_data.data { - DefPathData::StructCtor | - DefPathData::EnumVariant(..) | + DefPathData::StructCtor | DefPathData::VariantCtor | DefPathData::ClosureExpr => true, _ => false } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 91b84b68802..0de91af8460 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -8,7 +8,6 @@ use crate::hir::{map as hir_map, FreevarMap, GlobMap, TraitMap}; use crate::hir::{HirId, Node}; use crate::hir::def::{Def, CtorKind, ExportMap}; use crate::hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use crate::hir::map::DefPathData; use rustc_data_structures::svh::Svh; use rustc_macros::HashStable; use crate::ich::Fingerprint; @@ -1775,12 +1774,19 @@ bitflags! { #[derive(HashStable)] pub struct AdtFlags: u32 { const NO_ADT_FLAGS = 0; + /// Indicates whether the ADT is an enum. const IS_ENUM = 1 << 0; + /// Indicates whether the ADT is a union. const IS_UNION = 1 << 1; + /// Indicates whether the ADT is a struct. const IS_STRUCT = 1 << 2; + /// Indicates whether the ADT is a struct and has a constructor. const HAS_CTOR = 1 << 3; + /// Indicates whether the type is a `PhantomData`. const IS_PHANTOM_DATA = 1 << 4; + /// Indicates whether the type has a `#[fundamental]` attribute. const IS_FUNDAMENTAL = 1 << 5; + /// Indicates whether the type is a `Box`. const IS_BOX = 1 << 6; /// Indicates whether the type is an `Arc`. const IS_ARC = 1 << 7; @@ -1801,77 +1807,149 @@ bitflags! { } } +/// Definition of a variant -- a struct's fields or a enum variant. #[derive(Debug)] pub struct VariantDef { - /// The variant's `DefId`. If this is a tuple-like struct, - /// this is the `DefId` of the struct's ctor. - pub did: DefId, - pub ident: Ident, // struct's name if this is a struct + /// `DefId` that identifies this enum variant. If this `VariantDef` is part of a struct or + /// union then this is `None`. + variant_did: Option, + /// `DefId` that identifies this enum variant or struct's constructor. If this is a + /// `Struct`-variant then this is `None`. + ctor_did: Option, + /// Variant or struct name. + pub ident: Ident, + /// Discriminant of this variant. pub discr: VariantDiscr, + /// Fields of this variant. pub fields: Vec, + /// Type of constructor of variant. pub ctor_kind: CtorKind, + /// `DefId` of the parent `AdtDef` representing the struct or enum. This is required as there + /// is a valid scenario where this type represents a `Struct`-struct and both `ctor_did` and + /// `variant_did` would be `None` and we would still want a way to get back to the original + /// `AdtDef`. + parent_did: DefId, + /// Flags of the variant (e.g. is field list non-exhaustive)? flags: VariantFlags, + /// Recovered? pub recovered: bool, } impl<'a, 'gcx, 'tcx> VariantDef { /// Creates a new `VariantDef`. /// - /// - `did` is the `DefId` used for the variant. - /// This is the constructor `DefId` for tuple stucts, and the variant `DefId` for everything - /// else. - /// - `attribute_def_id` is the DefId that has the variant's attributes. - /// This is the struct `DefId` for structs, and the variant `DefId` for variants. + /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef` + /// represents an enum variant). /// - /// Note that we *could* use the constructor `DefId`, because the constructor attributes - /// redirect to the base attributes, but compiling a small crate requires - /// loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any + /// `ctor_did` is the `DefId` that identifies the constructor of unit or + /// tuple-variants/structs. If this is a `struct`-variant then this should be `None`. + /// + /// `parent_did` is the `DefId` of the `AdtDef` representing the enum or struct that + /// owns this variant. It is used for checking if a struct has `#[non_exhaustive]` w/out having + /// to go through the redirect of checking the ctor's attributes - but compiling a small crate + /// requires loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any /// built-in trait), and we do not want to load attributes twice. /// /// If someone speeds up attribute loading to not be a performance concern, they can /// remove this hack and use the constructor `DefId` everywhere. pub fn new( tcx: TyCtxt<'a, 'gcx, 'tcx>, - did: DefId, ident: Ident, + variant_did: Option, + ctor_did: Option, discr: VariantDiscr, fields: Vec, - adt_kind: AdtKind, ctor_kind: CtorKind, - attribute_def_id: DefId, + adt_kind: AdtKind, + parent_did: DefId, recovered: bool, ) -> Self { - debug!("VariantDef::new({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?})", did, ident, discr, - fields, adt_kind, ctor_kind, attribute_def_id); + debug!( + "VariantDef::new(ident = {:?}, variant_did = {:?}, ctor_did = {:?}, discr = {:?}, + fields = {:?}, ctor_kind = {:?}, adt_kind = {:?}, parent_did = {:?})", + ident, variant_did, ctor_did, discr, fields, ctor_kind, adt_kind, parent_did, + ); + let mut flags = VariantFlags::NO_VARIANT_FLAGS; - if adt_kind == AdtKind::Struct && tcx.has_attr(attribute_def_id, "non_exhaustive") { - debug!("found non-exhaustive field list for {:?}", did); + if adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, "non_exhaustive") { + debug!("found non-exhaustive field list for {:?}", parent_did); flags = flags | VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; } + VariantDef { - did, + variant_did, + ctor_did, ident, discr, fields, ctor_kind, flags, + parent_did, recovered, } } + /// Is this field list non-exhaustive? #[inline] pub fn is_field_list_non_exhaustive(&self) -> bool { self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE) } + + /// Returns `true` if this `VariantDef` represents a enum's variant. + #[inline] + pub fn is_enum_variant(&self) -> bool { + self.variant_did.is_some() + } + + /// Returns `true` if this `VariantDef` represents a struct. + #[inline] + pub fn is_struct(&self) -> bool { + !self.is_enum_variant() + } + + /// Returns the `DefId` of this variant if this `VariantDef` represents an enum's variant, or + /// returns the `DefId` of the parent struct. + #[inline] + pub fn variant_did_or_parent_struct_did(&self) -> DefId { + self.variant_did.unwrap_or(self.parent_did) + } + + /// Returns `true` if the variant is defined in the local crate. + #[inline] + pub fn is_local(&self) -> bool { + self.variant_did_or_parent_struct_did().krate == LOCAL_CRATE + } + + /// Returns the `DefId` of this variant if this `VariantDef` represents an enum's variant or + /// panics. + #[inline] + pub fn variant_did(&self) -> DefId { + self.variant_did.expect("enum variant without a variant id") + } + + /// Returns the `DefId` of this variant's constructor if this is a unit or + /// tuple-variant/struct. + #[inline] + pub fn ctor_did(&self) -> Option { + self.ctor_did + } + + /// Returns the `AdtDef` representing the struct or enum associated with this `VariantDef`. + #[inline] + pub fn adt_def(&self, tcx: TyCtxt<'a, 'tcx, 'gcx>) -> &'tcx AdtDef { + tcx.adt_def(self.parent_did) + } } impl_stable_hash_for!(struct VariantDef { - did, + variant_did, + ctor_did, ident -> (ident.name), discr, fields, ctor_kind, flags, + parent_did, recovered }); @@ -1898,12 +1976,15 @@ pub struct FieldDef { /// The definition of an abstract data type -- a struct or enum. /// -/// These are all interned (by `intern_adt_def`) into the `adt_defs` -/// table. +/// These are all interned (by `intern_adt_def`) into the `adt_defs` table. pub struct AdtDef { + /// `DefId` of the struct, enum or union item. pub did: DefId, + /// Variants of the ADT. If this is a struct or enum, then there will be a single variant. pub variants: IndexVec, + /// Flags of the ADT (e.g. is this a struct? is this non-exhaustive?) flags: AdtFlags, + /// Repr options provided by the user. pub repr: ReprOptions, } @@ -2102,11 +2183,14 @@ impl ReprOptions { } impl<'a, 'gcx, 'tcx> AdtDef { - fn new(tcx: TyCtxt<'_, '_, '_>, - did: DefId, - kind: AdtKind, - variants: IndexVec, - repr: ReprOptions) -> Self { + /// Creates a new `AdtDef`. + fn new( + tcx: TyCtxt<'_, '_, '_>, + did: DefId, + kind: AdtKind, + variants: IndexVec, + repr: ReprOptions + ) -> Self { debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr); let mut flags = AdtFlags::NO_ADT_FLAGS; @@ -2120,13 +2204,8 @@ impl<'a, 'gcx, 'tcx> AdtDef { AdtKind::Struct => AdtFlags::IS_STRUCT, }; - if let AdtKind::Struct = kind { - let variant_def = &variants[VariantIdx::new(0)]; - let def_key = tcx.def_key(variant_def.did); - match def_key.disambiguated_data.data { - DefPathData::StructCtor => flags |= AdtFlags::HAS_CTOR, - _ => (), - } + if kind == AdtKind::Struct && variants[VariantIdx::new(0)].ctor_did.is_some() { + flags |= AdtFlags::HAS_CTOR; } let attrs = tcx.get_attrs(did); @@ -2154,21 +2233,25 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } + /// Returns `true` if this is a struct. #[inline] pub fn is_struct(&self) -> bool { self.flags.contains(AdtFlags::IS_STRUCT) } + /// Returns `true` if this is a union. #[inline] pub fn is_union(&self) -> bool { self.flags.contains(AdtFlags::IS_UNION) } + /// Returns `true` if this is a enum. #[inline] pub fn is_enum(&self) -> bool { self.flags.contains(AdtFlags::IS_ENUM) } + /// Returns `true` if the variant list of this ADT is `#[non_exhaustive]`. #[inline] pub fn is_variant_list_non_exhaustive(&self) -> bool { self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE) @@ -2186,6 +2269,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } + /// Returns a description of this abstract data type. pub fn descr(&self) -> &'static str { match self.adt_kind() { AdtKind::Struct => "struct", @@ -2194,6 +2278,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } + /// Returns a description of a variant of this abstract data type. #[inline] pub fn variant_descr(&self) -> &'static str { match self.adt_kind() { @@ -2266,25 +2351,53 @@ impl<'a, 'gcx, 'tcx> AdtDef { self.variants.iter().all(|v| v.fields.is_empty()) } - pub fn variant_with_id(&self, vid: DefId) -> &VariantDef { + pub fn variant_with_variant_id(&self, vid: DefId) -> &VariantDef { self.variants .iter() - .find(|v| v.did == vid) - .expect("variant_with_id: unknown variant") + .find(|v| v.variant_did.map(|did| did == vid).unwrap_or(false)) + .expect("variant_with_variant_id: unknown variant") } - pub fn variant_index_with_id(&self, vid: DefId) -> VariantIdx { + pub fn variant_with_ctor_id(&self, cid: DefId) -> &VariantDef { + self.variants + .iter() + .find(|v| v.ctor_did.map(|did| did == cid).unwrap_or(false)) + .expect("variant_with_ctor_id: unknown variant") + } + + pub fn variant_index_with_variant_id(&self, vid: DefId) -> VariantIdx { self.variants .iter_enumerated() - .find(|(_, v)| v.did == vid) - .expect("variant_index_with_id: unknown variant") + .find(|(_, v)| v.variant_did.map(|did| did == vid).unwrap_or(false)) + .expect("variant_index_with_variant_id: unknown variant") + .0 + } + + pub fn variant_index_with_ctor_id(&self, cid: DefId) -> VariantIdx { + self.variants + .iter_enumerated() + .find(|(_, v)| v.ctor_did.map(|did| did == cid).unwrap_or(false)) + .expect("variant_index_with_ctor_id: unknown variant") + .0 + } + + pub fn variant_index_with_ctor_or_variant_id(&self, id: DefId) -> VariantIdx { + self.variants + .iter_enumerated() + .find(|(_, v)| { + let ctor = v.ctor_did.map(|did| did == id); + let variant = v.variant_did.map(|did| did == id); + ctor.or(variant).unwrap_or(false) + }) + .expect("variant_index_with_ctor_or_variant_id: unknown variant") .0 } pub fn variant_of_def(&self, def: Def) -> &VariantDef { match def { - Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid), - Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) | + Def::Variant(vid) => self.variant_with_variant_id(vid), + Def::Ctor(hir::CtorOf::Variant, cid, ..) => self.variant_with_ctor_id(cid), + Def::Struct(..) | Def::Ctor(..) | Def::Union(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => self.non_enum_variant(), _ => bug!("unexpected def {:?} in variant_of_def", def) @@ -2820,7 +2933,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option { variant.fields.iter().position(|field| { - self.adjust_ident(ident, variant.did, hir::DUMMY_HIR_ID).0 == field.ident.modern() + let did = variant.variant_did.unwrap_or(variant.parent_did); + self.adjust_ident(ident, did, hir::DUMMY_HIR_ID).0 == field.ident.modern() }) } @@ -2895,16 +3009,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // or variant or their constructors, panics otherwise. pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef { match def { - Def::Variant(did) | Def::VariantCtor(did, ..) => { + Def::Variant(did) => { let enum_did = self.parent(did).unwrap(); - self.adt_def(enum_did).variant_with_id(did) + self.adt_def(enum_did).variant_with_variant_id(did) } Def::Struct(did) | Def::Union(did) => { self.adt_def(did).non_enum_variant() } - Def::StructCtor(ctor_did, ..) => { - let did = self.parent(ctor_did).expect("struct ctor has no parent"); - self.adt_def(did).non_enum_variant() + Def::Ctor(hir::CtorOf::Variant, variant_ctor_did, ..) => { + let variant_did = self.parent(variant_ctor_did).unwrap(); + let enum_did = self.parent(variant_did).unwrap(); + self.adt_def(enum_did).variant_with_ctor_id(variant_ctor_did) + } + Def::Ctor(hir::CtorOf::Struct, ctor_did, ..) => { + let struct_did = self.parent(ctor_did).expect("struct ctor has no parent"); + self.adt_def(struct_did).non_enum_variant() } _ => bug!("expect_variant_def used with unexpected def {:?}", def) } @@ -2912,16 +3031,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Given a `VariantDef`, returns the def-id of the `AdtDef` of which it is a part. pub fn adt_def_id_of_variant(self, variant_def: &'tcx VariantDef) -> DefId { - let def_key = self.def_key(variant_def.did); - match def_key.disambiguated_data.data { - // for enum variants and tuple structs, the def-id of the ADT itself - // is the *parent* of the variant - DefPathData::EnumVariant(..) | DefPathData::StructCtor => - DefId { krate: variant_def.did.krate, index: def_key.parent.unwrap() }, - - // otherwise, for structs and unions, they share a def-id - _ => variant_def.did, - } + variant_def.parent_did } pub fn item_name(self, id: DefId) -> InternedString { @@ -2929,16 +3039,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.original_crate_name(id.krate).as_interned_str() } else { let def_key = self.def_key(id); - // The name of a StructCtor is that of its struct parent. - if let hir_map::DefPathData::StructCtor = def_key.disambiguated_data.data { - self.item_name(DefId { - krate: id.krate, - index: def_key.parent.unwrap() - }) - } else { - def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| { + match def_key.disambiguated_data.data { + // The name of a `StructCtor` or `VariantCtor` is that of its parent. + hir_map::DefPathData::StructCtor | hir_map::DefPathData::VariantCtor => + self.item_name(DefId { + krate: id.krate, + index: def_key.parent.unwrap() + }), + _ => def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| { bug!("item_name: no name for {:?}", self.def_path(id)); - }) + }), } } } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 7701a10d8ee..3d6a2cf9224 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -286,13 +286,17 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key); // For a UnitStruct or TupleStruct we want the name of its parent rather than . - if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data { - let parent = DefId { - krate: def_id.krate, - index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"), - }; + match cur_def_key.disambiguated_data.data { + DefPathData::StructCtor | DefPathData::VariantCtor => { + let parent = DefId { + krate: def_id.krate, + index: cur_def_key.parent + .expect("DefPathData::StructCtor/VariantData missing a parent"), + }; - cur_def_key = self.tcx().def_key(parent); + cur_def_key = self.tcx().def_key(parent); + }, + _ => {}, } let visible_parent = match visible_parent_map.get(&def_id).cloned() { @@ -860,6 +864,7 @@ impl TyCtxt<'_, '_, '_> { DefPathData::AnonConst | DefPathData::ConstParam(..) | DefPathData::ClosureExpr | + DefPathData::VariantCtor | DefPathData::StructCtor => Namespace::ValueNS, DefPathData::MacroDef(..) => Namespace::MacroNS, @@ -1024,7 +1029,7 @@ impl Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { // Skip `::{{constructor}}` on tuple/unit structs. match disambiguated_data.data { - DefPathData::StructCtor => return Ok(self), + DefPathData::StructCtor | DefPathData::VariantCtor => return Ok(self), _ => {} } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 4e1d360562d..7e38ce6377c 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -85,8 +85,7 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) let owner_id = tcx.hir().as_local_hir_id(owner_def_id).unwrap(); match tcx.hir().get_by_hir_id(owner_id) { - Node::StructCtor(_) | - Node::Variant(_) => { + Node::Ctor(_, _) => { // We get invoked with anything that has MIR, but some of // those things (notably the synthesized constructors from // tuple structs/variants) do not have an associated body diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 8153653e48b..6d694dcfac7 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -528,7 +528,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { fn check_variant(&mut self, cx: &LateContext<'_, '_>, v: &hir::Variant, _: &hir::Generics) { self.check_missing_docs_attrs(cx, - Some(v.node.data.hir_id()), + Some(v.node.id), &v.node.attrs, v.span, "a variant"); diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 67a249e605e..995532a00cd 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -407,6 +407,14 @@ impl cstore::CStore { self.get_crate_data(def.krate).get_struct_field_names(def.index) } + pub fn ctor_kind_untracked(&self, def: DefId) -> def::CtorKind { + self.get_crate_data(def.krate).get_ctor_kind(def.index) + } + + pub fn item_attrs_untracked(&self, def: DefId, sess: &Session) -> Lrc<[ast::Attribute]> { + self.get_crate_data(def.krate).get_item_attrs(def.index, sess) + } + pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec { let mut result = vec![]; self.get_crate_data(def_id.krate) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index c608c03095a..c6f7b46d383 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -544,13 +544,14 @@ impl<'a, 'tcx> CrateMetadata { } } - fn get_variant(&self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - item: &Entry<'_>, - index: DefIndex, - adt_kind: ty::AdtKind) - -> ty::VariantDef - { + fn get_variant( + &self, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + item: &Entry<'_>, + index: DefIndex, + parent_did: DefId, + adt_kind: ty::AdtKind + ) -> ty::VariantDef { let data = match item.kind { EntryKind::Variant(data) | EntryKind::Struct(data, _) | @@ -558,13 +559,18 @@ impl<'a, 'tcx> CrateMetadata { _ => bug!(), }; - let def_id = self.local_def_id(data.struct_ctor.unwrap_or(index)); - let attribute_def_id = self.local_def_id(index); + let variant_did = if adt_kind == ty::AdtKind::Enum { + Some(self.local_def_id(index)) + } else { + None + }; + let ctor_did = data.ctor.map(|index| self.local_def_id(index)); ty::VariantDef::new( tcx, - def_id, Ident::from_interned_str(self.item_name(index)), + variant_did, + ctor_did, data.discr, item.children.decode(self).map(|index| { let f = self.entry(index); @@ -574,9 +580,9 @@ impl<'a, 'tcx> CrateMetadata { vis: f.visibility.decode(self) } }).collect(), - adt_kind, data.ctor_kind, - attribute_def_id, + adt_kind, + parent_did, false, ) } @@ -599,11 +605,11 @@ impl<'a, 'tcx> CrateMetadata { item.children .decode(self) .map(|index| { - self.get_variant(tcx, &self.entry(index), index, kind) + self.get_variant(tcx, &self.entry(index), index, did, kind) }) .collect() } else { - std::iter::once(self.get_variant(tcx, &item, item_id, kind)).collect() + std::iter::once(self.get_variant(tcx, &item, item_id, did, kind)).collect() }; tcx.alloc_adt_def(did, kind, variants, repr) @@ -808,23 +814,22 @@ impl<'a, 'tcx> CrateMetadata { // Re-export lists automatically contain constructors when necessary. match def { Def::Struct(..) => { - if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) { + if let Some(ctor_def_id) = self.get_ctor_def_id(child_index) { let ctor_kind = self.get_ctor_kind(child_index); - let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind); - callback(def::Export { - def: ctor_def, - vis: self.get_visibility(ctor_def_id.index), - ident, span, - }); + let ctor_def = Def::Ctor( + hir::CtorOf::Struct, ctor_def_id, ctor_kind); + let vis = self.get_visibility(ctor_def_id.index); + callback(def::Export { def: ctor_def, vis, ident, span }); } } - Def::Variant(def_id) => { - // Braced variants, unlike structs, generate unusable names in - // value namespace, they are reserved for possible future use. - let ctor_kind = self.get_ctor_kind(child_index); - let ctor_def = Def::VariantCtor(def_id, ctor_kind); - let vis = self.get_visibility(child_index); - callback(def::Export { def: ctor_def, ident, vis, span }); + Def::Variant(..) => { + if let Some(ctor_def_id) = self.get_ctor_def_id(child_index) { + let ctor_kind = self.get_ctor_kind(child_index); + let ctor_def = Def::Ctor( + hir::CtorOf::Variant, ctor_def_id, ctor_kind); + let vis = self.get_visibility(ctor_def_id.index); + callback(def::Export { def: ctor_def, ident, vis, span }); + } } _ => {} } @@ -925,10 +930,13 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option { + pub fn get_ctor_def_id(&self, node_id: DefIndex) -> Option { match self.entry(node_id).kind { EntryKind::Struct(data, _) => { - data.decode(self).struct_ctor.map(|index| self.local_def_id(index)) + data.decode(self).ctor.map(|index| self.local_def_id(index)) + } + EntryKind::Variant(data) => { + data.decode(self).ctor.map(|index| self.local_def_id(index)) } _ => None, } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index ce0618d4599..1af59f314bc 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -572,24 +572,21 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { /// will have to lookup the adt-def by its id, and that gives us /// the right to access any information in the adt-def (including, /// e.g., the length of the various vectors). - fn encode_enum_variant_info(&mut self, - (enum_did, Untracked(index)): (DefId, Untracked)) - -> Entry<'tcx> { + fn encode_enum_variant_info( + &mut self, + (enum_did, Untracked(index)): (DefId, Untracked), + ) -> Entry<'tcx> { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; - let def_id = variant.did; + let def_id = variant.variant_did(); debug!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id); let data = VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - struct_ctor: None, - ctor_sig: if variant.ctor_kind == CtorKind::Fn { - Some(self.lazy(&tcx.fn_sig(def_id))) - } else { - None - } + ctor: variant.ctor_did().map(|did| did.index), + ctor_sig: None, }; let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap(); @@ -622,6 +619,57 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } } + /// Encode the constructor for the given variant of the given ADT. See + /// `encode_enum_variant_info` for an explanation about why the index is untracked. + fn encode_enum_variant_ctor( + &mut self, + (enum_did, Untracked(index)): (DefId, Untracked), + ) -> Entry<'tcx> { + let tcx = self.tcx; + let def = tcx.adt_def(enum_did); + let variant = &def.variants[index]; + let def_id = variant.ctor_did().unwrap(); + debug!("IsolatedEncoder::encode_enum_variant_ctor({:?})", def_id); + + let data = VariantData { + ctor_kind: variant.ctor_kind, + discr: variant.discr, + ctor: Some(def_id.index), + ctor_sig: if variant.ctor_kind == CtorKind::Fn { + Some(self.lazy(&tcx.fn_sig(def_id))) + } else { + None + } + }; + + // Variant constructors have the same visibility as the parent enums. + let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap(); + let enum_vis = &tcx.hir().expect_item_by_hir_id(enum_id).vis; + + Entry { + kind: EntryKind::Variant(self.lazy(&data)), + visibility: self.lazy(&ty::Visibility::from_hir(enum_vis, enum_id, tcx)), + span: self.lazy(&tcx.def_span(def_id)), + attributes: LazySeq::empty(), + children: LazySeq::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: LazySeq::empty(), + variances: if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id) + } else { + LazySeq::empty() + }, + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + predicates_defined_on: None, + + mir: self.encode_optimized_mir(def_id), + } + } + fn encode_info_for_mod(&mut self, FromId(id, (md, attrs, vis)): FromId<(&hir::Mod, &[ast::Attribute], @@ -678,7 +726,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let def_id = field.did; debug!("IsolatedEncoder::encode_field({:?})", def_id); - let variant_id = tcx.hir().as_local_hir_id(variant.did).unwrap(); + let variant_id = tcx.hir() + .as_local_hir_id(variant.variant_did_or_parent_struct_did()) + .unwrap(); let variant_data = tcx.hir().expect_variant_data(variant_id); Entry { @@ -710,7 +760,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let data = VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - struct_ctor: Some(def_id.index), + ctor: Some(def_id.index), ctor_sig: if variant.ctor_kind == CtorKind::Fn { Some(self.lazy(&tcx.fn_sig(def_id))) } else { @@ -1072,18 +1122,15 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { // Encode def_ids for each field and method // for methods, write all the stuff get_trait_method // needs to know - let struct_ctor = if !struct_def.is_struct() { - Some(tcx.hir().local_def_id_from_hir_id(struct_def.hir_id()).index) - } else { - None - }; + let ctor = struct_def.ctor_hir_id() + .map(|ctor_hir_id| tcx.hir().local_def_id_from_hir_id(ctor_hir_id).index); let repr_options = get_repr_options(&tcx, def_id); EntryKind::Struct(self.lazy(&VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - struct_ctor, + ctor, ctor_sig: None, }), repr_options) } @@ -1094,7 +1141,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { EntryKind::Union(self.lazy(&VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - struct_ctor: None, + ctor: None, ctor_sig: None, }), repr_options) } @@ -1171,8 +1218,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { hir::ItemKind::Enum(..) => { let def = self.tcx.adt_def(def_id); self.lazy_seq(def.variants.iter().map(|v| { - assert!(v.did.is_local()); - v.did.index + let did = v.variant_did(); + assert!(did.is_local()); + did.index })) } hir::ItemKind::Struct(..) | @@ -1765,17 +1813,23 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { let def = self.tcx.adt_def(def_id); for (i, variant) in def.variants.iter_enumerated() { - self.record(variant.did, + self.record(variant.variant_did(), IsolatedEncoder::encode_enum_variant_info, (def_id, Untracked(i))); + + if let Some(ctor_hir_did) = variant.ctor_did() { + self.record(ctor_hir_did, + IsolatedEncoder::encode_enum_variant_ctor, + (def_id, Untracked(i))); + } } } hir::ItemKind::Struct(ref struct_def, _) => { self.encode_fields(def_id); // If the struct has a constructor, encode it. - if !struct_def.is_struct() { - let ctor_def_id = self.tcx.hir().local_def_id_from_hir_id(struct_def.hir_id()); + if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { + let ctor_def_id = self.tcx.hir().local_def_id_from_hir_id(ctor_hir_id); self.record(ctor_def_id, IsolatedEncoder::encode_struct_ctor, (def_id, ctor_def_id)); diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index afeea9947b5..5b6166ebeaf 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -445,11 +445,8 @@ impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig }); pub struct VariantData<'tcx> { pub ctor_kind: CtorKind, pub discr: ty::VariantDiscr, - - /// If this is a struct's only variant, this - /// is the index of the "struct ctor" item. - pub struct_ctor: Option, - + /// If this is unit or tuple-variant/struct, then this is the index of the ctor id. + pub ctor: Option, /// If this is a tuple struct or variant /// ctor, this is its "function" signature. pub ctor_sig: Option>>, @@ -458,7 +455,7 @@ pub struct VariantData<'tcx> { impl_stable_hash_for!(struct VariantData<'tcx> { ctor_kind, discr, - struct_ctor, + ctor, ctor_sig }); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 1138edcb375..0283352066c 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -31,10 +31,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t // Figure out what primary body this item has. let (body_id, return_ty_span) = match tcx.hir().get_by_hir_id(id) { - Node::Variant(variant) => - return create_constructor_shim(tcx, id, &variant.node.data), - Node::StructCtor(ctor) => - return create_constructor_shim(tcx, id, ctor), + Node::Ctor(_, ctor) => return create_constructor_shim(tcx, id, ctor), Node::Expr(hir::Expr { node: hir::ExprKind::Closure(_, decl, body_id, _, _), .. }) | Node::Item(hir::Item { node: hir::ItemKind::Fn(decl, _, _, body_id), .. }) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index b83f048114b..eb50bd727db 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -261,10 +261,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // Tuple-like ADTs are represented as ExprKind::Call. We convert them here. expr_ty.ty_adt_def().and_then(|adt_def| { match path.def { - Def::VariantCtor(variant_id, CtorKind::Fn) => { - Some((adt_def, adt_def.variant_index_with_id(variant_id))) + Def::Ctor(hir::CtorOf::Variant, variant_ctor_id, CtorKind::Fn) => { + Some((adt_def, adt_def.variant_index_with_ctor_id(variant_ctor_id))) } - Def::StructCtor(_, CtorKind::Fn) | + Def::Ctor(hir::CtorOf::Struct, _, CtorKind::Fn) | Def::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))), _ => None, } @@ -486,7 +486,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::Variant(variant_id) => { assert!(base.is_none()); - let index = adt.variant_index_with_id(variant_id); + let index = adt.variant_index_with_variant_id(variant_id); let user_provided_types = cx.tables().user_provided_types(); let user_ty = user_provided_types.get(expr.hir_id) .map(|u_ty| *u_ty); @@ -677,8 +677,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, .ty_adt_def() .and_then(|adt_def| { match def { - Def::VariantCtor(variant_id, CtorKind::Const) => { - let idx = adt_def.variant_index_with_id(variant_id); + Def::Ctor(hir::CtorOf::Variant, variant_ctor_id, CtorKind::Const) => { + let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id); let (d, o) = adt_def.discriminant_def_for_variant(idx); use rustc::ty::util::IntTypeExt; let ty = adt_def.repr.discr_type(); @@ -804,8 +804,7 @@ fn user_substs_applied_to_def( // `Fn` but with the user-given substitutions. Def::Fn(_) | Def::Method(_) | - Def::StructCtor(_, CtorKind::Fn) | - Def::VariantCtor(_, CtorKind::Fn) | + Def::Ctor(_, _, CtorKind::Fn) | Def::Const(_) | Def::AssociatedConst(_) => cx.tables().user_provided_types().get(hir_id).map(|u_ty| *u_ty), @@ -813,8 +812,7 @@ fn user_substs_applied_to_def( // `None`). This has the type of the enum/struct that defines // this variant -- but with the substitutions given by the // user. - Def::StructCtor(_def_id, CtorKind::Const) | - Def::VariantCtor(_def_id, CtorKind::Const) => + Def::Ctor(_, _, CtorKind::Const) => cx.user_substs_applied_to_ty_of_hir_id(hir_id), // `Self` is used in expression as a tuple struct constructor or an unit struct constructor @@ -911,8 +909,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // A regular function, constructor function or a constant. Def::Fn(_) | Def::Method(_) | - Def::StructCtor(_, CtorKind::Fn) | - Def::VariantCtor(_, CtorKind::Fn) | + Def::Ctor(_, _, CtorKind::Fn) | Def::SelfCtor(..) => { let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def); debug!("convert_path_expr: user_ty={:?}", user_ty); @@ -956,8 +953,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } }, - Def::StructCtor(def_id, CtorKind::Const) | - Def::VariantCtor(def_id, CtorKind::Const) => { + Def::Ctor(_, def_id, CtorKind::Const) => { let user_provided_types = cx.tables.user_provided_types(); let user_provided_type = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty); debug!("convert_path_expr: user_provided_type={:?}", user_provided_type); @@ -968,7 +964,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ty::Adt(adt_def, substs) => { ExprKind::Adt { adt_def, - variant_index: adt_def.variant_index_with_id(def_id), + variant_index: adt_def.variant_index_with_ctor_id(def_id), substs, user_ty: user_provided_type, fields: vec![], diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 88d1eb2ee0b..9637a111f42 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -435,7 +435,7 @@ impl<'tcx> Constructor<'tcx> { adt: &'tcx ty::AdtDef, ) -> VariantIdx { match self { - &Variant(vid) => adt.variant_index_with_id(vid), + &Variant(id) => adt.variant_index_with_ctor_or_variant_id(id), &Single => { assert!(!adt.is_enum()); VariantIdx::new(0) @@ -659,7 +659,7 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>, ty::Adt(def, substs) if def.is_enum() => { def.variants.iter() .filter(|v| !cx.is_variant_uninhabited(v, substs)) - .map(|v| Variant(v.did)) + .map(|v| v.ctor_did().map_or_else(|| Variant(v.variant_did()), |did| Variant(did))) .collect() } ty::Char => { @@ -1307,7 +1307,9 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, PatternKind::Binding { .. } | PatternKind::Wild => None, PatternKind::Leaf { .. } | PatternKind::Deref { .. } => Some(vec![Single]), PatternKind::Variant { adt_def, variant_index, .. } => { - Some(vec![Variant(adt_def.variants[variant_index].did)]) + let variant = &adt_def.variants[variant_index]; + Some(variant.ctor_did() + .map_or_else(|| vec![Variant(variant.variant_did())], |did| vec![Variant(did)])) } PatternKind::Constant { value } => Some(vec![ConstantValue(value)]), PatternKind::Range(PatternRange { lo, hi, ty, end }) => @@ -1742,11 +1744,11 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( PatternKind::Variant { adt_def, variant_index, ref subpatterns, .. } => { let ref variant = adt_def.variants[variant_index]; - if *constructor == Variant(variant.did) { - Some(patterns_for_variant(subpatterns, wild_patterns)) - } else { - None - } + variant.ctor_did() + .map(|did| Variant(did)) + .or_else(|| Some(Variant(variant.variant_did()))) + .filter(|variant_constructor| variant_constructor == constructor) + .map(|_| patterns_for_variant(subpatterns, wild_patterns)) } PatternKind::Leaf { ref subpatterns } => { diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 8614be8d407..8349f21cdb4 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -733,8 +733,16 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ty: Ty<'tcx>, subpatterns: Vec>, ) -> PatternKind<'tcx> { + let def = match def { + Def::Ctor(hir::CtorOf::Variant, variant_ctor_id, ..) => { + let variant_id = self.tcx.parent(variant_ctor_id).unwrap(); + Def::Variant(variant_id) + }, + def => def, + }; + let mut kind = match def { - Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => { + Def::Variant(variant_id) => { let enum_id = self.tcx.parent(variant_id).unwrap(); let adt_def = self.tcx.adt_def(enum_id); if adt_def.is_enum() { @@ -749,7 +757,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatternKind::Variant { adt_def, substs, - variant_index: adt_def.variant_index_with_id(variant_id), + variant_index: adt_def.variant_index_with_variant_id(variant_id), subpatterns, } } else { @@ -757,7 +765,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } } - Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) | + Def::Struct(..) | Def::Ctor(hir::CtorOf::Struct, ..) | Def::Union(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => { PatternKind::Leaf { subpatterns } } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index f1fbc80edfb..cb25db73cd2 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -880,7 +880,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, }; let variant_no = if adt_def.is_enum() { - adt_def.variant_index_with_id(def_id) + adt_def.variant_index_with_ctor_id(def_id) } else { VariantIdx::new(0) }; diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 13bcdc26a5e..5e5e451b75b 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -1,5 +1,4 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE}; -use rustc::hir::def::CtorKind; use rustc::mir::*; use rustc::mir::visit::Visitor; use rustc::ty::{self, TyCtxt}; @@ -587,15 +586,12 @@ fn write_mir_sig( trace!("write_mir_sig: {:?}", src.instance); let descr = tcx.describe_def(src.def_id()); let is_function = match descr { - Some(Def::Fn(_)) | Some(Def::Method(_)) | Some(Def::Variant(..)) | - Some(Def::StructCtor(_, CtorKind::Fn)) => true, + Some(Def::Fn(_)) | Some(Def::Method(_)) | Some(Def::Ctor(..)) => true, _ => tcx.is_closure(src.def_id()), }; match (descr, src.promoted) { (_, Some(i)) => write!(w, "{:?} in ", i)?, - (Some(Def::StructCtor(..)), _) => write!(w, "struct ")?, - (Some(Def::Const(_)), _) - | (Some(Def::AssociatedConst(_)), _) => write!(w, "const ")?, + (Some(Def::Const(_)), _) | (Some(Def::AssociatedConst(_)), _) => write!(w, "const ")?, (Some(Def::Static(_, /*is_mutbl*/false)), _) => write!(w, "static ")?, (Some(Def::Static(_, /*is_mutbl*/true)), _) => write!(w, "static mut ")?, (_, _) if is_function => write!(w, "fn ")?, diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 6de98675a3d..71eb6ed7e05 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -322,8 +322,8 @@ fn check_expr_kind<'a, 'tcx>( hir::ExprKind::Path(ref qpath) => { let def = v.tables.qpath_def(qpath, e.hir_id); match def { - Def::VariantCtor(..) | Def::StructCtor(..) | - Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => Promotable, + Def::Ctor(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => + Promotable, // References to a static that are themselves within a static // are inherently promotable with the exception @@ -387,8 +387,7 @@ fn check_expr_kind<'a, 'tcx>( Def::Err }; let def_result = match def { - Def::StructCtor(_, CtorKind::Fn) | - Def::VariantCtor(_, CtorKind::Fn) | + Def::Ctor(_, _, CtorKind::Fn) | Def::SelfCtor(..) => Promotable, Def::Fn(did) => v.handle_const_fn_call(did), Def::Method(did) => { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 19b5fa1bfbe..96fdb6a4382 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -225,7 +225,7 @@ fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) let vis = match tcx.hir().get_by_hir_id(hir_id) { Node::Item(item) => &item.vis, Node::ForeignItem(foreign_item) => &foreign_item.vis, - Node::TraitItem(..) | Node::Variant(..) => { + Node::TraitItem(..) | Node::Variant(..) | Node::Ctor(hir::CtorOf::Variant, ..) => { return def_id_visibility(tcx, tcx.hir().get_parent_did_by_hir_id(hir_id)); } Node::ImplItem(impl_item) => { @@ -239,7 +239,7 @@ fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) node => bug!("unexpected node kind: {:?}", node), } } - Node::StructCtor(vdata) => { + Node::Ctor(hir::CtorOf::Struct, vdata) => { let struct_hir_id = tcx.hir().get_parent_item(hir_id); let item = match tcx.hir().get_by_hir_id(struct_hir_id) { Node::Item(item) => item, @@ -504,7 +504,10 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { match item.node { hir::ItemKind::Enum(ref def, _) => { for variant in &def.variants { - let variant_level = self.update(variant.node.data.hir_id(), item_level); + let variant_level = self.update(variant.node.id, item_level); + if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() { + self.update(ctor_hir_id, item_level); + } for field in variant.node.data.fields() { self.update(field.hir_id, variant_level); } @@ -523,8 +526,8 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { - if !def.is_struct() { - self.update(def.hir_id(), item_level); + if let Some(ctor_hir_id) = def.ctor_hir_id() { + self.update(ctor_hir_id, item_level); } for field in def.fields() { if field.vis.node.is_pub() { @@ -624,7 +627,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { self.reach(item.hir_id, item_level).generics().predicates(); } for variant in &def.variants { - let variant_level = self.get(variant.node.data.hir_id()); + let variant_level = self.get(variant.node.id); if variant_level.is_some() { for field in variant.node.data.fields() { self.reach(field.hir_id, variant_level).ty(); @@ -1468,7 +1471,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { v: &'tcx hir::Variant, g: &'tcx hir::Generics, item_id: hir::HirId) { - if self.access_levels.is_reachable(v.node.data.hir_id()) { + if self.access_levels.is_reachable(v.node.id) { self.in_variant = true; intravisit::walk_variant(self, v, g, item_id); self.in_variant = false; diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 6fad4b2db97..72197d4a17a 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -12,7 +12,7 @@ use crate::Namespace::{self, TypeNS, ValueNS, MacroNS}; use crate::{resolve_error, resolve_struct_error, ResolutionError}; use rustc::bug; -use rustc::hir::def::*; +use rustc::hir::{self, def::*}; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::ty; use rustc::middle::cstore::CrateStore; @@ -532,9 +532,10 @@ impl<'a> Resolver<'a> { // If this is a tuple or unit struct, define a name // in the value namespace as well. - if !struct_def.is_struct() { - let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()), - CtorKind::from_ast(struct_def)); + if let Some(ctor_node_id) = struct_def.ctor_id() { + let ctor_def = Def::Ctor(hir::CtorOf::Struct, + self.definitions.local_def_id(ctor_node_id), + CtorKind::from_ast(struct_def)); self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion)); self.struct_constructors.insert(def.def_id(), (ctor_def, ctor_vis)); } @@ -581,7 +582,7 @@ impl<'a> Resolver<'a> { vis: ty::Visibility, expansion: Mark) { let ident = variant.node.ident; - let def_id = self.definitions.local_def_id(variant.node.data.id()); + let def_id = self.definitions.local_def_id(variant.node.id); // Define a name in the type namespace. let def = Def::Variant(def_id); @@ -590,10 +591,22 @@ impl<'a> Resolver<'a> { // Define a constructor name in the value namespace. // Braced variants, unlike structs, generate unusable names in // value namespace, they are reserved for possible future use. - let ctor_kind = CtorKind::from_ast(&variant.node.data); - let ctor_def = Def::VariantCtor(def_id, ctor_kind); + if let Some(ctor_node_id) = variant.node.data.ctor_id() { + let ctor_def_id = self.definitions.local_def_id(ctor_node_id); + let ctor_kind = CtorKind::from_ast(&variant.node.data); + let ctor_def = Def::Ctor(hir::CtorOf::Variant, ctor_def_id, ctor_kind); - self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion)); + self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion)); + } else { + // We normally don't have a `Def::Ctor(hir::CtorOf::Variant, ..)` for + // `Struct`-variants, but we must define one for name resolution to succeed. This also + // takes place in `build_reduced_graph_for_external_crate_def`. + let def_id = self.definitions.local_def_id(variant.node.id); + let ctor_kind = CtorKind::from_ast(&variant.node.data); + let ctor_def = Def::Ctor(hir::CtorOf::Variant, def_id, ctor_kind); + + self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion)); + } } /// Constructs the reduced graph for one foreign item. @@ -645,14 +658,29 @@ impl<'a> Resolver<'a> { span); self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); } - Def::Variant(..) | Def::TyAlias(..) | Def::ForeignTy(..) | Def::Existential(..) | - Def::TraitAlias(..) | Def::PrimTy(..) | Def::ToolMod => { + Def::Variant(def_id) => { + self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion)); + + if hir::def::CtorKind::Fictive == self.cstore.ctor_kind_untracked(def_id) { + // We do not normally generate `Def::Ctor(hir::CtorOf::Variant, ..)` for + // `Struct`-variants. Therefore, `build_reduced_graph_for_external_crate_def` + // will not be called to define one. However, name resolution currently expects + // there to be one, so we generate one here. This is easy to solve for local + // code, see `build_reduced_graph_for_variant` for this case. + let ctor_def = Def::Ctor(hir::CtorOf::Variant, def_id, + hir::def::CtorKind::Fictive); + + let _ = self.try_define( + parent, ident, ValueNS, + (ctor_def, vis, DUMMY_SP, expansion).to_name_binding(self.arenas), + ); + } + } + Def::TyAlias(..) | Def::ForeignTy(..) | Def::Existential(..) | Def::TraitAlias(..) | + Def::PrimTy(..) | Def::ToolMod => { self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion)); } - Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => { - self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); - } - Def::StructCtor(def_id, ..) => { + Def::Ctor(hir::CtorOf::Struct, def_id, ..) => { self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); if let Some(struct_def_id) = @@ -661,6 +689,15 @@ impl<'a> Resolver<'a> { self.struct_constructors.insert(struct_def_id, (def, vis)); } } + Def::Ctor(hir::CtorOf::Variant, ..) => { + let _ = self.try_define( + parent, ident, ValueNS, + (def, vis, DUMMY_SP, expansion).to_name_binding(self.arenas), + ); + } + Def::Fn(..) | Def::Static(..) | Def::Const(..) => { + self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); + } Def::Trait(def_id) => { let module_kind = ModuleKind::Def(def, ident.name); let module = self.new_module(parent, diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index 828ffc6d320..6426ca12c6c 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -2,7 +2,7 @@ use std::cmp::Reverse; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use log::debug; -use rustc::hir::def::*; +use rustc::hir::{self, def::*}; use rustc::hir::def::Namespace::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::session::config::nightly_options; @@ -417,7 +417,7 @@ impl<'a> Resolver<'a> { } (Def::Union(..), _) | (Def::Variant(..), _) | - (Def::VariantCtor(_, CtorKind::Fictive), _) if ns == ValueNS => { + (Def::Ctor(hir::CtorOf::Variant, _, CtorKind::Fictive), _) if ns == ValueNS => { err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?", path_str)); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 38ca5f0b664..e421a9edf89 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -571,24 +571,20 @@ impl<'a> PathSource<'a> { _ => false, }, PathSource::Expr(..) => match def { - Def::StructCtor(_, CtorKind::Const) | Def::StructCtor(_, CtorKind::Fn) | - Def::VariantCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Fn) | + Def::Ctor(_, _, CtorKind::Const) | Def::Ctor(_, _, CtorKind::Fn) | Def::Const(..) | Def::Static(..) | Def::Local(..) | Def::Upvar(..) | Def::Fn(..) | Def::Method(..) | Def::AssociatedConst(..) | Def::SelfCtor(..) | Def::ConstParam(..) => true, _ => false, }, PathSource::Pat => match def { - Def::StructCtor(_, CtorKind::Const) | - Def::VariantCtor(_, CtorKind::Const) | + Def::Ctor(_, _, CtorKind::Const) | Def::Const(..) | Def::AssociatedConst(..) | Def::SelfCtor(..) => true, _ => false, }, PathSource::TupleStruct => match def { - Def::StructCtor(_, CtorKind::Fn) | - Def::VariantCtor(_, CtorKind::Fn) | - Def::SelfCtor(..) => true, + Def::Ctor(_, _, CtorKind::Fn) | Def::SelfCtor(..) => true, _ => false, }, PathSource::Struct => match def { @@ -1364,7 +1360,7 @@ impl<'a> NameBinding<'a> { fn is_variant(&self) -> bool { match self.kind { NameBindingKind::Def(Def::Variant(..), _) | - NameBindingKind::Def(Def::VariantCtor(..), _) => true, + NameBindingKind::Def(Def::Ctor(hir::CtorOf::Variant, ..), _) => true, _ => false, } } @@ -3089,16 +3085,14 @@ impl<'a> Resolver<'a> { let is_syntactic_ambiguity = opt_pat.is_none() && bmode == BindingMode::ByValue(Mutability::Immutable); match def { - Def::StructCtor(_, CtorKind::Const) | - Def::VariantCtor(_, CtorKind::Const) | + Def::Ctor(_, _, CtorKind::Const) | Def::Const(..) if is_syntactic_ambiguity => { // Disambiguate in favor of a unit struct/variant // or constant pattern. self.record_use(ident, ValueNS, binding.unwrap(), false); Some(PathResolution::new(def)) } - Def::StructCtor(..) | Def::VariantCtor(..) | - Def::Const(..) | Def::Static(..) => { + Def::Ctor(..) | Def::Const(..) | Def::Static(..) => { // This is unambiguously a fresh binding, either syntactically // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves // to something unusable as a pattern (e.g., constructor function), @@ -4458,8 +4452,7 @@ impl<'a> Resolver<'a> { // outside crate private modules => no need to check this) if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { let did = match def { - Def::StructCtor(did, _) | Def::VariantCtor(did, _) => - self.parent(did), + Def::Ctor(_, did, _) => self.parent(did), _ => def.opt_def_id(), }; candidates.push(ImportSuggestion { did, path }); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 9daffd522bf..77fe57910cb 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -880,10 +880,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { Ok(binding) => { let imported_binding = this.import(binding, directive); target_bindings[ns].set(Some(imported_binding)); - let conflict = this.try_define(parent, target, ns, imported_binding); - if let Err(old_binding) = conflict { - this.report_conflict(parent, target, ns, imported_binding, old_binding); - } + this.define(parent, target, ns, imported_binding); } } }); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 76fd8b22f74..263f5acb662 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -488,8 +488,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { }; let (value, fields) = match item.node { - ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, ..), _) | - ast::ItemKind::Union(ast::VariantData::Struct(ref fields, ..), _) => { + ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, ..), ..) | + ast::ItemKind::Union(ast::VariantData::Struct(ref fields, ..), ..) => { let include_priv_fields = !self.save_ctxt.config.pub_only; let fields_str = fields .iter() @@ -581,7 +581,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str); if !self.span.filter_generated(name_span) { let span = self.span_from_span(name_span); - let id = id_from_node_id(variant.node.data.id(), &self.save_ctxt); + let id = id_from_node_id(variant.node.id, &self.save_ctxt); let parent = Some(id_from_node_id(item.id, &self.save_ctxt)); self.dumper.dump_def( @@ -619,7 +619,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } if !self.span.filter_generated(name_span) { let span = self.span_from_span(name_span); - let id = id_from_node_id(variant.node.data.id(), &self.save_ctxt); + let id = id_from_node_id(variant.node.id, &self.save_ctxt); let parent = Some(id_from_node_id(item.id, &self.save_ctxt)); self.dumper.dump_def( @@ -648,7 +648,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { for field in variant.node.data.fields() { - self.process_struct_field_def(field, variant.node.data.id()); + self.process_struct_field_def(field, variant.node.id); self.visit_ty(&field.ty); } } @@ -957,8 +957,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ); } } - HirDef::StructCtor(..) | - HirDef::VariantCtor(..) | + HirDef::Ctor(_, _, _) | HirDef::Const(..) | HirDef::AssociatedConst(..) | HirDef::Struct(..) | diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 7ad5b7ce8c7..de9a4b92c82 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -298,7 +298,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { parent: None, children: def.variants .iter() - .map(|v| id_from_node_id(v.node.data.id(), self)) + .map(|v| id_from_node_id(v.node.id, self)) .collect(), decl_id: None, docs: self.docs_for_attrs(&item.attrs), @@ -725,16 +725,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ref_id: id_from_node_id(id, self), }) } - HirDef::Static(..) | - HirDef::Const(..) | - HirDef::AssociatedConst(..) | - HirDef::VariantCtor(..) => { - Some(Ref { - kind: RefKind::Variable, - span, - ref_id: id_from_def_id(def.def_id()), - }) - } HirDef::Trait(def_id) if fn_type(path_seg) => { Some(Ref { kind: RefKind::Type, @@ -767,7 +757,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ref_id: id_from_def_id(def_id), }) } - HirDef::StructCtor(def_id, _) => { + HirDef::Ctor(hir::CtorOf::Struct, def_id, _) => { // This is a reference to a tuple struct where the def_id points // to an invisible constructor function. That is not a very useful // def, so adjust to point to the tuple struct itself. @@ -778,6 +768,16 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ref_id: id_from_def_id(parent_def_id), }) } + HirDef::Static(..) | + HirDef::Const(..) | + HirDef::AssociatedConst(..) | + HirDef::Ctor(..) => { + Some(Ref { + kind: RefKind::Variable, + span, + ref_id: id_from_def_id(def.def_id()), + }) + } HirDef::Method(decl_id) => { let def_id = if decl_id.is_local() { let ti = self.tcx.associated_item(decl_id); diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 6e47ae6b159..76034f32c74 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -586,7 +586,7 @@ impl Sig for ast::Path { refs: vec![], }) } - Def::AssociatedConst(..) | Def::Variant(..) | Def::VariantCtor(..) => { + Def::AssociatedConst(..) | Def::Variant(..) | Def::Ctor(..) => { let len = self.segments.len(); if len < 2 { return Err("Bad path"); @@ -700,10 +700,11 @@ impl Sig for ast::StructField { impl Sig for ast::Variant_ { - fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext<'_, '_>) -> Result { + fn make(&self, offset: usize, parent_id: Option, scx: &SaveContext<'_, '_>) -> Result { let mut text = self.ident.to_string(); match self.data { - ast::VariantData::Struct(ref fields, id, r) => { + ast::VariantData::Struct(ref fields, r) => { + let id = parent_id.unwrap(); let name_def = SigElement { id: id_from_node_id(id, scx), start: offset, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index e470748e344..ad62d2160b1 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1318,10 +1318,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did) }); if let Some(variant_def) = variant_def { - let def = Def::Variant(variant_def.did); + let did = variant_def.variant_did(); + let def = Def::Variant(did); if permit_variants { check_type_alias_enum_variants_enabled(tcx, span); - tcx.check_stability(variant_def.did, Some(hir_ref_id), span); + tcx.check_stability(did, Some(hir_ref_id), span); return (qself_ty, def); } else { variant_resolution = Some(def); @@ -1596,7 +1597,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { match def { // Case 1. Reference to a struct constructor. - Def::StructCtor(def_id, ..) | + Def::Ctor(hir::CtorOf::Struct, def_id, ..) | Def::SelfCtor(.., def_id) => { // Everything but the final segment should have no // parameters at all. @@ -1608,8 +1609,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } // Case 2. Reference to a variant constructor. - Def::Variant(def_id) | - Def::VariantCtor(def_id, ..) => { + Def::Ctor(hir::CtorOf::Variant, def_id, ..) | Def::Variant(def_id, ..) => { let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap()); let (generics_def_id, index) = if let Some(adt_def) = adt_def { debug_assert!(adt_def.is_enum()); @@ -1617,6 +1617,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } else if last >= 1 && segments[last - 1].args.is_some() { // Everything but the penultimate segment should have no // parameters at all. + let mut def_id = def_id; + + // `Def::Ctor` -> `Def::Variant` + if let Def::Ctor(..) = def { + def_id = tcx.parent(def_id).unwrap() + } + + // `Def::Variant` -> `Def::Item` (enum) let enum_def_id = tcx.parent(def_id).unwrap(); (enum_def_id, last - 1) } else { diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index c30b9d65fec..6d441521a9e 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -807,15 +807,13 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); report_unexpected_variant_def(tcx, &def, pat.span, qpath); return tcx.types.err; } - Def::VariantCtor(_, CtorKind::Fictive) | - Def::VariantCtor(_, CtorKind::Fn) => { + Def::Ctor(hir::CtorOf::Variant, _, CtorKind::Fictive) | + Def::Ctor(hir::CtorOf::Variant, _, CtorKind::Fn) => { report_unexpected_variant_def(tcx, &def, pat.span, qpath); return tcx.types.err; } - Def::VariantCtor(_, CtorKind::Const) | - Def::StructCtor(_, CtorKind::Const) | - Def::SelfCtor(..) | - Def::Const(..) | Def::AssociatedConst(..) => {} // OK + Def::Ctor(_, _, CtorKind::Const) | Def::SelfCtor(..) | Def::Const(..) | + Def::AssociatedConst(..) => {} // OK _ => bug!("unexpected pattern definition: {:?}", def) } @@ -876,8 +874,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); report_unexpected_def(def); return tcx.types.err; } - Def::VariantCtor(_, CtorKind::Fn) | - Def::StructCtor(_, CtorKind::Fn) => { + Def::Ctor(_, _, CtorKind::Fn) => { tcx.expect_variant_def(def) } _ => bug!("unexpected pattern definition: {:?}", def) @@ -950,7 +947,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); let mut inexistent_fields = vec![]; // Typecheck each field. for &Spanned { node: ref field, span } in fields { - let ident = tcx.adjust_ident(field.ident, variant.did, self.body_id).0; + let ident = tcx.adjust_ident( + field.ident, variant.variant_did_or_parent_struct_did(), self.body_id).0; let field_ty = match used_fields.entry(ident) { Occupied(occupied) => { struct_span_err!(tcx.sess, span, E0025, @@ -998,18 +996,19 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); .join(", ")), "these", "s") }; let spans = inexistent_fields.iter().map(|(span, _)| *span).collect::>(); + let did = variant.variant_did_or_parent_struct_did(); let mut err = struct_span_err!(tcx.sess, spans, E0026, "{} `{}` does not have {}", kind_name, - tcx.def_path_str(variant.did), + tcx.def_path_str(did), field_names); if let Some((span, ident)) = inexistent_fields.last() { err.span_label(*span, format!("{} `{}` does not have {} field{}", kind_name, - tcx.def_path_str(variant.did), + tcx.def_path_str(did), t, plural)); if plural == "" { diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 3a7308d0917..5d10f531ced 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -130,7 +130,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let sole_field = &variant.fields[0]; let sole_field_ty = sole_field.ty(self.tcx, substs); if self.can_coerce(expr_ty, sole_field_ty) { - let variant_path = self.tcx.def_path_str(variant.did); + let variant_path = self.tcx.def_path_str(variant.variant_did()); // FIXME #56861: DRYer prelude filtering Some(variant_path.trim_start_matches("std::prelude::v1::").to_string()) } else { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 5e3ebcb3446..f860ab649f9 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -417,7 +417,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(variant_def) = variant_def { check_type_alias_enum_variants_enabled(tcx, span); - let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind); + let def = if let Some(ctor_did) = variant_def.ctor_did() { + Def::Ctor(hir::CtorOf::Variant, ctor_did, variant_def.ctor_kind) + } else { + // Normally, there do not exist any `Def::Ctor` for `Struct`-variants but + // in this case, we can get better error messages as diagnostics will + // specialize the message around a `CtorKind::Fictive`. + Def::Ctor(hir::CtorOf::Variant, variant_def.variant_did(), + hir::def::CtorKind::Fictive) + }; + tcx.check_stability(def.def_id(), Some(expr_id), span); return Ok(def); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1054619f0f8..fe17f247916 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1863,7 +1863,7 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for ((_, discr), v) in def.discriminants(tcx).zip(vs) { // Check for duplicate discriminant values if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) { - let variant_did = def.variants[VariantIdx::new(i)].did; + let variant_did = def.variants[VariantIdx::new(i)].variant_did(); let variant_i_hir_id = tcx.hir().as_local_hir_id(variant_did).unwrap(); let variant_i = tcx.hir().expect_variant(variant_i_hir_id); let i_span = match variant_i.node.disr_expr { @@ -3693,7 +3693,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let names = variant.fields.iter().filter_map(|field| { // ignore already set fields and private fields from non-local crates if skip.iter().any(|x| *x == field.ident.as_str()) || - (variant.did.krate != LOCAL_CRATE && field.vis != Visibility::Public) { + (!variant.is_local() && field.vis != Visibility::Public) + { None } else { Some(&field.ident.name) @@ -3705,7 +3706,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec { variant.fields.iter().filter(|field| { - let def_scope = self.tcx.adjust_ident(field.ident, variant.did, self.body_id).1; + let did = variant.variant_did_or_parent_struct_did(); + let def_scope = self.tcx.adjust_ident(field.ident, did, self.body_id).1; field.vis.is_accessible_from(def_scope, self.tcx) }) .map(|field| field.ident.name) @@ -3823,7 +3825,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Type-check each field. for field in ast_fields { - let ident = tcx.adjust_ident(field.ident, variant.did, self.body_id).0; + let ident = tcx.adjust_ident( + field.ident, variant.variant_did_or_parent_struct_did(), self.body_id).0; let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) { seen_fields.insert(ident, field.span); self.write_field_index(field.hir_id, i); @@ -4237,7 +4240,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.set_tainted_by_errors(); tcx.types.err } - Def::VariantCtor(_, CtorKind::Fictive) => { + Def::Ctor(hir::CtorOf::Variant, _, CtorKind::Fictive) => { report_unexpected_variant_def(tcx, &def, expr.span, qpath); tcx.types.err } @@ -5343,8 +5346,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match adt_def { Some(adt_def) if adt_def.has_ctor() => { let variant = adt_def.non_enum_variant(); - let def = Def::StructCtor(variant.did, variant.ctor_kind); - (def, variant.did, tcx.type_of(variant.did)) + let ctor_did = variant.ctor_did().unwrap(); + let def = Def::Ctor(hir::CtorOf::Struct, ctor_did, variant.ctor_kind); + (def, ctor_did, tcx.type_of(ctor_did)) } _ => { let mut err = tcx.sess.struct_span_err(span, @@ -5416,7 +5420,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut user_self_ty = None; let mut is_alias_variant_ctor = false; match def { - Def::VariantCtor(_, _) => { + Def::Ctor(hir::CtorOf::Variant, _, _) => { if let Some(self_ty) = self_ty { let adt_def = self_ty.ty_adt_def().unwrap(); user_self_ty = Some(UserSelfTy { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index c0739db3df6..56129479f77 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -446,8 +446,8 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: hir::HirId) { tcx.predicates_of(def_id); } - if !struct_def.is_struct() { - convert_variant_ctor(tcx, struct_def.hir_id()); + if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { + convert_variant_ctor(tcx, ctor_hir_id); } } @@ -556,21 +556,24 @@ fn convert_enum_variant_types<'a, 'tcx>( // Convert the ctor, if any. This also registers the variant as // an item. - convert_variant_ctor(tcx, variant.node.data.hir_id()); + if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() { + convert_variant_ctor(tcx, ctor_hir_id); + } } } fn convert_variant<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - did: DefId, + variant_did: Option, + ctor_did: Option, ident: Ident, discr: ty::VariantDiscr, def: &hir::VariantData, adt_kind: ty::AdtKind, - attribute_def_id: DefId + parent_did: DefId ) -> ty::VariantDef { let mut seen_fields: FxHashMap = Default::default(); - let hir_id = tcx.hir().as_local_hir_id(did).unwrap(); + let hir_id = tcx.hir().as_local_hir_id(variant_did.unwrap_or(parent_did)).unwrap(); let fields = def .fields() .iter() @@ -599,17 +602,19 @@ fn convert_variant<'a, 'tcx>( }) .collect(); let recovered = match def { - hir::VariantData::Struct(_, _, r) => *r, + hir::VariantData::Struct(_, r) => *r, _ => false, }; - ty::VariantDef::new(tcx, - did, + ty::VariantDef::new( + tcx, ident, + variant_did, + ctor_did, discr, fields, - adt_kind, CtorKind::from_hir(def), - attribute_def_id, + adt_kind, + parent_did, recovered, ) } @@ -627,58 +632,52 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad let (kind, variants) = match item.node { ItemKind::Enum(ref def, _) => { let mut distance_from_explicit = 0; - ( - AdtKind::Enum, - def.variants - .iter() - .map(|v| { - let did = tcx.hir().local_def_id_from_hir_id(v.node.data.hir_id()); - let discr = if let Some(ref e) = v.node.disr_expr { - distance_from_explicit = 0; - ty::VariantDiscr::Explicit(tcx.hir().local_def_id_from_hir_id(e.hir_id)) - } else { - ty::VariantDiscr::Relative(distance_from_explicit) - }; - distance_from_explicit += 1; + let variants = def.variants + .iter() + .map(|v| { + let variant_did = Some(tcx.hir().local_def_id_from_hir_id(v.node.id)); + let ctor_did = v.node.data.ctor_hir_id() + .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id)); - convert_variant(tcx, did, v.node.ident, discr, &v.node.data, AdtKind::Enum, - did) - }) - .collect(), - ) + let discr = if let Some(ref e) = v.node.disr_expr { + distance_from_explicit = 0; + ty::VariantDiscr::Explicit(tcx.hir().local_def_id_from_hir_id(e.hir_id)) + } else { + ty::VariantDiscr::Relative(distance_from_explicit) + }; + distance_from_explicit += 1; + + convert_variant(tcx, variant_did, ctor_did, v.node.ident, discr, + &v.node.data, AdtKind::Enum, def_id) + }) + .collect(); + + (AdtKind::Enum, variants) } ItemKind::Struct(ref def, _) => { - // Use separate constructor id for unit/tuple structs and reuse did for braced structs. - let ctor_id = if !def.is_struct() { - Some(tcx.hir().local_def_id_from_hir_id(def.hir_id())) - } else { - None - }; - ( - AdtKind::Struct, - std::iter::once(convert_variant( - tcx, - ctor_id.unwrap_or(def_id), - item.ident, - ty::VariantDiscr::Relative(0), - def, - AdtKind::Struct, - def_id - )).collect(), - ) + let variant_did = None; + let ctor_did = def.ctor_hir_id() + .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id)); + + let variants = std::iter::once(convert_variant( + tcx, variant_did, ctor_did, item.ident, ty::VariantDiscr::Relative(0), def, + AdtKind::Struct, def_id, + )).collect(); + + (AdtKind::Struct, variants) } - ItemKind::Union(ref def, _) => ( - AdtKind::Union, - std::iter::once(convert_variant( - tcx, - def_id, - item.ident, - ty::VariantDiscr::Relative(0), - def, - AdtKind::Union, - def_id - )).collect(), - ), + ItemKind::Union(ref def, _) => { + let variant_did = None; + let ctor_did = def.ctor_hir_id() + .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id)); + + let variants = std::iter::once(convert_variant( + tcx, variant_did, ctor_did, item.ident, ty::VariantDiscr::Relative(0), def, + AdtKind::Union, def_id, + )).collect(); + + (AdtKind::Union, variants) + }, _ => bug!(), }; tcx.alloc_adt_def(def_id, kind, variants, repr) @@ -889,8 +888,8 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty let node = tcx.hir().get_by_hir_id(hir_id); let parent_def_id = match node { - Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_) - | Node::StructCtor(_) | Node::Field(_) => { + Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_) | + Node::Ctor(..) | Node::Field(_) => { let parent_id = tcx.hir().get_parent_item(hir_id); Some(tcx.hir().local_def_id_from_hir_id(parent_id)) } @@ -1248,8 +1247,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { ForeignItemKind::Type => tcx.mk_foreign(def_id), }, - Node::StructCtor(&ref def) - | Node::Variant(&Spanned { + Node::Ctor(_, &ref def) | Node::Variant(&Spanned { node: hir::VariantKind { data: ref def, .. }, .. }) => match *def { @@ -1627,17 +1625,12 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::PolyFnSig compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) } - StructCtor(&VariantData::Tuple(ref fields, ..)) - | Variant(&Spanned { - node: - hir::VariantKind { - data: VariantData::Tuple(ref fields, ..), - .. - }, + Ctor(_, data) | Variant(Spanned { + node: hir::VariantKind { data, .. }, .. - }) => { + }) if data.ctor_hir_id().is_some() => { let ty = tcx.type_of(tcx.hir().get_parent_did_by_hir_id(hir_id)); - let inputs = fields + let inputs = data.fields() .iter() .map(|f| tcx.type_of(tcx.hir().local_def_id_from_hir_id(f.hir_id))); ty::Binder::bind(tcx.mk_fn_sig( diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 20eae5d8835..f2406bd8540 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -75,7 +75,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { self.visit_node_helper(item.hir_id); if let hir::VariantData::Tuple(..) = *struct_def { - self.visit_node_helper(struct_def.hir_id()); + self.visit_node_helper(struct_def.ctor_hir_id().unwrap()); } } @@ -84,7 +84,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { for variant in &enum_def.variants { if let hir::VariantData::Tuple(..) = variant.node.data { - self.visit_node_helper(variant.node.data.hir_id()); + self.visit_node_helper(variant.node.data.ctor_hir_id().unwrap()); } } } diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index c2f79207a56..9b9a6bace96 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -79,7 +79,7 @@ fn variances_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) _ => unsupported() }, - Node::Variant(_) | Node::StructCtor(_) => {} + Node::Variant(_) | Node::Ctor(..) => {} _ => unsupported() } diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index 50c8d5adfa3..ac686e40076 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -136,7 +136,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { self.add_inferreds_for_item(item.hir_id); if let hir::VariantData::Tuple(..) = *struct_def { - self.add_inferreds_for_item(struct_def.hir_id()); + self.add_inferreds_for_item(struct_def.ctor_hir_id().unwrap()); } } @@ -145,7 +145,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { for variant in &enum_def.variants { if let hir::VariantData::Tuple(..) = variant.node.data { - self.add_inferreds_for_item(variant.node.data.hir_id()); + self.add_inferreds_for_item(variant.node.data.ctor_hir_id().unwrap()); } } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 880f67281b9..5969aa758df 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -88,9 +88,7 @@ pub fn try_inline( Def::Variant(..) => return None, // Assume that enum variants and struct types are re-exported next to // their constructors. - Def::VariantCtor(..) | - Def::StructCtor(..) | - Def::SelfCtor(..) => return Some(Vec::new()), + Def::Ctor(..) | Def::SelfCtor(..) => return Some(Vec::new()), Def::Mod(did) => { record_extern_fqn(cx, did, clean::TypeKind::Module); clean::ModuleItem(build_module(cx, did, visited)) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ba4481733d5..3ebca05f7dd 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3133,7 +3133,7 @@ impl Clean for doctree::Variant { visibility: None, stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), - def_id: cx.tcx.hir().local_def_id_from_hir_id(self.def.hir_id()), + def_id: cx.tcx.hir().local_def_id_from_hir_id(self.id), inner: VariantItem(Variant { kind: self.def.clean(cx), }), @@ -3169,15 +3169,16 @@ impl<'tcx> Clean for ty::VariantDef { }) } }; + let did = self.variant_did_or_parent_struct_did(); Item { name: Some(self.ident.clean(cx)), - attrs: inline::load_attrs(cx, self.did), - source: cx.tcx.def_span(self.did).clean(cx), + attrs: inline::load_attrs(cx, did), + source: cx.tcx.def_span(did).clean(cx), visibility: Some(Inherited), - def_id: self.did, + def_id: did, inner: VariantItem(Variant { kind }), - stability: get_stability(cx, self.did), - deprecation: get_deprecation(cx, self.did), + stability: get_stability(cx, did), + deprecation: get_deprecation(cx, did), } } } diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 9c54b40b422..7a528e50e9c 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -125,6 +125,7 @@ pub struct Enum { pub struct Variant { pub name: Name, + pub id: hir::HirId, pub attrs: hir::HirVec, pub def: hir::VariantData, pub stab: Option, diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 7c1a61449a2..ee182237b49 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -344,9 +344,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { .and_then(|(def, fragment)| { // Constructors are picked up in the type namespace. match def { - Def::StructCtor(..) - | Def::VariantCtor(..) - | Def::SelfCtor(..) => None, + Def::Ctor(..) | Def::SelfCtor(..) => None, _ => Some((def, fragment)) } }), diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index b4db121fb53..a7e2b2155e9 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -141,9 +141,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { name, variants: def.variants.iter().map(|v| Variant { name: v.node.ident.name, + id: v.node.id, attrs: v.node.attrs.clone(), - stab: self.stability(v.node.data.hir_id()), - depr: self.deprecation(v.node.data.hir_id()), + stab: self.stability(v.node.id), + depr: self.deprecation(v.node.id), def: v.node.data.clone(), whence: v.span, }).collect(), @@ -420,8 +421,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // Struct and variant constructors and proc macro stubs always show up alongside // their definitions, we've already processed them so just discard these. match path.def { - Def::StructCtor(..) | Def::VariantCtor(..) | Def::SelfCtor(..) | - Def::Macro(_, MacroKind::ProcMacroStub) => return, + Def::Ctor(..) | Def::SelfCtor(..) | Def::Macro(_, MacroKind::ProcMacroStub) => + return, _ => {} } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2cbd2dfeb25..c64ffb1232f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1956,8 +1956,13 @@ pub struct EnumDef { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Variant_ { + /// Name of the variant. pub ident: Ident, + /// Attributes of the variant. pub attrs: Vec, + /// Id of the variant (not the constructor, see `VariantData::ctor_id()`). + pub id: NodeId, + /// Fields and constructor id of the variant. pub data: VariantData, /// Explicit discriminant, e.g., `Foo = 1`. pub disr_expr: Option, @@ -2117,23 +2122,13 @@ pub struct StructField { pub attrs: Vec, } -/// Fields and Ids of enum variants and structs -/// -/// For enum variants: `NodeId` represents both an Id of the variant itself (relevant for all -/// variant kinds) and an Id of the variant's constructor (not relevant for `Struct`-variants). -/// One shared Id can be successfully used for these two purposes. -/// Id of the whole enum lives in `Item`. -/// -/// For structs: `NodeId` represents an Id of the structure's constructor, so it is not actually -/// used for `Struct`-structs (but still presents). Structures don't have an analogue of "Id of -/// the variant itself" from enum variants. -/// Id of the whole struct lives in `Item`. +/// Fields and constructor ids of enum variants and structs. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum VariantData { /// Struct variant. /// /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`. - Struct(Vec, NodeId, bool), + Struct(Vec, bool), /// Tuple variant. /// /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`. @@ -2145,17 +2140,23 @@ pub enum VariantData { } impl VariantData { + /// Return the fields of this variant. pub fn fields(&self) -> &[StructField] { match *self { VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, _) => fields, _ => &[], } } - pub fn id(&self) -> NodeId { + + /// Return the `NodeId` of this variant's constructor, if it has one. + pub fn ctor_id(&self) -> Option { match *self { - VariantData::Struct(_, id, _) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id, + VariantData::Struct(..) => None, + VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id), } } + + /// Does this `VariantData` represent a `Struct`-struct/variant? pub fn is_struct(&self) -> bool { if let VariantData::Struct(..) = *self { true @@ -2163,6 +2164,8 @@ impl VariantData { false } } + + /// Does this `VariantData` represent a tuple struct/variant? pub fn is_tuple(&self) -> bool { if let VariantData::Tuple(..) = *self { true @@ -2170,6 +2173,8 @@ impl VariantData { false } } + + /// Does this `VariantData` represent a unit struct/variant? pub fn is_unit(&self) -> bool { if let VariantData::Unit(..) = *self { true diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 7159c949513..18173628a26 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -225,10 +225,9 @@ impl<'a> StripUnconfigured<'a> { fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) { match vdata { - ast::VariantData::Struct(fields, _id, _) | - ast::VariantData::Tuple(fields, _id) => + ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) => fields.flat_map_in_place(|field| self.configure(field)), - ast::VariantData::Unit(_id) => {} + ast::VariantData::Unit(_) => {} } } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index e95f0589449..614967bdeb4 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -1062,6 +1062,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { respan(span, ast::Variant_ { ident, + id: ast::DUMMY_NODE_ID, attrs: Vec::new(), data: vdata, disr_expr: None, diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 5bb1d8a4b94..784d0049ac5 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -450,9 +450,10 @@ pub fn noop_visit_foreign_mod(foreign_mod: &mut ForeignMod, vis: } pub fn noop_visit_variant(variant: &mut Variant, vis: &mut T) { - let Spanned { node: Variant_ { ident, attrs, data, disr_expr }, span } = variant; + let Spanned { node: Variant_ { ident, attrs, id, data, disr_expr }, span } = variant; vis.visit_ident(ident); visit_attrs(attrs, vis); + vis.visit_id(id); vis.visit_variant_data(data); visit_opt(disr_expr, |disr_expr| vis.visit_anon_const(disr_expr)); vis.visit_span(span); @@ -765,11 +766,11 @@ pub fn noop_visit_where_predicate(pred: &mut WherePredicate, vis: pub fn noop_visit_variant_data(vdata: &mut VariantData, vis: &mut T) { match vdata { - VariantData::Struct(fields, id, _) | + VariantData::Struct(fields, ..) => visit_vec(fields, |field| vis.visit_struct_field(field)), VariantData::Tuple(fields, id) => { visit_vec(fields, |field| vis.visit_struct_field(field)); vis.visit_id(id); - } + }, VariantData::Unit(id) => vis.visit_id(id), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 99260314054..d7a2170342d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6844,7 +6844,7 @@ impl<'a> Parser<'a> { } else { // If we see: `struct Foo where T: Copy { ... }` let (fields, recovered) = self.parse_record_struct_body()?; - VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered) + VariantData::Struct(fields, recovered) } // No `where` so: `struct Foo;` } else if self.eat(&token::Semi) { @@ -6852,7 +6852,7 @@ impl<'a> Parser<'a> { // Record-style struct definition } else if self.token == token::OpenDelim(token::Brace) { let (fields, recovered) = self.parse_record_struct_body()?; - VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered) + VariantData::Struct(fields, recovered) // Tuple-style struct definition with optional where-clause. } else if self.token == token::OpenDelim(token::Paren) { let body = VariantData::Tuple(self.parse_tuple_struct_body()?, ast::DUMMY_NODE_ID); @@ -6881,10 +6881,10 @@ impl<'a> Parser<'a> { let vdata = if self.token.is_keyword(keywords::Where) { generics.where_clause = self.parse_where_clause()?; let (fields, recovered) = self.parse_record_struct_body()?; - VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered) + VariantData::Struct(fields, recovered) } else if self.token == token::OpenDelim(token::Brace) { let (fields, recovered) = self.parse_record_struct_body()?; - VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered) + VariantData::Struct(fields, recovered) } else { let token_str = self.this_token_descr(); let mut err = self.fatal(&format!( @@ -7708,7 +7708,7 @@ impl<'a> Parser<'a> { // Parse a struct variant. all_nullary = false; let (fields, recovered) = self.parse_record_struct_body()?; - struct_def = VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered); + struct_def = VariantData::Struct(fields, recovered); } else if self.check(&token::OpenDelim(token::Paren)) { all_nullary = false; struct_def = VariantData::Tuple( @@ -7730,6 +7730,7 @@ impl<'a> Parser<'a> { let vr = ast::Variant_ { ident, + id: ast::DUMMY_NODE_ID, attrs: variant_attrs, data: struct_def, disr_expr, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 07df14ddc72..946fdc0c469 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -3266,6 +3266,7 @@ mod tests { let var = source_map::respan(syntax_pos::DUMMY_SP, ast::Variant_ { ident, attrs: Vec::new(), + id: ast::DUMMY_NODE_ID, // making this up as I go.... ? data: ast::VariantData::Unit(ast::DUMMY_NODE_ID), disr_expr: None, diff --git a/src/test/mir-opt/unusual-item-types.rs b/src/test/mir-opt/unusual-item-types.rs index ef41373d774..29c97ed6d38 100644 --- a/src/test/mir-opt/unusual-item-types.rs +++ b/src/test/mir-opt/unusual-item-types.rs @@ -72,7 +72,7 @@ fn main() { // } // END rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir -// START rustc.Test-X.mir_map.0.mir +// START rustc.Test-X-{{variant constructor}}.mir_map.0.mir // fn Test::X(_1: usize) -> Test { // let mut _0: Test; // @@ -81,4 +81,4 @@ fn main() { // return; // } // } -// END rustc.Test-X.mir_map.0.mir +// END rustc.Test-X-{{variant constructor}}.mir_map.0.mir