From 5c3d1e5d76fdc6d9f40ab13a6a342e1f7ceb4f17 Mon Sep 17 00:00:00 2001 From: David Wood Date: Thu, 21 Mar 2019 23:38:50 +0100 Subject: [PATCH 1/9] Separate variant id and variant constructor id. This commit makes two changes - separating the `NodeId` that identifies an enum variant from the `NodeId` that identifies the variant's constructor; and no longer creating a `NodeId` for `Struct`-style enum variants and structs. Separation of the variant id and variant constructor id will allow the rest of RFC 2008 to be implemented by lowering the visibility of the variant's constructor without lowering the visbility of the variant itself. No longer creating a `NodeId` for `Struct`-style enum variants and structs mostly simplifies logic as previously this `NodeId` wasn't used. There were various cases where the `NodeId` wouldn't be used unless there was an unit or tuple struct or enum variant but not all uses of this `NodeId` had that condition, by removing this `NodeId`, this must be explicitly dealt with. This change mostly applied cleanly, but there were one or two cases in name resolution and one case in type check where the existing logic required a id for `Struct`-style enum variants and structs. --- src/librustc/hir/def.rs | 30 ++- src/librustc/hir/intravisit.rs | 5 +- src/librustc/hir/lowering.rs | 20 +- src/librustc/hir/map/collector.rs | 16 +- src/librustc/hir/map/def_collector.rs | 18 +- src/librustc/hir/map/definitions.rs | 8 +- src/librustc/hir/map/mod.rs | 35 +-- src/librustc/hir/mod.rs | 60 +++-- src/librustc/hir/pat_util.rs | 6 +- src/librustc/lint/context.rs | 6 +- src/librustc/lint/mod.rs | 2 +- src/librustc/middle/dead.rs | 39 ++- src/librustc/middle/expr_use_visitor.rs | 14 +- src/librustc/middle/mem_categorization.rs | 23 +- src/librustc/middle/reachable.rs | 2 +- src/librustc/middle/stability.rs | 17 +- src/librustc/mir/mod.rs | 3 +- src/librustc/traits/error_reporting.rs | 24 +- src/librustc/ty/instance.rs | 3 +- src/librustc/ty/mod.rs | 248 +++++++++++++----- src/librustc/ty/print/pretty.rs | 19 +- src/librustc_borrowck/borrowck/mod.rs | 3 +- src/librustc_lint/builtin.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 8 + src/librustc_metadata/decoder.rs | 68 ++--- src/librustc_metadata/encoder.rs | 102 +++++-- src/librustc_metadata/schema.rs | 9 +- src/librustc_mir/build/mod.rs | 5 +- src/librustc_mir/hair/cx/expr.rs | 26 +- src/librustc_mir/hair/pattern/_match.rs | 18 +- src/librustc_mir/hair/pattern/mod.rs | 14 +- src/librustc_mir/shim.rs | 2 +- src/librustc_mir/util/pretty.rs | 8 +- src/librustc_passes/rvalue_promotion.rs | 7 +- src/librustc_privacy/lib.rs | 17 +- src/librustc_resolve/build_reduced_graph.rs | 63 ++++- src/librustc_resolve/error_reporting.rs | 4 +- src/librustc_resolve/lib.rs | 21 +- src/librustc_resolve/resolve_imports.rs | 5 +- src/librustc_save_analysis/dump_visitor.rs | 13 +- src/librustc_save_analysis/lib.rs | 24 +- src/librustc_save_analysis/sig.rs | 7 +- src/librustc_typeck/astconv.rs | 18 +- src/librustc_typeck/check/_match.rs | 21 +- src/librustc_typeck/check/demand.rs | 2 +- src/librustc_typeck/check/method/mod.rs | 11 +- src/librustc_typeck/check/mod.rs | 20 +- src/librustc_typeck/collect.rs | 139 +++++----- src/librustc_typeck/variance/constraints.rs | 4 +- src/librustc_typeck/variance/mod.rs | 2 +- src/librustc_typeck/variance/terms.rs | 4 +- src/librustdoc/clean/inline.rs | 4 +- src/librustdoc/clean/mod.rs | 13 +- src/librustdoc/doctree.rs | 1 + .../passes/collect_intra_doc_links.rs | 4 +- src/librustdoc/visit_ast.rs | 9 +- src/libsyntax/ast.rs | 33 ++- src/libsyntax/config.rs | 5 +- src/libsyntax/ext/build.rs | 1 + src/libsyntax/mut_visit.rs | 7 +- src/libsyntax/parse/parser.rs | 11 +- src/libsyntax/print/pprust.rs | 1 + src/test/mir-opt/unusual-item-types.rs | 4 +- 63 files changed, 818 insertions(+), 520 deletions(-) diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index b45fc3ffd82fe..87a6065bb75ec 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 977830315e23e..bce528189ad1e 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 2251e67233c5f..8db90035c8e0c 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 e88f9e60702f7..e7cd8f113539a 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 12760f8b9828b..2c92d907201d5 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 dca4ce4aef817..dc23b55c1fcb3 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 3e8da882eed15..ce0246dec7182 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 823de08874e60..6ce7c347c9971 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 18a3d6708db64..b859a0f389ed5 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 9761ee313533f..94f1d9c271007 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 03ed62f2a0d66..e96fe3d3b7741 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 ccec4bd143269..786d339e876c5 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 8ada67efaafdd..a60a145dd2161 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 b36d2a57cb3b1..aa582d48bb660 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 a7294dbf07c00..b57f96f2d469d 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 72c90b258608d..772c6ab474543 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 9f2027e7d0563..b54b92b798ef7 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 f5f2ec38bdf27..ef232c06921df 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 995e85fc5f4db..84ce826c6a588 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 91b84b68802b1..0de91af846046 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_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.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_id(&self, vid: DefId) -> VariantIdx { + pub fn variant_index_with_ctor_or_variant_id(&self, id: DefId) -> VariantIdx { self.variants .iter_enumerated() - .find(|(_, v)| v.did == vid) - .expect("variant_index_with_id: unknown variant") + .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 7701a10d8eeee..3d6a2cf9224be 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 4e1d360562d9d..7e38ce6377c89 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 8153653e48b25..6d694dcfac7be 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 67a249e605ecc..995532a00cd6e 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 c608c03095aa3..c6f7b46d38339 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 ce0618d4599e7..1af59f314bc2b 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 afeea9947b5e3..5b6166ebeaf59 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 1138edcb3757e..0283352066cb8 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 b83f048114b06..eb50bd727db15 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 88d1eb2ee0be0..9637a111f42a0 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 8614be8d407b1..8349f21cdb47e 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 f1fbc80edfb4b..cb25db73cd2be 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 13bcdc26a5efb..5e5e451b75bf2 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 6de98675a3dc8..71eb6ed7e0517 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 19b5fa1bfbe57..96fdb6a438228 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 6fad4b2db9713..72197d4a17aa5 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::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => { - self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); + Def::TyAlias(..) | Def::ForeignTy(..) | Def::Existential(..) | Def::TraitAlias(..) | + Def::PrimTy(..) | Def::ToolMod => { + self.define(parent, ident, TypeNS, (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 828ffc6d320e7..6426ca12c6c92 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 38ca5f0b6640a..e421a9edf8927 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 9daffd522bf2c..77fe57910cb78 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 76fd8b22f7452..263f5acb662fc 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 7ad5b7ce8c73e..de9a4b92c820d 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 6e47ae6b15984..76034f32c741c 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 e470748e34434..ad62d2160b1eb 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 c30b9d65fec83..6d441521a9e98 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 3a7308d09172e..5d10f531ced4d 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 5e3ebcb3446c6..f860ab649f990 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 1054619f0f808..fe17f247916b6 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 c0739db3df6a2..56129479f7755 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)); + + 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, did, v.node.ident, discr, &v.node.data, AdtKind::Enum, - did) - }) - .collect(), - ) + 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(), - ) - } - 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(), - ), + 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, _) => { + 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 20eae5d88351b..f2406bd8540b5 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 c2f79207a5624..9b9a6bace96b1 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 50c8d5adfa370..ac686e40076eb 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 880f67281b967..5969aa758df2c 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 ba4481733d592..3ebca05f7dd85 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 9c54b40b422ae..7a528e50e9c3f 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 7c1a61449a26f..ee182237b49ec 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 b4db121fb530a..a7e2b2155e9f3 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 2cbd2dfeb25d6..c64ffb1232fba 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 7159c949513ac..18173628a2602 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 e95f05894491b..614967bdeb447 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 5bb1d8a4b9476..784d0049ac51f 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 9926031405416..d7a2170342d7f 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 07df14ddc722c..946fdc0c46942 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 ef41373d774e3..29c97ed6d3845 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 From c667c2fc0896b2a58a363d2c535881e5b983857a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 24 Mar 2019 00:06:58 +0300 Subject: [PATCH 2/9] Remove methods is_struct/is_tuple/is_unit from VariantData --- src/librustc/hir/mod.rs | 27 ------- src/librustc/hir/print.rs | 67 ++++++++-------- src/librustc_passes/ast_validation.rs | 2 +- src/librustdoc/clean/mod.rs | 11 ++- src/libsyntax/ast.rs | 27 ------- src/libsyntax/print/pprust.rs | 73 ++++++++--------- src/libsyntax_ext/deriving/debug.rs | 96 +++++++++++------------ src/libsyntax_ext/deriving/generic/mod.rs | 8 +- 8 files changed, 130 insertions(+), 181 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 6ce7c347c9971..7895919e15078 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2208,33 +2208,6 @@ impl VariantData { 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 - } else { - false - } - } - - /// Does this `VariantData` represent a tuple struct/variant? - pub fn is_tuple(&self) -> bool { - if let VariantData::Tuple(..) = *self { - true - } else { - false - } - } - - /// Does this `VariantData` represent a unit struct/variant? - pub fn is_unit(&self) -> bool { - if let VariantData::Unit(..) = *self { - true - } else { - false - } - } } // The bodies for items are stored "out of line", in a separate diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index bff4190ae7925..cdd4043f4bc21 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -860,41 +860,44 @@ impl<'a> State<'a> { -> io::Result<()> { self.print_name(name)?; self.print_generic_params(&generics.params)?; - if !struct_def.is_struct() { - if struct_def.is_tuple() { - self.popen()?; - self.commasep(Inconsistent, struct_def.fields(), |s, field| { - s.maybe_print_comment(field.span.lo())?; - s.print_outer_attributes(&field.attrs)?; - s.print_visibility(&field.vis)?; - s.print_type(&field.ty) - })?; - self.pclose()?; - } - self.print_where_clause(&generics.where_clause)?; - if print_finalizer { - self.s.word(";")?; + match struct_def { + hir::VariantData::Tuple(..) | hir::VariantData::Unit(..) => { + if let hir::VariantData::Tuple(..) = struct_def { + self.popen()?; + self.commasep(Inconsistent, struct_def.fields(), |s, field| { + s.maybe_print_comment(field.span.lo())?; + s.print_outer_attributes(&field.attrs)?; + s.print_visibility(&field.vis)?; + s.print_type(&field.ty) + })?; + self.pclose()?; + } + self.print_where_clause(&generics.where_clause)?; + if print_finalizer { + self.s.word(";")?; + } + self.end()?; + self.end() // close the outer-box } - self.end()?; - self.end() // close the outer-box - } else { - self.print_where_clause(&generics.where_clause)?; - self.nbsp()?; - self.bopen()?; - self.hardbreak_if_not_bol()?; - - for field in struct_def.fields() { + hir::VariantData::Struct(..) => { + self.print_where_clause(&generics.where_clause)?; + self.nbsp()?; + self.bopen()?; self.hardbreak_if_not_bol()?; - self.maybe_print_comment(field.span.lo())?; - self.print_outer_attributes(&field.attrs)?; - self.print_visibility(&field.vis)?; - self.print_ident(field.ident)?; - self.word_nbsp(":")?; - self.print_type(&field.ty)?; - self.s.word(",")?; - } - self.bclose(span) + for field in struct_def.fields() { + self.hardbreak_if_not_bol()?; + self.maybe_print_comment(field.span.lo())?; + self.print_outer_attributes(&field.attrs)?; + self.print_visibility(&field.vis)?; + self.print_ident(field.ident)?; + self.word_nbsp(":")?; + self.print_type(&field.ty)?; + self.s.word(",")?; + } + + self.bclose(span) + } } } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index b85429cd3cfdc..4e2aefe623167 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -661,7 +661,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } ItemKind::Union(ref vdata, _) => { - if !vdata.is_struct() { + if let VariantData::Tuple(..) | VariantData::Unit(..) = vdata { self.err_handler().span_err(item.span, "tuple and unit unions are not permitted"); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3ebca05f7dd85..ddd68c483790e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3192,12 +3192,11 @@ pub enum VariantKind { impl Clean for hir::VariantData { fn clean(&self, cx: &DocContext<'_>) -> VariantKind { - if self.is_struct() { - VariantKind::Struct(self.clean(cx)) - } else if self.is_unit() { - VariantKind::CLike - } else { - VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect()) + match self { + hir::VariantData::Struct(..) => VariantKind::Struct(self.clean(cx)), + hir::VariantData::Tuple(..) => + VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect()), + hir::VariantData::Unit(..) => VariantKind::CLike, } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index c64ffb1232fba..bcc8fdf8cd4e7 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2155,33 +2155,6 @@ impl VariantData { 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 - } else { - false - } - } - - /// Does this `VariantData` represent a tuple struct/variant? - pub fn is_tuple(&self) -> bool { - if let VariantData::Tuple(..) = *self { - true - } else { - false - } - } - - /// Does this `VariantData` represent a unit struct/variant? - pub fn is_unit(&self) -> bool { - if let VariantData::Unit(..) = *self { - true - } else { - false - } - } } /// An item. diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 946fdc0c46942..f5a9aded8455e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1550,44 +1550,47 @@ impl<'a> State<'a> { print_finalizer: bool) -> io::Result<()> { self.print_ident(ident)?; self.print_generic_params(&generics.params)?; - if !struct_def.is_struct() { - if struct_def.is_tuple() { - self.popen()?; - self.commasep( - Inconsistent, struct_def.fields(), - |s, field| { - s.maybe_print_comment(field.span.lo())?; - s.print_outer_attributes(&field.attrs)?; - s.print_visibility(&field.vis)?; - s.print_type(&field.ty) - } - )?; - self.pclose()?; - } - self.print_where_clause(&generics.where_clause)?; - if print_finalizer { - self.s.word(";")?; + match struct_def { + ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => { + if let ast::VariantData::Tuple(..) = struct_def { + self.popen()?; + self.commasep( + Inconsistent, struct_def.fields(), + |s, field| { + s.maybe_print_comment(field.span.lo())?; + s.print_outer_attributes(&field.attrs)?; + s.print_visibility(&field.vis)?; + s.print_type(&field.ty) + } + )?; + self.pclose()?; + } + self.print_where_clause(&generics.where_clause)?; + if print_finalizer { + self.s.word(";")?; + } + self.end()?; + self.end() // close the outer-box } - self.end()?; - self.end() // close the outer-box - } else { - self.print_where_clause(&generics.where_clause)?; - self.nbsp()?; - self.bopen()?; - self.hardbreak_if_not_bol()?; - - for field in struct_def.fields() { + ast::VariantData::Struct(..) => { + self.print_where_clause(&generics.where_clause)?; + self.nbsp()?; + self.bopen()?; self.hardbreak_if_not_bol()?; - self.maybe_print_comment(field.span.lo())?; - self.print_outer_attributes(&field.attrs)?; - self.print_visibility(&field.vis)?; - self.print_ident(field.ident.unwrap())?; - self.word_nbsp(":")?; - self.print_type(&field.ty)?; - self.s.word(",")?; - } - self.bclose(span) + for field in struct_def.fields() { + self.hardbreak_if_not_bol()?; + self.maybe_print_comment(field.span.lo())?; + self.print_outer_attributes(&field.attrs)?; + self.print_visibility(&field.vis)?; + self.print_ident(field.ident.unwrap())?; + self.word_nbsp(":")?; + self.print_type(&field.ty)?; + self.s.word(",")?; + } + + self.bclose(span) + } } } diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index 7dc2d007d73d6..7c47c6ff79ac1 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -51,9 +51,9 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> // build fmt.debug_struct().field(, &)....build() // or fmt.debug_tuple().field(&)....build() // based on the "shape". - let (ident, is_struct) = match *substr.fields { - Struct(vdata, _) => (substr.type_ident, vdata.is_struct()), - EnumMatching(_, _, v, _) => (v.node.ident, v.node.data.is_struct()), + let (ident, vdata, fields) = match substr.fields { + Struct(vdata, fields) => (substr.type_ident, *vdata, fields), + EnumMatching(_, _, v, fields) => (v.node.ident, &v.node.data, fields), EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"), @@ -67,55 +67,51 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_> let fmt = substr.nonself_args[0].clone(); - let mut stmts = match *substr.fields { - Struct(_, ref fields) | - EnumMatching(.., ref fields) => { - let mut stmts = vec![]; - if !is_struct { - // tuple struct/"normal" variant - let expr = - cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]); - stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr)); - - for field in fields { - // Use double indirection to make sure this works for unsized types - let field = cx.expr_addr_of(field.span, field.self_.clone()); - let field = cx.expr_addr_of(field.span, field); - - let expr = cx.expr_method_call(span, - builder_expr.clone(), - Ident::from_str("field"), - vec![field]); - - // Use `let _ = expr;` to avoid triggering the - // unused_results lint. - stmts.push(stmt_let_undescore(cx, span, expr)); - } - } else { - // normal struct/struct variant - let expr = - cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]); - stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr)); - - for field in fields { - let name = cx.expr_lit(field.span, - ast::LitKind::Str(field.name.unwrap().name, - ast::StrStyle::Cooked)); - - // Use double indirection to make sure this works for unsized types - let field = cx.expr_addr_of(field.span, field.self_.clone()); - let field = cx.expr_addr_of(field.span, field); - let expr = cx.expr_method_call(span, - builder_expr.clone(), - Ident::from_str("field"), - vec![name, field]); - stmts.push(stmt_let_undescore(cx, span, expr)); - } + let mut stmts = vec![]; + match vdata { + ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => { + // tuple struct/"normal" variant + let expr = + cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]); + stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr)); + + for field in fields { + // Use double indirection to make sure this works for unsized types + let field = cx.expr_addr_of(field.span, field.self_.clone()); + let field = cx.expr_addr_of(field.span, field); + + let expr = cx.expr_method_call(span, + builder_expr.clone(), + Ident::from_str("field"), + vec![field]); + + // Use `let _ = expr;` to avoid triggering the + // unused_results lint. + stmts.push(stmt_let_undescore(cx, span, expr)); } - stmts } - _ => unreachable!(), - }; + ast::VariantData::Struct(..) => { + // normal struct/struct variant + let expr = + cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]); + stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr)); + + for field in fields { + let name = cx.expr_lit(field.span, + ast::LitKind::Str(field.name.unwrap().name, + ast::StrStyle::Cooked)); + + // Use double indirection to make sure this works for unsized types + let field = cx.expr_addr_of(field.span, field.self_.clone()); + let field = cx.expr_addr_of(field.span, field); + let expr = cx.expr_method_call(span, + builder_expr.clone(), + Ident::from_str("field"), + vec![name, field]); + stmts.push(stmt_let_undescore(cx, span, expr)); + } + } + } let expr = cx.expr_method_call(span, builder_expr, Ident::from_str("finish"), vec![]); diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 2bb98c1bf625c..dc0d72a7830e6 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -1539,6 +1539,7 @@ impl<'a> TraitDef<'a> { } } + let is_tuple = if let ast::VariantData::Tuple(..) = struct_def { true } else { false }; match (just_spans.is_empty(), named_idents.is_empty()) { (false, false) => { cx.span_bug(self.span, @@ -1547,9 +1548,10 @@ impl<'a> TraitDef<'a> { } // named fields (_, false) => Named(named_idents), - // empty structs - _ if struct_def.is_struct() => Named(named_idents), - _ => Unnamed(just_spans, struct_def.is_tuple()), + // unnamed fields + (false, _) => Unnamed(just_spans, is_tuple), + // empty + _ => Named(Vec::new()), } } From 7f5a8dcdb95b07234d323cad8492bef96f2bee1b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 24 Mar 2019 12:09:44 +0300 Subject: [PATCH 3/9] Remove `VariantDef::parent_did` --- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/mir/mod.rs | 3 +- src/librustc/ty/inhabitedness/mod.rs | 29 +---- src/librustc/ty/mod.rs | 132 ++++----------------- src/librustc_metadata/encoder.rs | 21 ++-- src/librustc_mir/build/matches/simplify.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 2 +- src/librustc_mir/hair/pattern/_match.rs | 33 ++---- src/librustc_mir/hair/pattern/mod.rs | 2 +- src/librustc_typeck/astconv.rs | 5 +- src/librustc_typeck/check/_match.rs | 8 +- src/librustc_typeck/check/demand.rs | 2 +- src/librustc_typeck/check/method/mod.rs | 6 +- src/librustc_typeck/check/mod.rs | 16 ++- src/librustdoc/clean/mod.rs | 11 +- 15 files changed, 72 insertions(+), 202 deletions(-) diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index aa582d48bb660..fe6667a94b815 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_variant_id(variant_did) + adt_def.variant_with_id(variant_did) } _ => { assert_eq!(adt_def.variants.len(), 1); diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index b54b92b798ef7..d747f348ac990 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2405,13 +2405,12 @@ 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(did, substs)?; + .print_def_path(variant_def.def_id, substs)?; Ok(()) })?; diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index d732f3ff04086..963b4b439f84d 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -104,33 +104,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { fn ty_inhabitedness_forest(self, ty: Ty<'tcx>) -> DefIdForest { ty.uninhabited_from(self) } - - pub fn is_enum_variant_uninhabited_from(self, - module: DefId, - variant: &'tcx VariantDef, - substs: SubstsRef<'tcx>) - -> bool - { - self.variant_inhabitedness_forest(variant, substs).contains(self, module) - } - - pub fn is_variant_uninhabited_from_all_modules(self, - variant: &'tcx VariantDef, - substs: SubstsRef<'tcx>) - -> bool - { - !self.variant_inhabitedness_forest(variant, substs).is_empty() - } - - fn variant_inhabitedness_forest(self, variant: &'tcx VariantDef, substs: SubstsRef<'tcx>) - -> DefIdForest { - // Determine the ADT kind: - let adt_def_id = self.adt_def_id_of_variant(variant); - let adt_kind = self.adt_def(adt_def_id).adt_kind(); - - // Compute inhabitedness forest: - variant.uninhabited_from(self, substs, adt_kind) - } } impl<'a, 'gcx, 'tcx> AdtDef { @@ -148,7 +121,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { impl<'a, 'gcx, 'tcx> VariantDef { /// Calculate the forest of DefIds from which this variant is visibly uninhabited. - fn uninhabited_from( + pub fn uninhabited_from( &self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: SubstsRef<'tcx>, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 0de91af846046..10755a9c0218e 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1810,12 +1810,12 @@ bitflags! { /// Definition of a variant -- a struct's fields or a enum variant. #[derive(Debug)] pub struct VariantDef { - /// `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, + /// `DefId` that identifies the variant itself. + /// If this variant belongs to a struct or union, then this is a copy of its `DefId`. + pub def_id: DefId, + /// `DefId` that identifies the variant's constructor. + /// If this variant is a struct variant, then this is `None`. + pub ctor_def_id: Option, /// Variant or struct name. pub ident: Ident, /// Discriminant of this variant. @@ -1824,11 +1824,6 @@ pub struct VariantDef { 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? @@ -1856,7 +1851,7 @@ impl<'a, 'gcx, 'tcx> VariantDef { tcx: TyCtxt<'a, 'gcx, 'tcx>, ident: Ident, variant_did: Option, - ctor_did: Option, + ctor_def_id: Option, discr: VariantDiscr, fields: Vec, ctor_kind: CtorKind, @@ -1865,9 +1860,9 @@ impl<'a, 'gcx, 'tcx> VariantDef { recovered: bool, ) -> Self { debug!( - "VariantDef::new(ident = {:?}, variant_did = {:?}, ctor_did = {:?}, discr = {:?}, + "VariantDef::new(ident = {:?}, variant_did = {:?}, ctor_def_id = {:?}, discr = {:?}, fields = {:?}, ctor_kind = {:?}, adt_kind = {:?}, parent_did = {:?})", - ident, variant_did, ctor_did, discr, fields, ctor_kind, adt_kind, parent_did, + ident, variant_did, ctor_def_id, discr, fields, ctor_kind, adt_kind, parent_did, ); let mut flags = VariantFlags::NO_VARIANT_FLAGS; @@ -1877,14 +1872,13 @@ impl<'a, 'gcx, 'tcx> VariantDef { } VariantDef { - variant_did, - ctor_did, + def_id: variant_did.unwrap_or(parent_did), + ctor_def_id, ident, discr, fields, ctor_kind, flags, - parent_did, recovered, } } @@ -1894,62 +1888,16 @@ impl<'a, 'gcx, 'tcx> VariantDef { 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 { - variant_did, - ctor_did, + def_id, + ctor_def_id, ident -> (ident.name), discr, fields, ctor_kind, flags, - parent_did, recovered }); @@ -2204,7 +2152,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { AdtKind::Struct => AdtFlags::IS_STRUCT, }; - if kind == AdtKind::Struct && variants[VariantIdx::new(0)].ctor_did.is_some() { + if kind == AdtKind::Struct && variants[VariantIdx::new(0)].ctor_def_id.is_some() { flags |= AdtFlags::HAS_CTOR; } @@ -2351,51 +2299,29 @@ impl<'a, 'gcx, 'tcx> AdtDef { self.variants.iter().all(|v| v.fields.is_empty()) } - pub fn variant_with_variant_id(&self, vid: DefId) -> &VariantDef { - self.variants - .iter() - .find(|v| v.variant_did.map(|did| did == vid).unwrap_or(false)) - .expect("variant_with_variant_id: unknown variant") + pub fn variant_with_id(&self, vid: DefId) -> &VariantDef { + self.variants.iter().find(|v| v.def_id == vid) + .expect("variant_with_id: unknown variant") } 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)) + self.variants.iter().find(|v| v.ctor_def_id == Some(cid)) .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.variant_did.map(|did| did == vid).unwrap_or(false)) - .expect("variant_index_with_variant_id: unknown variant") - .0 + pub fn variant_index_with_id(&self, vid: DefId) -> VariantIdx { + self.variants.iter_enumerated().find(|(_, v)| v.def_id == vid) + .expect("variant_index_with_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 + self.variants.iter_enumerated().find(|(_, v)| v.ctor_def_id == Some(cid)) + .expect("variant_index_with_ctor_id: unknown variant").0 } pub fn variant_of_def(&self, def: Def) -> &VariantDef { match def { - Def::Variant(vid) => self.variant_with_variant_id(vid), + Def::Variant(vid) => self.variant_with_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(..) | @@ -2933,8 +2859,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option { variant.fields.iter().position(|field| { - let did = variant.variant_did.unwrap_or(variant.parent_did); - self.adjust_ident(ident, did, hir::DUMMY_HIR_ID).0 == field.ident.modern() + self.adjust_ident(ident, variant.def_id, hir::DUMMY_HIR_ID).0 == field.ident.modern() }) } @@ -3011,7 +2936,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match def { Def::Variant(did) => { let enum_did = self.parent(did).unwrap(); - self.adt_def(enum_did).variant_with_variant_id(did) + self.adt_def(enum_did).variant_with_id(did) } Def::Struct(did) | Def::Union(did) => { self.adt_def(did).non_enum_variant() @@ -3029,11 +2954,6 @@ 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 { - variant_def.parent_did - } - pub fn item_name(self, id: DefId) -> InternedString { if id.index == CRATE_DEF_INDEX { self.original_crate_name(id.krate).as_interned_str() diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 1af59f314bc2b..78a186fbb714a 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -579,13 +579,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; - let def_id = variant.variant_did(); + let def_id = variant.def_id; debug!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id); let data = VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - ctor: variant.ctor_did().map(|did| did.index), + ctor: variant.ctor_def_id.map(|did| did.index), ctor_sig: None, }; @@ -628,7 +628,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; - let def_id = variant.ctor_did().unwrap(); + let def_id = variant.ctor_def_id.unwrap(); debug!("IsolatedEncoder::encode_enum_variant_ctor({:?})", def_id); let data = VariantData { @@ -726,9 +726,7 @@ 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.variant_did_or_parent_struct_did()) - .unwrap(); + let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap(); let variant_data = tcx.hir().expect_variant_data(variant_id); Entry { @@ -1218,9 +1216,8 @@ 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| { - let did = v.variant_did(); - assert!(did.is_local()); - did.index + assert!(v.def_id.is_local()); + v.def_id.index })) } hir::ItemKind::Struct(..) | @@ -1813,12 +1810,12 @@ 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.variant_did(), + self.record(variant.def_id, IsolatedEncoder::encode_enum_variant_info, (def_id, Untracked(i))); - if let Some(ctor_hir_did) = variant.ctor_did() { - self.record(ctor_hir_did, + if let Some(ctor_def_id) = variant.ctor_def_id { + self.record(ctor_def_id, IsolatedEncoder::encode_enum_variant_ctor, (def_id, Untracked(i))); } diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 77978d7d38ff7..2e4f53023f409 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -163,7 +163,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { i == variant_index || { self.hir.tcx().features().never_type && self.hir.tcx().features().exhaustive_patterns && - self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs) + !v.uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind()).is_empty() } }); if irrefutable { diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index eb50bd727db15..610c63b208cb6 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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_variant_id(variant_id); + let index = adt.variant_index_with_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); diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 9637a111f42a0..303ffcb3bfb3a 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -168,7 +168,7 @@ use super::{PatternFoldable, PatternFolder, compare_const_vals}; use rustc::hir::def_id::DefId; use rustc::hir::RangeEnd; -use rustc::ty::{self, subst::SubstsRef, Ty, TyCtxt, TypeFoldable, Const}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const}; use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size}; use rustc::mir::Field; @@ -399,22 +399,10 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { _ => false, } } - - fn is_variant_uninhabited(&self, - variant: &'tcx ty::VariantDef, - substs: SubstsRef<'tcx>) - -> bool - { - if self.tcx.features().exhaustive_patterns { - self.tcx.is_enum_variant_uninhabited_from(self.module, variant, substs) - } else { - false - } - } } #[derive(Clone, Debug, PartialEq)] -pub enum Constructor<'tcx> { +enum Constructor<'tcx> { /// The constructor of all patterns that don't vary by constructor, /// e.g., struct patterns and fixed-length arrays. Single, @@ -435,7 +423,7 @@ impl<'tcx> Constructor<'tcx> { adt: &'tcx ty::AdtDef, ) -> VariantIdx { match self { - &Variant(id) => adt.variant_index_with_ctor_or_variant_id(id), + &Variant(id) => adt.variant_index_with_id(id), &Single => { assert!(!adt.is_enum()); VariantIdx::new(0) @@ -658,8 +646,11 @@ 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| v.ctor_did().map_or_else(|| Variant(v.variant_did()), |did| Variant(did))) + .filter(|v| { + !cx.tcx.features().exhaustive_patterns || + !v.uninhabited_from(cx.tcx, substs, def.adt_kind()).contains(cx.tcx, cx.module) + }) + .map(|v| Variant(v.def_id)) .collect() } ty::Char => { @@ -1307,9 +1298,7 @@ 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, .. } => { - let variant = &adt_def.variants[variant_index]; - Some(variant.ctor_did() - .map_or_else(|| vec![Variant(variant.variant_did())], |did| vec![Variant(did)])) + Some(vec![Variant(adt_def.variants[variant_index].def_id)]) } PatternKind::Constant { value } => Some(vec![ConstantValue(value)]), PatternKind::Range(PatternRange { lo, hi, ty, end }) => @@ -1744,9 +1733,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>( PatternKind::Variant { adt_def, variant_index, ref subpatterns, .. } => { let ref variant = adt_def.variants[variant_index]; - variant.ctor_did() - .map(|did| Variant(did)) - .or_else(|| Some(Variant(variant.variant_did()))) + Some(Variant(variant.def_id)) .filter(|variant_constructor| variant_constructor == constructor) .map(|_| patterns_for_variant(subpatterns, wild_patterns)) } diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 8349f21cdb47e..2f1c542b4737c 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -757,7 +757,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatternKind::Variant { adt_def, substs, - variant_index: adt_def.variant_index_with_variant_id(variant_id), + variant_index: adt_def.variant_index_with_id(variant_id), subpatterns, } } else { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ad62d2160b1eb..32986014282a5 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1318,11 +1318,10 @@ 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 did = variant_def.variant_did(); - let def = Def::Variant(did); + let def = Def::Variant(variant_def.def_id); if permit_variants { check_type_alias_enum_variants_enabled(tcx, span); - tcx.check_stability(did, Some(hir_ref_id), span); + tcx.check_stability(variant_def.def_id, Some(hir_ref_id), span); return (qself_ty, def); } else { variant_resolution = Some(def); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 6d441521a9e98..d56a0dcc0446c 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -947,8 +947,7 @@ 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.variant_did_or_parent_struct_did(), self.body_id).0; + let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0; let field_ty = match used_fields.entry(ident) { Occupied(occupied) => { struct_span_err!(tcx.sess, span, E0025, @@ -996,19 +995,18 @@ 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(did), + tcx.def_path_str(variant.def_id), 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(did), + tcx.def_path_str(variant.def_id), t, plural)); if plural == "" { diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 5d10f531ced4d..b1a249d821bec 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.variant_did()); + let variant_path = self.tcx.def_path_str(variant.def_id); // 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 f860ab649f990..0060b1031a761 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -417,13 +417,13 @@ 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 = if let Some(ctor_did) = variant_def.ctor_did() { - Def::Ctor(hir::CtorOf::Variant, ctor_did, variant_def.ctor_kind) + let def = if let Some(ctor_def_id) = variant_def.ctor_def_id { + Def::Ctor(hir::CtorOf::Variant, ctor_def_id, 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(), + Def::Ctor(hir::CtorOf::Variant, variant_def.def_id, hir::def::CtorKind::Fictive) }; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index fe17f247916b6..b6bfa9ce27bd2 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)].variant_did(); + let variant_did = def.variants[VariantIdx::new(i)].def_id; 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,7 @@ 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.is_local() && field.vis != Visibility::Public) + (!variant.def_id.is_local() && field.vis != Visibility::Public) { None } else { @@ -3706,8 +3706,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec { variant.fields.iter().filter(|field| { - let did = variant.variant_did_or_parent_struct_did(); - let def_scope = self.tcx.adjust_ident(field.ident, did, self.body_id).1; + let def_scope = self.tcx.adjust_ident(field.ident, variant.def_id, self.body_id).1; field.vis.is_accessible_from(def_scope, self.tcx) }) .map(|field| field.ident.name) @@ -3825,8 +3824,7 @@ 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.variant_did_or_parent_struct_did(), self.body_id).0; + let ident = tcx.adjust_ident(field.ident, variant.def_id, 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); @@ -5346,9 +5344,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 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 ctor_def_id = variant.ctor_def_id.unwrap(); + let def = Def::Ctor(hir::CtorOf::Struct, ctor_def_id, variant.ctor_kind); + (def, ctor_def_id, tcx.type_of(ctor_def_id)) } _ => { let mut err = tcx.sess.struct_span_err(span, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ddd68c483790e..61dbf00a1f536 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3169,16 +3169,15 @@ 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, did), - source: cx.tcx.def_span(did).clean(cx), + attrs: inline::load_attrs(cx, self.def_id), + source: cx.tcx.def_span(self.def_id).clean(cx), visibility: Some(Inherited), - def_id: did, + def_id: self.def_id, inner: VariantItem(Variant { kind }), - stability: get_stability(cx, did), - deprecation: get_deprecation(cx, did), + stability: get_stability(cx, self.def_id), + deprecation: get_deprecation(cx, self.def_id), } } } From 5bcf9f4f119b8109c6c642dcfeb63fb39c26950a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 24 Mar 2019 15:29:57 +0300 Subject: [PATCH 4/9] Slightly more uniform treatment of struct and variant constructors --- src/librustc/hir/def.rs | 8 +++----- src/librustc/ty/mod.rs | 4 ++-- src/librustc_mir/hair/cx/expr.rs | 6 ++---- src/librustc_resolve/error_reporting.rs | 4 ++-- src/librustc_typeck/check/_match.rs | 8 ++++---- src/librustc_typeck/check/mod.rs | 2 +- 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 87a6065bb75ec..6567d9e8c7a9d 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -37,13 +37,11 @@ pub enum NonMacroAttrKind { pub enum Def { // Type namespace Mod(DefId), - /// `DefId` refers to `NodeId` of the struct. `Def::VariantCtor` represents the constructor of - /// a struct. + /// `DefId` refers to the struct itself, `Def::Ctor` refers to its constructor if it exists. Struct(DefId), Union(DefId), Enum(DefId), - /// `DefId` refers to the `NodeId` of the variant. `Def::VariantCtor` represents the - /// constructor of an enum variant. + /// `DefId` refers to the variant itself, `Def::Ctor` refers to its constructor if it exists. Variant(DefId), Trait(DefId), /// `existential type Foo: Bar;` @@ -65,7 +63,7 @@ pub enum Def { Const(DefId), ConstParam(DefId), Static(DefId, bool /* is_mutbl */), - /// `DefId` refers to `NodeId` of the struct or enum variant's constructor. + /// `DefId` refers to the struct or enum variant's constructor. Ctor(hir::CtorOf, DefId, CtorKind), SelfCtor(DefId /* impl */), // `DefId` refers to the impl Method(DefId), diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 10755a9c0218e..3ab3ae0c537bb 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2322,8 +2322,8 @@ impl<'a, 'gcx, 'tcx> AdtDef { pub fn variant_of_def(&self, def: Def) -> &VariantDef { match def { Def::Variant(vid) => self.variant_with_id(vid), - Def::Ctor(hir::CtorOf::Variant, cid, ..) => self.variant_with_ctor_id(cid), - Def::Struct(..) | Def::Ctor(..) | Def::Union(..) | + Def::Ctor(_, cid, ..) => self.variant_with_ctor_id(cid), + Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => self.non_enum_variant(), _ => bug!("unexpected def {:?} in variant_of_def", def) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 610c63b208cb6..27dba512dfb58 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -261,10 +261,8 @@ 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::Ctor(hir::CtorOf::Variant, variant_ctor_id, CtorKind::Fn) => { - Some((adt_def, adt_def.variant_index_with_ctor_id(variant_ctor_id))) - } - Def::Ctor(hir::CtorOf::Struct, _, CtorKind::Fn) | + Def::Ctor(_, ctor_id, CtorKind::Fn) => + Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id))), Def::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))), _ => None, } diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index 6426ca12c6c92..dbd323821949d 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::{self, def::*}; +use rustc::hir::def::{Def, CtorKind}; 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::Ctor(hir::CtorOf::Variant, _, CtorKind::Fictive), _) if ns == ValueNS => { + (Def::Ctor(_, _, CtorKind::Fictive), _) if ns == ValueNS => { err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?", path_str)); } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index d56a0dcc0446c..5f46a5a165213 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -807,13 +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::Ctor(hir::CtorOf::Variant, _, CtorKind::Fictive) | - Def::Ctor(hir::CtorOf::Variant, _, CtorKind::Fn) => { + Def::Ctor(_, _, CtorKind::Fictive) | + Def::Ctor(_, _, CtorKind::Fn) => { report_unexpected_variant_def(tcx, &def, pat.span, qpath); return tcx.types.err; } - Def::Ctor(_, _, 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) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b6bfa9ce27bd2..e842be0d7e1a5 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4238,7 +4238,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.set_tainted_by_errors(); tcx.types.err } - Def::Ctor(hir::CtorOf::Variant, _, CtorKind::Fictive) => { + Def::Ctor(_, _, CtorKind::Fictive) => { report_unexpected_variant_def(tcx, &def, expr.span, qpath); tcx.types.err } From 2cbc25e6fce9bb594ea78ccfd58ef1b6ea42ea38 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 24 Mar 2019 17:49:58 +0300 Subject: [PATCH 5/9] Merge `DefPathData::VariantCtor` and `DefPathData::StructCtor` --- src/librustc/hir/map/def_collector.rs | 10 ++-------- src/librustc/hir/map/definitions.rs | 12 ++++-------- src/librustc/ty/instance.rs | 3 +-- src/librustc/ty/mod.rs | 4 ++-- src/librustc/ty/print/pretty.rs | 11 +++++------ src/librustc/ty/util.rs | 4 ++-- src/librustc_codegen_utils/symbol_names.rs | 2 +- src/librustc_metadata/decoder.rs | 4 ++-- src/librustc_mir/borrow_check/mod.rs | 4 ++-- src/librustc_mir/borrow_check/nll/type_check/mod.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 2 +- src/test/mir-opt/unusual-item-types.rs | 4 ++-- 12 files changed, 26 insertions(+), 38 deletions(-) diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 2c92d907201d5..1a3bbc5ecc49e 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -160,10 +160,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => { // 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); + this.create_def(ctor_hir_id, DefPathData::Ctor, REGULAR_SPACE, i.span); } } _ => {} @@ -199,10 +196,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { v.span); 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); + this.create_def(ctor_hir_id, DefPathData::Ctor, REGULAR_SPACE, v.span); } visit::walk_variant(this, v, g, item_id) }); diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index dc23b55c1fcb3..1006d813e65ed 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -366,10 +366,8 @@ pub enum DefPathData { EnumVariant(InternedString), /// A struct field Field(InternedString), - /// Implicit ctor for a unit or tuple-like struct - StructCtor, - /// Implicit ctor for a unit or tuple-like enum variant - VariantCtor, + /// Implicit ctor for a unit or tuple-like struct or enum variant. + Ctor, /// A constant expression (see {ast,hir}::AnonConst). AnonConst, /// An `impl Trait` type node @@ -654,8 +652,7 @@ impl DefPathData { CrateRoot | Misc | ClosureExpr | - StructCtor | - VariantCtor | + Ctor | AnonConst | ImplTrait => None } @@ -686,8 +683,7 @@ impl DefPathData { Impl => "{{impl}}", Misc => "{{misc}}", ClosureExpr => "{{closure}}", - StructCtor => "{{struct constructor}}", - VariantCtor => "{{variant constructor}}", + Ctor => "{{constructor}}", AnonConst => "{{constant}}", ImplTrait => "{{opaque}}", }; diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 84ce826c6a588..f54e69f352a4e 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::VariantCtor | - DefPathData::ClosureExpr => true, + DefPathData::Ctor | DefPathData::ClosureExpr => true, _ => false } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 3ab3ae0c537bb..880f75ab9ddba 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2960,8 +2960,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } else { let def_key = self.def_key(id); 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 => + // The name of a constructor is that of its parent. + hir_map::DefPathData::Ctor => self.item_name(DefId { krate: id.krate, index: def_key.parent.unwrap() diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 3d6a2cf9224be..c9a4961a8e044 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -285,13 +285,13 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: let mut cur_def_key = self.tcx().def_key(def_id); 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 . + // For a constructor we want the name of its parent rather than . match cur_def_key.disambiguated_data.data { - DefPathData::StructCtor | DefPathData::VariantCtor => { + DefPathData::Ctor => { let parent = DefId { krate: def_id.krate, index: cur_def_key.parent - .expect("DefPathData::StructCtor/VariantData missing a parent"), + .expect("DefPathData::Ctor/VariantData missing a parent"), }; cur_def_key = self.tcx().def_key(parent); @@ -864,8 +864,7 @@ impl TyCtxt<'_, '_, '_> { DefPathData::AnonConst | DefPathData::ConstParam(..) | DefPathData::ClosureExpr | - DefPathData::VariantCtor | - DefPathData::StructCtor => Namespace::ValueNS, + DefPathData::Ctor => Namespace::ValueNS, DefPathData::MacroDef(..) => Namespace::MacroNS, @@ -1029,7 +1028,7 @@ impl Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { // Skip `::{{constructor}}` on tuple/unit structs. match disambiguated_data.data { - DefPathData::StructCtor | DefPathData::VariantCtor => return Ok(self), + DefPathData::Ctor => return Ok(self), _ => {} } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 4fb2bfb075c8f..ccead14e76b23 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -549,8 +549,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns `true` if this `DefId` refers to the implicit constructor for /// a tuple struct like `struct Foo(u32)`, and `false` otherwise. - pub fn is_struct_constructor(self, def_id: DefId) -> bool { - self.def_key(def_id).disambiguated_data.data == DefPathData::StructCtor + pub fn is_constructor(self, def_id: DefId) -> bool { + self.def_key(def_id).disambiguated_data.data == DefPathData::Ctor } /// Given the `DefId` of a fn or closure, returns the `DefId` of diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 0fa935199f97b..ebd48f0ae1e2b 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -522,7 +522,7 @@ impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> { // Skip `::{{constructor}}` on tuple/unit structs. match disambiguated_data.data { - DefPathData::StructCtor => return Ok(self), + DefPathData::Ctor => return Ok(self), _ => {} } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index c6f7b46d38339..0e750cd15eebd 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -947,11 +947,11 @@ impl<'a, 'tcx> CrateMetadata { return Lrc::new([]); } - // The attributes for a tuple struct are attached to the definition, not the ctor; + // The attributes for a tuple struct/variant are attached to the definition, not the ctor; // we assume that someone passing in a tuple struct ctor is actually wanting to // look at the definition let def_key = self.def_key(node_id); - let item_id = if def_key.disambiguated_data.data == DefPathData::StructCtor { + let item_id = if def_key.disambiguated_data.data == DefPathData::Ctor { def_key.parent.unwrap() } else { node_id diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index c4e371d5afedb..5f0892d1d46e6 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -75,8 +75,8 @@ fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> BorrowC // Return early if we are not supposed to use MIR borrow checker for this function. return_early = !tcx.has_attr(def_id, "rustc_mir") && !tcx.use_mir_borrowck(); - if tcx.is_struct_constructor(def_id) { - // We are not borrow checking the automatically generated struct constructors + if tcx.is_constructor(def_id) { + // We are not borrow checking the automatically generated struct/variant constructors // because we want to accept structs such as this (taken from the `linked-hash-map` // crate): // ```rust diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 25a3160a498d3..d3d6b98627703 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -2685,8 +2685,8 @@ impl MirPass for TypeckMir { return; } - if tcx.is_struct_constructor(def_id) { - // We just assume that the automatically generated struct constructors are + if tcx.is_constructor(def_id) { + // We just assume that the automatically generated struct/variant constructors are // correct. See the comment in the `mir_borrowck` implementation for an // explanation why we need this. return; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e842be0d7e1a5..f4f17e1dcc519 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5334,7 +5334,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Some(original_span.with_lo(original_span.hi() - BytePos(1))) } - // Rewrite `SelfCtor` to `StructCtor` + // Rewrite `SelfCtor` to `Ctor` pub fn rewrite_self_ctor(&self, def: Def, span: Span) -> (Def, DefId, Ty<'tcx>) { let tcx = self.tcx; if let Def::SelfCtor(impl_def_id) = def { diff --git a/src/test/mir-opt/unusual-item-types.rs b/src/test/mir-opt/unusual-item-types.rs index 29c97ed6d3845..606503151c985 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-{{variant constructor}}.mir_map.0.mir +// START rustc.Test-X-{{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-{{variant constructor}}.mir_map.0.mir +// END rustc.Test-X-{{constructor}}.mir_map.0.mir From 782a6debe4542788a6c455070e06fb1137941376 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 24 Mar 2019 18:41:09 +0300 Subject: [PATCH 6/9] Revert changes to creation of fictive constructors for struct variants --- src/librustc_metadata/decoder.rs | 18 ++++--- src/librustc_resolve/build_reduced_graph.rs | 58 +++++---------------- src/librustc_typeck/check/method/mod.rs | 15 +++--- 3 files changed, 29 insertions(+), 62 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 0e750cd15eebd..32aa75166aec0 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -822,14 +822,16 @@ impl<'a, 'tcx> CrateMetadata { callback(def::Export { def: ctor_def, vis, ident, 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 }); - } + Def::Variant(def_id) => { + // Braced variants, unlike structs, generate unusable names in + // value namespace, they are reserved for possible future use. + // It's ok to use the variant's id as a ctor id since an + // error will be reported on any use of such resolution anyway. + let ctor_def_id = self.get_ctor_def_id(child_index).unwrap_or(def_id); + 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 }); } _ => {} } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 72197d4a17aa5..0cb6872ce7654 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -582,31 +582,22 @@ impl<'a> Resolver<'a> { vis: ty::Visibility, expansion: Mark) { let ident = variant.node.ident; - let def_id = self.definitions.local_def_id(variant.node.id); // Define a name in the type namespace. + let def_id = self.definitions.local_def_id(variant.node.id); let def = Def::Variant(def_id); self.define(parent, ident, TypeNS, (def, vis, variant.span, expansion)); // 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. - 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)); - } 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)); - } + // It's ok to use the variant's id as a ctor id since an + // error will be reported on any use of such resolution anyway. + let ctor_node_id = variant.node.data.ctor_id().unwrap_or(variant.node.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)); } /// Constructs the reduced graph for one foreign item. @@ -658,27 +649,13 @@ impl<'a> Resolver<'a> { span); self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); } - Def::Variant(def_id) => { + Def::Variant(..) | Def::TyAlias(..) | Def::ForeignTy(..) | Def::Existential(..) | + Def::TraitAlias(..) | Def::PrimTy(..) | Def::ToolMod => { 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::Ctor(hir::CtorOf::Variant, ..) => { + self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); } Def::Ctor(hir::CtorOf::Struct, def_id, ..) => { self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); @@ -689,15 +666,6 @@ 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_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 0060b1031a761..26024ece05427 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -417,15 +417,12 @@ 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 = if let Some(ctor_def_id) = variant_def.ctor_def_id { - Def::Ctor(hir::CtorOf::Variant, ctor_def_id, 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.def_id, - hir::def::CtorKind::Fictive) - }; + // Braced variants generate unusable names in value namespace (reserved for + // possible future use), so variants resolved as associated items may refer to + // them as well. It's ok to use the variant's id as a ctor id since an + // error will be reported on any use of such resolution anyway. + let ctor_def_id = variant_def.ctor_def_id.unwrap_or(variant_def.def_id); + let def = Def::Ctor(hir::CtorOf::Variant, ctor_def_id, variant_def.ctor_kind); tcx.check_stability(def.def_id(), Some(expr_id), span); return Ok(def); From db4770f699bb5e700c5946d5d1a1651c3ad0bfcc Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 24 Mar 2019 18:21:59 +0100 Subject: [PATCH 7/9] Remove `CtorOf` from `Node::Ctor`. This commit removes `CtorOf` from `Node::Ctor` as the parent of the constructor can be determined by looking at the node's parent in the few places where knowing this is necessary. --- src/librustc/hir/map/collector.rs | 6 +-- src/librustc/hir/map/mod.rs | 22 +++++---- src/librustc/hir/mod.rs | 2 +- src/librustc/traits/error_reporting.rs | 2 +- src/librustc_borrowck/borrowck/mod.rs | 2 +- src/librustc_mir/build/mod.rs | 2 +- src/librustc_privacy/lib.rs | 66 +++++++++++++++---------- src/librustc_resolve/error_reporting.rs | 3 +- src/librustc_typeck/collect.rs | 4 +- 9 files changed, 61 insertions(+), 48 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index e7cd8f113539a..75d7d843dea7e 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -362,9 +362,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { if let ItemKind::Struct(ref struct_def, _) = i.node { // 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)); + this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def)); } } intravisit::walk_item(this, i); @@ -521,7 +519,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { 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)); + this.insert(v.span, ctor_hir_id, Node::Ctor(&v.node.data)); } intravisit::walk_variant(this, v, g, item_id); }); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index ce0246dec7182..ee3bc72632a7c 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -369,12 +369,15 @@ impl<'hir> Map<'hir> { let def_id = self.local_def_id_from_hir_id(variant.node.id); Some(Def::Variant(def_id)) } - Node::Ctor(ctor_of, variant_data) => { + Node::Ctor(variant_data) => { + let ctor_of = match self.find(self.get_parent_node(node_id)) { + Some(Node::Item(..)) => CtorOf::Struct, + Some(Node::Variant(..)) => CtorOf::Variant, + _ => unreachable!(), + }; variant_data.ctor_hir_id() .map(|hir_id| self.local_def_id_from_hir_id(hir_id)) - .map(|def_id| Def::Ctor( - ctor_of, def_id, def::CtorKind::from_hir(variant_data), - )) + .map(|def_id| Def::Ctor(ctor_of, def_id, def::CtorKind::from_hir(variant_data))) } Node::AnonConst(_) | Node::Field(_) | @@ -951,7 +954,7 @@ impl<'hir> Map<'hir> { } } Some(Node::Variant(variant)) => &variant.node.data, - Some(Node::Ctor(_, data)) => data, + Some(Node::Ctor(data)) => data, _ => bug!("expected struct or variant, found {}", self.hir_to_string(id)) } } @@ -1070,10 +1073,11 @@ impl<'hir> Map<'hir> { Some(Node::Binding(pat)) => pat.span, Some(Node::Pat(pat)) => pat.span, Some(Node::Block(block)) => block.span, - Some(Node::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::Ctor(..)) => match self.find(self.get_parent_node(id)) { + Some(Node::Item(item)) => item.span, + Some(Node::Variant(variant)) => variant.span, + _ => unreachable!(), + } Some(Node::Lifetime(lifetime)) => lifetime.span, Some(Node::GenericParam(param)) => param.span, Some(Node::Visibility(&Spanned { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 7895919e15078..0ffbb1c8106e2 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2590,7 +2590,7 @@ pub enum Node<'hir> { /// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants /// with synthesized constructors. - Ctor(CtorOf, &'hir VariantData), + Ctor(&'hir VariantData), Lifetime(&'hir Lifetime), GenericParam(&'hir GenericParam), diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index ef232c06921df..5b5a7cc9ed85b 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1077,7 +1077,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { _ => ArgKind::empty() }).collect::>()) } - Node::Ctor(_, ref variant_data) => { + 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); diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 7e38ce6377c89..09de907b75104 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -85,7 +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::Ctor(_, _) => { + 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_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 0283352066cb8..7fe86d11c9ee4 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -31,7 +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::Ctor(_, 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_privacy/lib.rs b/src/librustc_privacy/lib.rs index 96fdb6a438228..bbd03e82a3730 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::Ctor(hir::CtorOf::Variant, ..) => { + Node::TraitItem(..) | Node::Variant(..) => { return def_id_visibility(tcx, tcx.hir().get_parent_did_by_hir_id(hir_id)); } Node::ImplItem(impl_item) => { @@ -239,36 +239,48 @@ fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) node => bug!("unexpected node kind: {:?}", node), } } - 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, - node => bug!("unexpected node kind: {:?}", node), - }; - let (mut ctor_vis, mut span, mut descr) = - (ty::Visibility::from_hir(&item.vis, struct_hir_id, tcx), - item.vis.span, item.vis.node.descr()); - for field in vdata.fields() { - let field_vis = ty::Visibility::from_hir(&field.vis, hir_id, tcx); - if ctor_vis.is_at_least(field_vis, tcx) { - ctor_vis = field_vis; - span = field.vis.span; - descr = field.vis.node.descr(); + Node::Ctor(vdata) => { + let parent_hir_id = tcx.hir().get_parent_node_by_hir_id(hir_id); + match tcx.hir().get_by_hir_id(parent_hir_id) { + Node::Variant(..) => { + let parent_did = tcx.hir().local_def_id_from_hir_id(parent_hir_id); + return def_id_visibility(tcx, parent_did); } - } + Node::Item(..) => { + let item = match tcx.hir().get_by_hir_id(parent_hir_id) { + Node::Item(item) => item, + node => bug!("unexpected node kind: {:?}", node), + }; + let (mut ctor_vis, mut span, mut descr) = + (ty::Visibility::from_hir(&item.vis, parent_hir_id, tcx), + item.vis.span, item.vis.node.descr()); + for field in vdata.fields() { + let field_vis = ty::Visibility::from_hir(&field.vis, hir_id, tcx); + if ctor_vis.is_at_least(field_vis, tcx) { + ctor_vis = field_vis; + span = field.vis.span; + descr = field.vis.node.descr(); + } + } - // If the structure is marked as non_exhaustive then lower the - // visibility to within the crate. - if ctor_vis == ty::Visibility::Public { - let adt_def = tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id)); - if adt_def.non_enum_variant().is_field_list_non_exhaustive() { - ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); - span = attr::find_by_name(&item.attrs, "non_exhaustive").unwrap().span; - descr = "crate-visible"; + // If the structure is marked as non_exhaustive then lower the + // visibility to within the crate. + if ctor_vis == ty::Visibility::Public { + let adt_def = + tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id)); + if adt_def.non_enum_variant().is_field_list_non_exhaustive() { + ctor_vis = + ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); + span = attr::find_by_name(&item.attrs, "non_exhaustive") + .unwrap().span; + descr = "crate-visible"; + } + } + + return (ctor_vis, span, descr); } + node => bug!("unexpected node kind: {:?}", node), } - - return (ctor_vis, span, descr); } Node::Expr(expr) => { return (ty::Visibility::Restricted( diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index dbd323821949d..fc8452e49ad1b 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -2,8 +2,7 @@ use std::cmp::Reverse; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use log::debug; -use rustc::hir::def::{Def, CtorKind}; -use rustc::hir::def::Namespace::*; +use rustc::hir::def::{Def, CtorKind, Namespace::*}; use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId}; use rustc::session::config::nightly_options; use syntax::ast::{ExprKind}; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 56129479f7755..06450424776d4 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1247,7 +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::Ctor(_, &ref def) | Node::Variant(&Spanned { + Node::Ctor(&ref def) | Node::Variant(&Spanned { node: hir::VariantKind { data: ref def, .. }, .. }) => match *def { @@ -1625,7 +1625,7 @@ 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) } - Ctor(_, data) | Variant(Spanned { + Ctor(data) | Variant(Spanned { node: hir::VariantKind { data, .. }, .. }) if data.ctor_hir_id().is_some() => { From 88f8f0779417963fe04aaba6719f1752ff1ce487 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 24 Mar 2019 18:54:56 +0100 Subject: [PATCH 8/9] Move `CtorOf` into `hir::def`. This commit moves the definition of `CtorOf` from `rustc::hir` to `rustc::hir::def` and adds imports wherever it is used. --- src/librustc/hir/def.rs | 23 ++++++++++++++------- src/librustc/hir/map/mod.rs | 4 ++-- src/librustc/hir/mod.rs | 9 -------- src/librustc/hir/pat_util.rs | 4 ++-- src/librustc/middle/dead.rs | 4 ++-- src/librustc/middle/expr_use_visitor.rs | 4 ++-- src/librustc/middle/mem_categorization.rs | 8 +++---- src/librustc/ty/mod.rs | 6 +++--- src/librustc_metadata/decoder.rs | 6 +++--- src/librustc_mir/hair/cx/expr.rs | 4 ++-- src/librustc_mir/hair/pattern/mod.rs | 6 +++--- src/librustc_resolve/build_reduced_graph.rs | 10 ++++----- src/librustc_resolve/lib.rs | 2 +- src/librustc_save_analysis/lib.rs | 4 ++-- src/librustc_typeck/astconv.rs | 6 +++--- src/librustc_typeck/check/method/mod.rs | 5 ++--- src/librustc_typeck/check/mod.rs | 6 +++--- 17 files changed, 55 insertions(+), 56 deletions(-) diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index 6567d9e8c7a9d..e30d4a1a648e1 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -9,6 +9,15 @@ use crate::ty; use self::Namespace::*; +/// Encodes if a `Def::Ctor` is the constructor of an enum variant or a struct. +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] +pub enum CtorOf { + /// This `Def::Ctor` is a synthesized constructor of a tuple or unit struct. + Struct, + /// This `Def::Ctor` is a synthesized constructor of a tuple or unit variant. + Variant, +} + #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)] pub enum CtorKind { /// Constructor function automatically created by a tuple struct/variant. @@ -64,7 +73,7 @@ pub enum Def { ConstParam(DefId), Static(DefId, bool /* is_mutbl */), /// `DefId` refers to the struct or enum variant's constructor. - Ctor(hir::CtorOf, DefId, CtorKind), + Ctor(CtorOf, DefId, CtorKind), SelfCtor(DefId /* impl */), // `DefId` refers to the impl Method(DefId), AssociatedConst(DefId), @@ -306,13 +315,13 @@ impl Def { Def::Static(..) => "static", 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::Ctor(CtorOf::Variant, _, CtorKind::Fn) => "tuple variant", + Def::Ctor(CtorOf::Variant, _, CtorKind::Const) => "unit variant", + Def::Ctor(CtorOf::Variant, _, CtorKind::Fictive) => "struct variant", Def::Struct(..) => "struct", - Def::Ctor(hir::CtorOf::Struct, _, CtorKind::Fn) => "tuple struct", - Def::Ctor(hir::CtorOf::Struct, _, CtorKind::Const) => "unit struct", - Def::Ctor(hir::CtorOf::Struct, _, CtorKind::Fictive) => + Def::Ctor(CtorOf::Struct, _, CtorKind::Fn) => "tuple struct", + Def::Ctor(CtorOf::Struct, _, CtorKind::Const) => "unit struct", + Def::Ctor(CtorOf::Struct, _, CtorKind::Fictive) => bug!("impossible struct constructor"), Def::Existential(..) => "existential type", Def::TyAlias(..) => "type alias", diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index ee3bc72632a7c..b94ccd90abdad 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -371,8 +371,8 @@ impl<'hir> Map<'hir> { } Node::Ctor(variant_data) => { let ctor_of = match self.find(self.get_parent_node(node_id)) { - Some(Node::Item(..)) => CtorOf::Struct, - Some(Node::Variant(..)) => CtorOf::Variant, + Some(Node::Item(..)) => def::CtorOf::Struct, + Some(Node::Variant(..)) => def::CtorOf::Variant, _ => unreachable!(), }; variant_data.ctor_hir_id() diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 0ffbb1c8106e2..1bf7eed71bf0f 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2559,15 +2559,6 @@ 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), diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index b859a0f389ed5..bce559b17fa00 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -1,4 +1,4 @@ -use crate::hir::def::Def; +use crate::hir::def::{CtorOf, Def}; use crate::hir::def_id::DefId; use crate::hir::{self, HirId, PatKind}; use syntax::ast; @@ -126,7 +126,7 @@ impl hir::Pat { PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => { match path.def { Def::Variant(id) => variants.push(id), - Def::Ctor(hir::CtorOf::Variant, id, _) => variants.push(id), + Def::Ctor(CtorOf::Variant, id, _) => variants.push(id), _ => () } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 786d339e876c5..da62423000261 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -7,7 +7,7 @@ use crate::hir::{self, PatKind, TyKind}; use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; use crate::hir::itemlikevisit::ItemLikeVisitor; -use crate::hir::def::Def; +use crate::hir::def::{CtorOf, Def}; use crate::hir::CodegenFnAttrFlags; use crate::hir::def_id::{DefId, LOCAL_CRATE}; use crate::lint; @@ -76,7 +76,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { _ if self.in_pat => (), Def::PrimTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) | Def::Local(..) | Def::Upvar(..) => {} - Def::Ctor(hir::CtorOf::Variant, ctor_def_id, ..) => { + Def::Ctor(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); diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index a60a145dd2161..f92331b35d847 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -9,7 +9,7 @@ pub use self::MatchMode::*; use self::TrackMatchMode::*; use self::OverloadedCallType::*; -use crate::hir::def::Def; +use crate::hir::def::{CtorOf, Def}; use crate::hir::def_id::DefId; use crate::infer::InferCtxt; use crate::middle::mem_categorization as mc; @@ -902,7 +902,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { }; let def = mc.tables.qpath_def(qpath, pat.hir_id); match def { - Def::Ctor(hir::CtorOf::Variant, variant_ctor_did, ..) => { + Def::Ctor(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); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index fe6667a94b815..c907cbba4fd2f 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -62,7 +62,7 @@ use crate::middle::region; use crate::hir::def_id::{DefId, LocalDefId}; use crate::hir::Node; use crate::infer::InferCtxt; -use crate::hir::def::{Def, CtorKind}; +use crate::hir::def::{CtorOf, Def, CtorKind}; use crate::ty::adjustment; use crate::ty::{self, DefIdTree, Ty, TyCtxt}; use crate::ty::fold::TypeFoldable; @@ -1274,14 +1274,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { debug!("access to unresolvable pattern {:?}", pat); return Err(()) } - Def::Ctor(hir::CtorOf::Variant, variant_ctor_did, CtorKind::Fn) => { + Def::Ctor(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::Ctor(hir::CtorOf::Struct, _, CtorKind::Fn) | Def::SelfCtor(..) => { + Def::Ctor(CtorOf::Struct, _, CtorKind::Fn) | Def::SelfCtor(..) => { let ty = self.pat_ty_unadjusted(&pat)?; match ty.sty { ty::Adt(adt_def, _) => { @@ -1316,7 +1316,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { debug!("access to unresolvable pattern {:?}", pat); return Err(()) } - Def::Ctor(hir::CtorOf::Variant, variant_ctor_did, _) => { + Def::Ctor(CtorOf::Variant, variant_ctor_did, _) => { let variant_did = self.tcx.parent(variant_ctor_did).unwrap(); self.cat_downcast_if_needed(pat, cmt, variant_did) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 880f75ab9ddba..f32b290a7e6bf 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -6,7 +6,7 @@ pub use self::fold::TypeFoldable; 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::{Def, CtorOf, CtorKind, ExportMap}; use crate::hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_data_structures::svh::Svh; use rustc_macros::HashStable; @@ -2941,12 +2941,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { Def::Struct(did) | Def::Union(did) => { self.adt_def(did).non_enum_variant() } - Def::Ctor(hir::CtorOf::Variant, variant_ctor_did, ..) => { + Def::Ctor(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, ..) => { + Def::Ctor(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() } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 32aa75166aec0..ecce27f4969d6 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -8,7 +8,7 @@ use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions}; use rustc::hir; use rustc::middle::cstore::LinkagePreference; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; -use rustc::hir::def::{self, Def, CtorKind}; +use rustc::hir::def::{self, Def, CtorOf, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId}; use rustc::hir::map::definitions::DefPathTable; @@ -817,7 +817,7 @@ impl<'a, 'tcx> CrateMetadata { 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::Struct, ctor_def_id, ctor_kind); + hir::def::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 }); } @@ -829,7 +829,7 @@ impl<'a, 'tcx> CrateMetadata { // error will be reported on any use of such resolution anyway. let ctor_def_id = self.get_ctor_def_id(child_index).unwrap_or(def_id); let ctor_kind = self.get_ctor_kind(child_index); - let ctor_def = Def::Ctor(hir::CtorOf::Variant, ctor_def_id, ctor_kind); + let ctor_def = Def::Ctor(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 }); } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 27dba512dfb58..805d386b190be 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -4,7 +4,7 @@ use crate::hair::cx::block; use crate::hair::cx::to_ref::ToRef; use crate::hair::util::UserAnnotatedTyHelpers; use rustc_data_structures::indexed_vec::Idx; -use rustc::hir::def::{Def, CtorKind}; +use rustc::hir::def::{CtorOf, Def, CtorKind}; use rustc::mir::interpret::{GlobalId, ErrorHandled, ConstValue}; use rustc::ty::{self, AdtKind, Ty}; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability}; @@ -675,7 +675,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, .ty_adt_def() .and_then(|adt_def| { match def { - Def::Ctor(hir::CtorOf::Variant, variant_ctor_id, CtorKind::Const) => { + Def::Ctor(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; diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 2f1c542b4737c..83a281ac7a791 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -18,7 +18,7 @@ use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTyp use rustc::ty::subst::{SubstsRef, Kind}; use rustc::ty::layout::VariantIdx; use rustc::hir::{self, PatKind, RangeEnd}; -use rustc::hir::def::{Def, CtorKind}; +use rustc::hir::def::{CtorOf, Def, CtorKind}; use rustc::hir::pat_util::EnumerateAndAdjustIterator; use rustc_data_structures::indexed_vec::Idx; @@ -734,7 +734,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { subpatterns: Vec>, ) -> PatternKind<'tcx> { let def = match def { - Def::Ctor(hir::CtorOf::Variant, variant_ctor_id, ..) => { + Def::Ctor(CtorOf::Variant, variant_ctor_id, ..) => { let variant_id = self.tcx.parent(variant_ctor_id).unwrap(); Def::Variant(variant_id) }, @@ -765,7 +765,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } } - Def::Struct(..) | Def::Ctor(hir::CtorOf::Struct, ..) | Def::Union(..) | + Def::Struct(..) | Def::Ctor(CtorOf::Struct, ..) | Def::Union(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => { PatternKind::Leaf { subpatterns } } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 0cb6872ce7654..a62df699e050b 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::{self, def::*}; +use rustc::hir::def::*; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::ty; use rustc::middle::cstore::CrateStore; @@ -533,7 +533,7 @@ impl<'a> Resolver<'a> { // If this is a tuple or unit struct, define a name // in the value namespace as well. if let Some(ctor_node_id) = struct_def.ctor_id() { - let ctor_def = Def::Ctor(hir::CtorOf::Struct, + let ctor_def = Def::Ctor(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)); @@ -596,7 +596,7 @@ impl<'a> Resolver<'a> { let ctor_node_id = variant.node.data.ctor_id().unwrap_or(variant.node.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); + let ctor_def = Def::Ctor(CtorOf::Variant, ctor_def_id, ctor_kind); self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion)); } @@ -654,10 +654,10 @@ impl<'a> Resolver<'a> { self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion)); } Def::Fn(..) | Def::Static(..) | Def::Const(..) | - Def::Ctor(hir::CtorOf::Variant, ..) => { + Def::Ctor(CtorOf::Variant, ..) => { self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); } - Def::Ctor(hir::CtorOf::Struct, def_id, ..) => { + Def::Ctor(CtorOf::Struct, def_id, ..) => { self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); if let Some(struct_def_id) = diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e421a9edf8927..5021353b7dff8 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1360,7 +1360,7 @@ impl<'a> NameBinding<'a> { fn is_variant(&self) -> bool { match self.kind { NameBindingKind::Def(Def::Variant(..), _) | - NameBindingKind::Def(Def::Ctor(hir::CtorOf::Variant, ..), _) => true, + NameBindingKind::Def(Def::Ctor(CtorOf::Variant, ..), _) => true, _ => false, } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index de9a4b92c820d..96a0b364678c3 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -14,7 +14,7 @@ mod span_utils; mod sig; use rustc::hir; -use rustc::hir::def::Def as HirDef; +use rustc::hir::def::{CtorOf, Def as HirDef}; use rustc::hir::Node; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::middle::privacy::AccessLevels; @@ -757,7 +757,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ref_id: id_from_def_id(def_id), }) } - HirDef::Ctor(hir::CtorOf::Struct, def_id, _) => { + HirDef::Ctor(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. diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 32986014282a5..3d289a5c48df8 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -4,7 +4,7 @@ use errors::{Applicability, DiagnosticId}; use crate::hir::{self, GenericArg, GenericArgs, ExprKind}; -use crate::hir::def::Def; +use crate::hir::def::{CtorOf, Def}; use crate::hir::def_id::DefId; use crate::hir::HirVec; use crate::lint; @@ -1596,7 +1596,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { match def { // Case 1. Reference to a struct constructor. - Def::Ctor(hir::CtorOf::Struct, def_id, ..) | + Def::Ctor(CtorOf::Struct, def_id, ..) | Def::SelfCtor(.., def_id) => { // Everything but the final segment should have no // parameters at all. @@ -1608,7 +1608,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } // Case 2. Reference to a variant constructor. - Def::Ctor(hir::CtorOf::Variant, def_id, ..) | Def::Variant(def_id, ..) => { + Def::Ctor(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()); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 26024ece05427..5c6bbe2dee5af 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -15,7 +15,7 @@ use crate::namespace::Namespace; use errors::{Applicability, DiagnosticBuilder}; use rustc_data_structures::sync::Lrc; use rustc::hir; -use rustc::hir::def::Def; +use rustc::hir::def::{CtorOf, Def}; use rustc::hir::def_id::DefId; use rustc::traits; use rustc::ty::subst::{InternalSubsts, SubstsRef}; @@ -422,8 +422,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // them as well. It's ok to use the variant's id as a ctor id since an // error will be reported on any use of such resolution anyway. let ctor_def_id = variant_def.ctor_def_id.unwrap_or(variant_def.def_id); - let def = Def::Ctor(hir::CtorOf::Variant, ctor_def_id, variant_def.ctor_kind); - + let def = Def::Ctor(CtorOf::Variant, ctor_def_id, variant_def.ctor_kind); 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 f4f17e1dcc519..1c3c0f479f699 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -86,7 +86,7 @@ mod op; use crate::astconv::{AstConv, PathSeg}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use rustc::hir::{self, ExprKind, GenericArg, ItemKind, Node, PatKind, QPath}; -use rustc::hir::def::{CtorKind, Def}; +use rustc::hir::def::{CtorOf, CtorKind, Def}; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -5345,7 +5345,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Some(adt_def) if adt_def.has_ctor() => { let variant = adt_def.non_enum_variant(); let ctor_def_id = variant.ctor_def_id.unwrap(); - let def = Def::Ctor(hir::CtorOf::Struct, ctor_def_id, variant.ctor_kind); + let def = Def::Ctor(CtorOf::Struct, ctor_def_id, variant.ctor_kind); (def, ctor_def_id, tcx.type_of(ctor_def_id)) } _ => { @@ -5418,7 +5418,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::Ctor(hir::CtorOf::Variant, _, _) => { + Def::Ctor(CtorOf::Variant, _, _) => { if let Some(self_ty) = self_ty { let adt_def = self_ty.ty_adt_def().unwrap(); user_self_ty = Some(UserSelfTy { From 23cae1d3f06ccb339f2f780e63b6d6d5c1c6a9da Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 24 Mar 2019 19:16:44 +0100 Subject: [PATCH 9/9] Re-order fields in `Def::Ctor`. This commit moves the `DefId` field of `Def::Ctor` to be the first field. --- src/librustc/hir/def.rs | 16 ++++++++-------- src/librustc/hir/map/mod.rs | 2 +- src/librustc/hir/pat_util.rs | 2 +- src/librustc/middle/dead.rs | 2 +- src/librustc/middle/expr_use_visitor.rs | 2 +- src/librustc/middle/mem_categorization.rs | 6 +++--- src/librustc/ty/mod.rs | 6 +++--- src/librustc_metadata/decoder.rs | 5 ++--- src/librustc_mir/hair/cx/expr.rs | 6 +++--- src/librustc_mir/hair/pattern/mod.rs | 4 ++-- src/librustc_resolve/build_reduced_graph.rs | 10 +++++----- src/librustc_resolve/lib.rs | 4 ++-- src/librustc_save_analysis/lib.rs | 2 +- src/librustc_typeck/astconv.rs | 4 ++-- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/mod.rs | 4 ++-- 16 files changed, 38 insertions(+), 39 deletions(-) diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index e30d4a1a648e1..3cc23ccdb642c 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -73,7 +73,7 @@ pub enum Def { ConstParam(DefId), Static(DefId, bool /* is_mutbl */), /// `DefId` refers to the struct or enum variant's constructor. - Ctor(CtorOf, DefId, CtorKind), + Ctor(DefId, CtorOf, CtorKind), SelfCtor(DefId /* impl */), // `DefId` refers to the impl Method(DefId), AssociatedConst(DefId), @@ -276,7 +276,7 @@ impl Def { pub fn opt_def_id(&self) -> Option { match *self { Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) | - Def::Variant(id) | Def::Ctor(_, 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::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) | @@ -315,13 +315,13 @@ impl Def { Def::Static(..) => "static", Def::Enum(..) => "enum", Def::Variant(..) => "variant", - Def::Ctor(CtorOf::Variant, _, CtorKind::Fn) => "tuple variant", - Def::Ctor(CtorOf::Variant, _, CtorKind::Const) => "unit variant", - Def::Ctor(CtorOf::Variant, _, CtorKind::Fictive) => "struct variant", + Def::Ctor(_, CtorOf::Variant, CtorKind::Fn) => "tuple variant", + Def::Ctor(_, CtorOf::Variant, CtorKind::Const) => "unit variant", + Def::Ctor(_, CtorOf::Variant, CtorKind::Fictive) => "struct variant", Def::Struct(..) => "struct", - Def::Ctor(CtorOf::Struct, _, CtorKind::Fn) => "tuple struct", - Def::Ctor(CtorOf::Struct, _, CtorKind::Const) => "unit struct", - Def::Ctor(CtorOf::Struct, _, CtorKind::Fictive) => + Def::Ctor(_, CtorOf::Struct, CtorKind::Fn) => "tuple struct", + Def::Ctor(_, CtorOf::Struct, CtorKind::Const) => "unit struct", + Def::Ctor(_, CtorOf::Struct, CtorKind::Fictive) => bug!("impossible struct constructor"), Def::Existential(..) => "existential type", Def::TyAlias(..) => "type alias", diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index b94ccd90abdad..d810a9310c55f 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -377,7 +377,7 @@ impl<'hir> Map<'hir> { }; 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))) + .map(|def_id| Def::Ctor(def_id, ctor_of, def::CtorKind::from_hir(variant_data))) } Node::AnonConst(_) | Node::Field(_) | diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index bce559b17fa00..e7eda5aab133f 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -126,7 +126,7 @@ impl hir::Pat { PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => { match path.def { Def::Variant(id) => variants.push(id), - Def::Ctor(CtorOf::Variant, id, _) => variants.push(id), + Def::Ctor(id, CtorOf::Variant, ..) => variants.push(id), _ => () } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index da62423000261..f12367a89bbf3 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -76,7 +76,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { _ if self.in_pat => (), Def::PrimTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) | Def::Local(..) | Def::Upvar(..) => {} - Def::Ctor(CtorOf::Variant, ctor_def_id, ..) => { + Def::Ctor(ctor_def_id, CtorOf::Variant, ..) => { 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); diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index f92331b35d847..6c8d9fe29d7a0 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -902,7 +902,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { }; let def = mc.tables.qpath_def(qpath, pat.hir_id); match def { - Def::Ctor(CtorOf::Variant, variant_ctor_did, ..) => { + Def::Ctor(variant_ctor_did, CtorOf::Variant, ..) => { let variant_did = mc.tcx.parent(variant_ctor_did).unwrap(); let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index c907cbba4fd2f..4b169dea06c7c 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -1274,14 +1274,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { debug!("access to unresolvable pattern {:?}", pat); return Err(()) } - Def::Ctor(CtorOf::Variant, variant_ctor_did, CtorKind::Fn) => { + Def::Ctor(variant_ctor_did, CtorOf::Variant, 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::Ctor(CtorOf::Struct, _, CtorKind::Fn) | Def::SelfCtor(..) => { + Def::Ctor(_, CtorOf::Struct, CtorKind::Fn) | Def::SelfCtor(..) => { let ty = self.pat_ty_unadjusted(&pat)?; match ty.sty { ty::Adt(adt_def, _) => { @@ -1316,7 +1316,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { debug!("access to unresolvable pattern {:?}", pat); return Err(()) } - Def::Ctor(CtorOf::Variant, variant_ctor_did, _) => { + Def::Ctor(variant_ctor_did, CtorOf::Variant, _) => { let variant_did = self.tcx.parent(variant_ctor_did).unwrap(); self.cat_downcast_if_needed(pat, cmt, variant_did) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f32b290a7e6bf..f0045136f41bf 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2322,7 +2322,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { pub fn variant_of_def(&self, def: Def) -> &VariantDef { match def { Def::Variant(vid) => self.variant_with_id(vid), - Def::Ctor(_, cid, ..) => self.variant_with_ctor_id(cid), + Def::Ctor(cid, ..) => self.variant_with_ctor_id(cid), Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => self.non_enum_variant(), @@ -2941,12 +2941,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { Def::Struct(did) | Def::Union(did) => { self.adt_def(did).non_enum_variant() } - Def::Ctor(CtorOf::Variant, variant_ctor_did, ..) => { + Def::Ctor(variant_ctor_did, CtorOf::Variant, ..) => { 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(CtorOf::Struct, ctor_did, ..) => { + Def::Ctor(ctor_did, CtorOf::Struct, ..) => { let struct_did = self.parent(ctor_did).expect("struct ctor has no parent"); self.adt_def(struct_did).non_enum_variant() } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ecce27f4969d6..fb519407398fe 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -816,8 +816,7 @@ impl<'a, 'tcx> CrateMetadata { Def::Struct(..) => { 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::def::CtorOf::Struct, ctor_def_id, ctor_kind); + let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Struct, ctor_kind); let vis = self.get_visibility(ctor_def_id.index); callback(def::Export { def: ctor_def, vis, ident, span }); } @@ -829,7 +828,7 @@ impl<'a, 'tcx> CrateMetadata { // error will be reported on any use of such resolution anyway. let ctor_def_id = self.get_ctor_def_id(child_index).unwrap_or(def_id); let ctor_kind = self.get_ctor_kind(child_index); - let ctor_def = Def::Ctor(CtorOf::Variant, ctor_def_id, ctor_kind); + let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Variant, ctor_kind); let vis = self.get_visibility(ctor_def_id.index); callback(def::Export { def: ctor_def, ident, vis, span }); } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 805d386b190be..2ca44ecaba220 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -261,7 +261,7 @@ 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::Ctor(_, ctor_id, CtorKind::Fn) => + Def::Ctor(ctor_id, _, CtorKind::Fn) => Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id))), Def::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))), _ => None, @@ -675,7 +675,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, .ty_adt_def() .and_then(|adt_def| { match def { - Def::Ctor(CtorOf::Variant, variant_ctor_id, CtorKind::Const) => { + Def::Ctor(variant_ctor_id, CtorOf::Variant, 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; @@ -951,7 +951,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } }, - Def::Ctor(_, 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); diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 83a281ac7a791..6c532fce57f0e 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -734,7 +734,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { subpatterns: Vec>, ) -> PatternKind<'tcx> { let def = match def { - Def::Ctor(CtorOf::Variant, variant_ctor_id, ..) => { + Def::Ctor(variant_ctor_id, CtorOf::Variant, ..) => { let variant_id = self.tcx.parent(variant_ctor_id).unwrap(); Def::Variant(variant_id) }, @@ -765,7 +765,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } } - Def::Struct(..) | Def::Ctor(CtorOf::Struct, ..) | Def::Union(..) | + Def::Struct(..) | Def::Ctor(_, CtorOf::Struct, ..) | Def::Union(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => { PatternKind::Leaf { subpatterns } } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index a62df699e050b..80cb14deac49a 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -533,8 +533,8 @@ impl<'a> Resolver<'a> { // If this is a tuple or unit struct, define a name // in the value namespace as well. if let Some(ctor_node_id) = struct_def.ctor_id() { - let ctor_def = Def::Ctor(CtorOf::Struct, - self.definitions.local_def_id(ctor_node_id), + let ctor_def = Def::Ctor(self.definitions.local_def_id(ctor_node_id), + CtorOf::Struct, 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)); @@ -596,7 +596,7 @@ impl<'a> Resolver<'a> { let ctor_node_id = variant.node.data.ctor_id().unwrap_or(variant.node.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(CtorOf::Variant, ctor_def_id, ctor_kind); + let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Variant, ctor_kind); self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion)); } @@ -654,10 +654,10 @@ impl<'a> Resolver<'a> { self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion)); } Def::Fn(..) | Def::Static(..) | Def::Const(..) | - Def::Ctor(CtorOf::Variant, ..) => { + Def::Ctor(_, CtorOf::Variant, ..) => { self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); } - Def::Ctor(CtorOf::Struct, def_id, ..) => { + Def::Ctor(def_id, CtorOf::Struct, ..) => { self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); if let Some(struct_def_id) = diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 5021353b7dff8..a2b052044ce74 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1360,7 +1360,7 @@ impl<'a> NameBinding<'a> { fn is_variant(&self) -> bool { match self.kind { NameBindingKind::Def(Def::Variant(..), _) | - NameBindingKind::Def(Def::Ctor(CtorOf::Variant, ..), _) => true, + NameBindingKind::Def(Def::Ctor(_, CtorOf::Variant, ..), _) => true, _ => false, } } @@ -4452,7 +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::Ctor(_, did, _) => self.parent(did), + Def::Ctor(did, ..) => self.parent(did), _ => def.opt_def_id(), }; candidates.push(ImportSuggestion { did, path }); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 96a0b364678c3..828ef802dd714 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -757,7 +757,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { ref_id: id_from_def_id(def_id), }) } - HirDef::Ctor(CtorOf::Struct, def_id, _) => { + HirDef::Ctor(def_id, CtorOf::Struct, ..) => { // 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. diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 3d289a5c48df8..3e61b175b76e0 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1596,7 +1596,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { match def { // Case 1. Reference to a struct constructor. - Def::Ctor(CtorOf::Struct, def_id, ..) | + Def::Ctor(def_id, CtorOf::Struct, ..) | Def::SelfCtor(.., def_id) => { // Everything but the final segment should have no // parameters at all. @@ -1608,7 +1608,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } // Case 2. Reference to a variant constructor. - Def::Ctor(CtorOf::Variant, def_id, ..) | Def::Variant(def_id, ..) => { + Def::Ctor(def_id, CtorOf::Variant, ..) | 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()); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 5c6bbe2dee5af..34a24308e491a 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -422,7 +422,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // them as well. It's ok to use the variant's id as a ctor id since an // error will be reported on any use of such resolution anyway. let ctor_def_id = variant_def.ctor_def_id.unwrap_or(variant_def.def_id); - let def = Def::Ctor(CtorOf::Variant, ctor_def_id, variant_def.ctor_kind); + let def = Def::Ctor(ctor_def_id, CtorOf::Variant, variant_def.ctor_kind); 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 1c3c0f479f699..94f76b03a643c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5345,7 +5345,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Some(adt_def) if adt_def.has_ctor() => { let variant = adt_def.non_enum_variant(); let ctor_def_id = variant.ctor_def_id.unwrap(); - let def = Def::Ctor(CtorOf::Struct, ctor_def_id, variant.ctor_kind); + let def = Def::Ctor(ctor_def_id, CtorOf::Struct, variant.ctor_kind); (def, ctor_def_id, tcx.type_of(ctor_def_id)) } _ => { @@ -5418,7 +5418,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::Ctor(CtorOf::Variant, _, _) => { + Def::Ctor(_, CtorOf::Variant, _) => { if let Some(self_ty) = self_ty { let adt_def = self_ty.ty_adt_def().unwrap(); user_self_ty = Some(UserSelfTy {