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 | 65 ++++- 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 | 137 +++++----- 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 b45fc3ffd82f..87a6065bb75e 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 977830315e23..bce528189ad1 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 2251e67233c5..8db90035c8e0 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 e88f9e60702f..e7cd8f113539 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 12760f8b9828..2c92d907201d 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 dca4ce4aef81..dc23b55c1fcb 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 3e8da882eed1..ce0246dec718 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 823de08874e6..6ce7c347c997 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 18a3d6708db6..b859a0f389ed 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 9761ee313533..94f1d9c27100 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 03ed62f2a0d6..e96fe3d3b774 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 ccec4bd14326..786d339e876c 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 8ada67efaafd..a60a145dd216 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 b36d2a57cb3b..aa582d48bb66 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 a7294dbf07c0..b57f96f2d469 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 72c90b258608..772c6ab47454 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 9f2027e7d056..b54b92b798ef 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 f5f2ec38bdf2..ef232c06921d 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 995e85fc5f4d..84ce826c6a58 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 91b84b68802b..0de91af84604 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -8,7 +8,6 @@ use crate::hir::{map as hir_map, FreevarMap, GlobMap, TraitMap}; use crate::hir::{HirId, Node}; use crate::hir::def::{Def, CtorKind, ExportMap}; use crate::hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use crate::hir::map::DefPathData; use rustc_data_structures::svh::Svh; use rustc_macros::HashStable; use crate::ich::Fingerprint; @@ -1775,12 +1774,19 @@ bitflags! { #[derive(HashStable)] pub struct AdtFlags: u32 { const NO_ADT_FLAGS = 0; + /// Indicates whether the ADT is an enum. const IS_ENUM = 1 << 0; + /// Indicates whether the ADT is a union. const IS_UNION = 1 << 1; + /// Indicates whether the ADT is a struct. const IS_STRUCT = 1 << 2; + /// Indicates whether the ADT is a struct and has a constructor. const HAS_CTOR = 1 << 3; + /// Indicates whether the type is a `PhantomData`. const IS_PHANTOM_DATA = 1 << 4; + /// Indicates whether the type has a `#[fundamental]` attribute. const IS_FUNDAMENTAL = 1 << 5; + /// Indicates whether the type is a `Box`. const IS_BOX = 1 << 6; /// Indicates whether the type is an `Arc`. const IS_ARC = 1 << 7; @@ -1801,77 +1807,149 @@ bitflags! { } } +/// Definition of a variant -- a struct's fields or a enum variant. #[derive(Debug)] pub struct VariantDef { - /// The variant's `DefId`. If this is a tuple-like struct, - /// this is the `DefId` of the struct's ctor. - pub did: DefId, - pub ident: Ident, // struct's name if this is a struct + /// `DefId` that identifies this enum variant. If this `VariantDef` is part of a struct or + /// union then this is `None`. + variant_did: Option, + /// `DefId` that identifies this enum variant or struct's constructor. If this is a + /// `Struct`-variant then this is `None`. + ctor_did: Option, + /// Variant or struct name. + pub ident: Ident, + /// Discriminant of this variant. pub discr: VariantDiscr, + /// Fields of this variant. pub fields: Vec, + /// Type of constructor of variant. pub ctor_kind: CtorKind, + /// `DefId` of the parent `AdtDef` representing the struct or enum. This is required as there + /// is a valid scenario where this type represents a `Struct`-struct and both `ctor_did` and + /// `variant_did` would be `None` and we would still want a way to get back to the original + /// `AdtDef`. + parent_did: DefId, + /// Flags of the variant (e.g. is field list non-exhaustive)? flags: VariantFlags, + /// Recovered? pub recovered: bool, } impl<'a, 'gcx, 'tcx> VariantDef { /// Creates a new `VariantDef`. /// - /// - `did` is the `DefId` used for the variant. - /// This is the constructor `DefId` for tuple stucts, and the variant `DefId` for everything - /// else. - /// - `attribute_def_id` is the DefId that has the variant's attributes. - /// This is the struct `DefId` for structs, and the variant `DefId` for variants. + /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef` + /// represents an enum variant). /// - /// Note that we *could* use the constructor `DefId`, because the constructor attributes - /// redirect to the base attributes, but compiling a small crate requires - /// loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any + /// `ctor_did` is the `DefId` that identifies the constructor of unit or + /// tuple-variants/structs. If this is a `struct`-variant then this should be `None`. + /// + /// `parent_did` is the `DefId` of the `AdtDef` representing the enum or struct that + /// owns this variant. It is used for checking if a struct has `#[non_exhaustive]` w/out having + /// to go through the redirect of checking the ctor's attributes - but compiling a small crate + /// requires loading the `AdtDef`s for all the structs in the universe (e.g., coherence for any /// built-in trait), and we do not want to load attributes twice. /// /// If someone speeds up attribute loading to not be a performance concern, they can /// remove this hack and use the constructor `DefId` everywhere. pub fn new( tcx: TyCtxt<'a, 'gcx, 'tcx>, - did: DefId, ident: Ident, + variant_did: Option, + ctor_did: Option, discr: VariantDiscr, fields: Vec, - adt_kind: AdtKind, ctor_kind: CtorKind, - attribute_def_id: DefId, + adt_kind: AdtKind, + parent_did: DefId, recovered: bool, ) -> Self { - debug!("VariantDef::new({:?}, {:?}, {:?}, {:?}, {:?}, {:?}, {:?})", did, ident, discr, - fields, adt_kind, ctor_kind, attribute_def_id); + debug!( + "VariantDef::new(ident = {:?}, variant_did = {:?}, ctor_did = {:?}, discr = {:?}, + fields = {:?}, ctor_kind = {:?}, adt_kind = {:?}, parent_did = {:?})", + ident, variant_did, ctor_did, discr, fields, ctor_kind, adt_kind, parent_did, + ); + let mut flags = VariantFlags::NO_VARIANT_FLAGS; - if adt_kind == AdtKind::Struct && tcx.has_attr(attribute_def_id, "non_exhaustive") { - debug!("found non-exhaustive field list for {:?}", did); + if adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, "non_exhaustive") { + debug!("found non-exhaustive field list for {:?}", parent_did); flags = flags | VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE; } + VariantDef { - did, + variant_did, + ctor_did, ident, discr, fields, ctor_kind, flags, + parent_did, recovered, } } + /// Is this field list non-exhaustive? #[inline] pub fn is_field_list_non_exhaustive(&self) -> bool { self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE) } + + /// Returns `true` if this `VariantDef` represents a enum's variant. + #[inline] + pub fn is_enum_variant(&self) -> bool { + self.variant_did.is_some() + } + + /// Returns `true` if this `VariantDef` represents a struct. + #[inline] + pub fn is_struct(&self) -> bool { + !self.is_enum_variant() + } + + /// Returns the `DefId` of this variant if this `VariantDef` represents an enum's variant, or + /// returns the `DefId` of the parent struct. + #[inline] + pub fn variant_did_or_parent_struct_did(&self) -> DefId { + self.variant_did.unwrap_or(self.parent_did) + } + + /// Returns `true` if the variant is defined in the local crate. + #[inline] + pub fn is_local(&self) -> bool { + self.variant_did_or_parent_struct_did().krate == LOCAL_CRATE + } + + /// Returns the `DefId` of this variant if this `VariantDef` represents an enum's variant or + /// panics. + #[inline] + pub fn variant_did(&self) -> DefId { + self.variant_did.expect("enum variant without a variant id") + } + + /// Returns the `DefId` of this variant's constructor if this is a unit or + /// tuple-variant/struct. + #[inline] + pub fn ctor_did(&self) -> Option { + self.ctor_did + } + + /// Returns the `AdtDef` representing the struct or enum associated with this `VariantDef`. + #[inline] + pub fn adt_def(&self, tcx: TyCtxt<'a, 'tcx, 'gcx>) -> &'tcx AdtDef { + tcx.adt_def(self.parent_did) + } } impl_stable_hash_for!(struct VariantDef { - did, + variant_did, + ctor_did, ident -> (ident.name), discr, fields, ctor_kind, flags, + parent_did, recovered }); @@ -1898,12 +1976,15 @@ pub struct FieldDef { /// The definition of an abstract data type -- a struct or enum. /// -/// These are all interned (by `intern_adt_def`) into the `adt_defs` -/// table. +/// These are all interned (by `intern_adt_def`) into the `adt_defs` table. pub struct AdtDef { + /// `DefId` of the struct, enum or union item. pub did: DefId, + /// Variants of the ADT. If this is a struct or enum, then there will be a single variant. pub variants: IndexVec, + /// Flags of the ADT (e.g. is this a struct? is this non-exhaustive?) flags: AdtFlags, + /// Repr options provided by the user. pub repr: ReprOptions, } @@ -2102,11 +2183,14 @@ impl ReprOptions { } impl<'a, 'gcx, 'tcx> AdtDef { - fn new(tcx: TyCtxt<'_, '_, '_>, - did: DefId, - kind: AdtKind, - variants: IndexVec, - repr: ReprOptions) -> Self { + /// Creates a new `AdtDef`. + fn new( + tcx: TyCtxt<'_, '_, '_>, + did: DefId, + kind: AdtKind, + variants: IndexVec, + repr: ReprOptions + ) -> Self { debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr); let mut flags = AdtFlags::NO_ADT_FLAGS; @@ -2120,13 +2204,8 @@ impl<'a, 'gcx, 'tcx> AdtDef { AdtKind::Struct => AdtFlags::IS_STRUCT, }; - if let AdtKind::Struct = kind { - let variant_def = &variants[VariantIdx::new(0)]; - let def_key = tcx.def_key(variant_def.did); - match def_key.disambiguated_data.data { - DefPathData::StructCtor => flags |= AdtFlags::HAS_CTOR, - _ => (), - } + if kind == AdtKind::Struct && variants[VariantIdx::new(0)].ctor_did.is_some() { + flags |= AdtFlags::HAS_CTOR; } let attrs = tcx.get_attrs(did); @@ -2154,21 +2233,25 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } + /// Returns `true` if this is a struct. #[inline] pub fn is_struct(&self) -> bool { self.flags.contains(AdtFlags::IS_STRUCT) } + /// Returns `true` if this is a union. #[inline] pub fn is_union(&self) -> bool { self.flags.contains(AdtFlags::IS_UNION) } + /// Returns `true` if this is a enum. #[inline] pub fn is_enum(&self) -> bool { self.flags.contains(AdtFlags::IS_ENUM) } + /// Returns `true` if the variant list of this ADT is `#[non_exhaustive]`. #[inline] pub fn is_variant_list_non_exhaustive(&self) -> bool { self.flags.contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE) @@ -2186,6 +2269,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } + /// Returns a description of this abstract data type. pub fn descr(&self) -> &'static str { match self.adt_kind() { AdtKind::Struct => "struct", @@ -2194,6 +2278,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } + /// Returns a description of a variant of this abstract data type. #[inline] pub fn variant_descr(&self) -> &'static str { match self.adt_kind() { @@ -2266,25 +2351,53 @@ impl<'a, 'gcx, 'tcx> AdtDef { self.variants.iter().all(|v| v.fields.is_empty()) } - pub fn variant_with_id(&self, vid: DefId) -> &VariantDef { + pub fn variant_with_variant_id(&self, vid: DefId) -> &VariantDef { self.variants .iter() - .find(|v| v.did == vid) - .expect("variant_with_id: unknown variant") + .find(|v| v.variant_did.map(|did| did == vid).unwrap_or(false)) + .expect("variant_with_variant_id: unknown variant") } - pub fn variant_index_with_id(&self, vid: DefId) -> VariantIdx { + pub fn variant_with_ctor_id(&self, cid: DefId) -> &VariantDef { + self.variants + .iter() + .find(|v| v.ctor_did.map(|did| did == cid).unwrap_or(false)) + .expect("variant_with_ctor_id: unknown variant") + } + + pub fn variant_index_with_variant_id(&self, vid: DefId) -> VariantIdx { self.variants .iter_enumerated() - .find(|(_, v)| v.did == vid) - .expect("variant_index_with_id: unknown variant") + .find(|(_, v)| v.variant_did.map(|did| did == vid).unwrap_or(false)) + .expect("variant_index_with_variant_id: unknown variant") + .0 + } + + pub fn variant_index_with_ctor_id(&self, cid: DefId) -> VariantIdx { + self.variants + .iter_enumerated() + .find(|(_, v)| v.ctor_did.map(|did| did == cid).unwrap_or(false)) + .expect("variant_index_with_ctor_id: unknown variant") + .0 + } + + pub fn variant_index_with_ctor_or_variant_id(&self, id: DefId) -> VariantIdx { + self.variants + .iter_enumerated() + .find(|(_, v)| { + let ctor = v.ctor_did.map(|did| did == id); + let variant = v.variant_did.map(|did| did == id); + ctor.or(variant).unwrap_or(false) + }) + .expect("variant_index_with_ctor_or_variant_id: unknown variant") .0 } pub fn variant_of_def(&self, def: Def) -> &VariantDef { match def { - Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid), - Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) | + Def::Variant(vid) => self.variant_with_variant_id(vid), + Def::Ctor(hir::CtorOf::Variant, cid, ..) => self.variant_with_ctor_id(cid), + Def::Struct(..) | Def::Ctor(..) | Def::Union(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) => self.non_enum_variant(), _ => bug!("unexpected def {:?} in variant_of_def", def) @@ -2820,7 +2933,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option { variant.fields.iter().position(|field| { - self.adjust_ident(ident, variant.did, hir::DUMMY_HIR_ID).0 == field.ident.modern() + let did = variant.variant_did.unwrap_or(variant.parent_did); + self.adjust_ident(ident, did, hir::DUMMY_HIR_ID).0 == field.ident.modern() }) } @@ -2895,16 +3009,21 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // or variant or their constructors, panics otherwise. pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef { match def { - Def::Variant(did) | Def::VariantCtor(did, ..) => { + Def::Variant(did) => { let enum_did = self.parent(did).unwrap(); - self.adt_def(enum_did).variant_with_id(did) + self.adt_def(enum_did).variant_with_variant_id(did) } Def::Struct(did) | Def::Union(did) => { self.adt_def(did).non_enum_variant() } - Def::StructCtor(ctor_did, ..) => { - let did = self.parent(ctor_did).expect("struct ctor has no parent"); - self.adt_def(did).non_enum_variant() + Def::Ctor(hir::CtorOf::Variant, variant_ctor_did, ..) => { + let variant_did = self.parent(variant_ctor_did).unwrap(); + let enum_did = self.parent(variant_did).unwrap(); + self.adt_def(enum_did).variant_with_ctor_id(variant_ctor_did) + } + Def::Ctor(hir::CtorOf::Struct, ctor_did, ..) => { + let struct_did = self.parent(ctor_did).expect("struct ctor has no parent"); + self.adt_def(struct_did).non_enum_variant() } _ => bug!("expect_variant_def used with unexpected def {:?}", def) } @@ -2912,16 +3031,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Given a `VariantDef`, returns the def-id of the `AdtDef` of which it is a part. pub fn adt_def_id_of_variant(self, variant_def: &'tcx VariantDef) -> DefId { - let def_key = self.def_key(variant_def.did); - match def_key.disambiguated_data.data { - // for enum variants and tuple structs, the def-id of the ADT itself - // is the *parent* of the variant - DefPathData::EnumVariant(..) | DefPathData::StructCtor => - DefId { krate: variant_def.did.krate, index: def_key.parent.unwrap() }, - - // otherwise, for structs and unions, they share a def-id - _ => variant_def.did, - } + variant_def.parent_did } pub fn item_name(self, id: DefId) -> InternedString { @@ -2929,16 +3039,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.original_crate_name(id.krate).as_interned_str() } else { let def_key = self.def_key(id); - // The name of a StructCtor is that of its struct parent. - if let hir_map::DefPathData::StructCtor = def_key.disambiguated_data.data { - self.item_name(DefId { - krate: id.krate, - index: def_key.parent.unwrap() - }) - } else { - def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| { + match def_key.disambiguated_data.data { + // The name of a `StructCtor` or `VariantCtor` is that of its parent. + hir_map::DefPathData::StructCtor | hir_map::DefPathData::VariantCtor => + self.item_name(DefId { + krate: id.krate, + index: def_key.parent.unwrap() + }), + _ => def_key.disambiguated_data.data.get_opt_name().unwrap_or_else(|| { bug!("item_name: no name for {:?}", self.def_path(id)); - }) + }), } } } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 7701a10d8eee..3d6a2cf9224b 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 4e1d360562d9..7e38ce6377c8 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 8153653e48b2..6d694dcfac7b 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 67a249e605ec..995532a00cd6 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 c608c03095aa..c6f7b46d3833 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 ce0618d4599e..1af59f314bc2 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 afeea9947b5e..5b6166ebeaf5 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 1138edcb3757..0283352066cb 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 b83f048114b0..eb50bd727db1 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 88d1eb2ee0be..9637a111f42a 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 8614be8d407b..8349f21cdb47 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 f1fbc80edfb4..cb25db73cd2b 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 13bcdc26a5ef..5e5e451b75bf 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 6de98675a3dc..71eb6ed7e051 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 19b5fa1bfbe5..96fdb6a43822 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 6fad4b2db971..72197d4a17aa 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -12,7 +12,7 @@ use crate::Namespace::{self, TypeNS, ValueNS, MacroNS}; use crate::{resolve_error, resolve_struct_error, ResolutionError}; use rustc::bug; -use rustc::hir::def::*; +use rustc::hir::{self, def::*}; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::ty; use rustc::middle::cstore::CrateStore; @@ -532,9 +532,10 @@ impl<'a> Resolver<'a> { // If this is a tuple or unit struct, define a name // in the value namespace as well. - if !struct_def.is_struct() { - let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()), - CtorKind::from_ast(struct_def)); + if let Some(ctor_node_id) = struct_def.ctor_id() { + let ctor_def = Def::Ctor(hir::CtorOf::Struct, + self.definitions.local_def_id(ctor_node_id), + CtorKind::from_ast(struct_def)); self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion)); self.struct_constructors.insert(def.def_id(), (ctor_def, ctor_vis)); } @@ -581,7 +582,7 @@ impl<'a> Resolver<'a> { vis: ty::Visibility, expansion: Mark) { let ident = variant.node.ident; - let def_id = self.definitions.local_def_id(variant.node.data.id()); + let def_id = self.definitions.local_def_id(variant.node.id); // Define a name in the type namespace. let def = Def::Variant(def_id); @@ -590,10 +591,22 @@ impl<'a> Resolver<'a> { // Define a constructor name in the value namespace. // Braced variants, unlike structs, generate unusable names in // value namespace, they are reserved for possible future use. - let ctor_kind = CtorKind::from_ast(&variant.node.data); - let ctor_def = Def::VariantCtor(def_id, ctor_kind); + if let Some(ctor_node_id) = variant.node.data.ctor_id() { + let ctor_def_id = self.definitions.local_def_id(ctor_node_id); + let ctor_kind = CtorKind::from_ast(&variant.node.data); + let ctor_def = Def::Ctor(hir::CtorOf::Variant, ctor_def_id, ctor_kind); - self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion)); + self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion)); + } else { + // We normally don't have a `Def::Ctor(hir::CtorOf::Variant, ..)` for + // `Struct`-variants, but we must define one for name resolution to succeed. This also + // takes place in `build_reduced_graph_for_external_crate_def`. + let def_id = self.definitions.local_def_id(variant.node.id); + let ctor_kind = CtorKind::from_ast(&variant.node.data); + let ctor_def = Def::Ctor(hir::CtorOf::Variant, def_id, ctor_kind); + + self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion)); + } } /// Constructs the reduced graph for one foreign item. @@ -645,14 +658,29 @@ impl<'a> Resolver<'a> { span); self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion)); } - Def::Variant(..) | Def::TyAlias(..) | Def::ForeignTy(..) | Def::Existential(..) | - Def::TraitAlias(..) | Def::PrimTy(..) | Def::ToolMod => { + Def::Variant(def_id) => { + self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion)); + + if hir::def::CtorKind::Fictive == self.cstore.ctor_kind_untracked(def_id) { + // We do not normally generate `Def::Ctor(hir::CtorOf::Variant, ..)` for + // `Struct`-variants. Therefore, `build_reduced_graph_for_external_crate_def` + // will not be called to define one. However, name resolution currently expects + // there to be one, so we generate one here. This is easy to solve for local + // code, see `build_reduced_graph_for_variant` for this case. + let ctor_def = Def::Ctor(hir::CtorOf::Variant, def_id, + hir::def::CtorKind::Fictive); + + let _ = self.try_define( + parent, ident, ValueNS, + (ctor_def, vis, DUMMY_SP, expansion).to_name_binding(self.arenas), + ); + } + } + Def::TyAlias(..) | Def::ForeignTy(..) | Def::Existential(..) | Def::TraitAlias(..) | + Def::PrimTy(..) | Def::ToolMod => { self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion)); } - Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => { - self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); - } - Def::StructCtor(def_id, ..) => { + Def::Ctor(hir::CtorOf::Struct, def_id, ..) => { self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); if let Some(struct_def_id) = @@ -661,6 +689,15 @@ impl<'a> Resolver<'a> { self.struct_constructors.insert(struct_def_id, (def, vis)); } } + Def::Ctor(hir::CtorOf::Variant, ..) => { + let _ = self.try_define( + parent, ident, ValueNS, + (def, vis, DUMMY_SP, expansion).to_name_binding(self.arenas), + ); + } + Def::Fn(..) | Def::Static(..) | Def::Const(..) => { + self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion)); + } Def::Trait(def_id) => { let module_kind = ModuleKind::Def(def, ident.name); let module = self.new_module(parent, diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index 828ffc6d320e..6426ca12c6c9 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 38ca5f0b6640..e421a9edf892 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 9daffd522bf2..77fe57910cb7 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 76fd8b22f745..263f5acb662f 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 7ad5b7ce8c73..de9a4b92c820 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 6e47ae6b1598..76034f32c741 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 e470748e3443..ad62d2160b1e 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 c30b9d65fec8..6d441521a9e9 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 3a7308d09172..5d10f531ced4 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 5e3ebcb3446c..f860ab649f99 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 1054619f0f80..fe17f247916b 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 c0739db3df6a..56129479f775 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -446,8 +446,8 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: hir::HirId) { tcx.predicates_of(def_id); } - if !struct_def.is_struct() { - convert_variant_ctor(tcx, struct_def.hir_id()); + if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { + convert_variant_ctor(tcx, ctor_hir_id); } } @@ -556,21 +556,24 @@ fn convert_enum_variant_types<'a, 'tcx>( // Convert the ctor, if any. This also registers the variant as // an item. - convert_variant_ctor(tcx, variant.node.data.hir_id()); + if let Some(ctor_hir_id) = variant.node.data.ctor_hir_id() { + convert_variant_ctor(tcx, ctor_hir_id); + } } } fn convert_variant<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - did: DefId, + variant_did: Option, + ctor_did: Option, ident: Ident, discr: ty::VariantDiscr, def: &hir::VariantData, adt_kind: ty::AdtKind, - attribute_def_id: DefId + parent_did: DefId ) -> ty::VariantDef { let mut seen_fields: FxHashMap = Default::default(); - let hir_id = tcx.hir().as_local_hir_id(did).unwrap(); + let hir_id = tcx.hir().as_local_hir_id(variant_did.unwrap_or(parent_did)).unwrap(); let fields = def .fields() .iter() @@ -599,17 +602,19 @@ fn convert_variant<'a, 'tcx>( }) .collect(); let recovered = match def { - hir::VariantData::Struct(_, _, r) => *r, + hir::VariantData::Struct(_, r) => *r, _ => false, }; - ty::VariantDef::new(tcx, - did, + ty::VariantDef::new( + tcx, ident, + variant_did, + ctor_did, discr, fields, - adt_kind, CtorKind::from_hir(def), - attribute_def_id, + adt_kind, + parent_did, recovered, ) } @@ -627,58 +632,52 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad let (kind, variants) = match item.node { ItemKind::Enum(ref def, _) => { let mut distance_from_explicit = 0; - ( - AdtKind::Enum, - def.variants - .iter() - .map(|v| { - let did = tcx.hir().local_def_id_from_hir_id(v.node.data.hir_id()); - let discr = if let Some(ref e) = v.node.disr_expr { - distance_from_explicit = 0; - ty::VariantDiscr::Explicit(tcx.hir().local_def_id_from_hir_id(e.hir_id)) - } else { - ty::VariantDiscr::Relative(distance_from_explicit) - }; - distance_from_explicit += 1; + let variants = def.variants + .iter() + .map(|v| { + let variant_did = Some(tcx.hir().local_def_id_from_hir_id(v.node.id)); + let ctor_did = v.node.data.ctor_hir_id() + .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id)); - convert_variant(tcx, did, v.node.ident, discr, &v.node.data, AdtKind::Enum, - did) - }) - .collect(), - ) + let discr = if let Some(ref e) = v.node.disr_expr { + distance_from_explicit = 0; + ty::VariantDiscr::Explicit(tcx.hir().local_def_id_from_hir_id(e.hir_id)) + } else { + ty::VariantDiscr::Relative(distance_from_explicit) + }; + distance_from_explicit += 1; + + convert_variant(tcx, variant_did, ctor_did, v.node.ident, discr, + &v.node.data, AdtKind::Enum, def_id) + }) + .collect(); + + (AdtKind::Enum, variants) } ItemKind::Struct(ref def, _) => { - // Use separate constructor id for unit/tuple structs and reuse did for braced structs. - let ctor_id = if !def.is_struct() { - Some(tcx.hir().local_def_id_from_hir_id(def.hir_id())) - } else { - None - }; - ( - AdtKind::Struct, - std::iter::once(convert_variant( - tcx, - ctor_id.unwrap_or(def_id), - item.ident, - ty::VariantDiscr::Relative(0), - def, - AdtKind::Struct, - def_id - )).collect(), - ) + let variant_did = None; + let ctor_did = def.ctor_hir_id() + .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id)); + + let variants = std::iter::once(convert_variant( + tcx, variant_did, ctor_did, item.ident, ty::VariantDiscr::Relative(0), def, + AdtKind::Struct, def_id, + )).collect(); + + (AdtKind::Struct, variants) } - ItemKind::Union(ref def, _) => ( - AdtKind::Union, - std::iter::once(convert_variant( - tcx, - def_id, - item.ident, - ty::VariantDiscr::Relative(0), - def, - AdtKind::Union, - def_id - )).collect(), - ), + ItemKind::Union(ref def, _) => { + let variant_did = None; + let ctor_did = def.ctor_hir_id() + .map(|hir_id| tcx.hir().local_def_id_from_hir_id(hir_id)); + + let variants = std::iter::once(convert_variant( + tcx, variant_did, ctor_did, item.ident, ty::VariantDiscr::Relative(0), def, + AdtKind::Union, def_id, + )).collect(); + + (AdtKind::Union, variants) + }, _ => bug!(), }; tcx.alloc_adt_def(def_id, kind, variants, repr) @@ -889,8 +888,8 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty let node = tcx.hir().get_by_hir_id(hir_id); let parent_def_id = match node { - Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_) - | Node::StructCtor(_) | Node::Field(_) => { + Node::ImplItem(_) | Node::TraitItem(_) | Node::Variant(_) | + Node::Ctor(..) | Node::Field(_) => { let parent_id = tcx.hir().get_parent_item(hir_id); Some(tcx.hir().local_def_id_from_hir_id(parent_id)) } @@ -1248,8 +1247,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> { ForeignItemKind::Type => tcx.mk_foreign(def_id), }, - Node::StructCtor(&ref def) - | Node::Variant(&Spanned { + Node::Ctor(_, &ref def) | Node::Variant(&Spanned { node: hir::VariantKind { data: ref def, .. }, .. }) => match *def { @@ -1627,17 +1625,12 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::PolyFnSig compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) } - StructCtor(&VariantData::Tuple(ref fields, ..)) - | Variant(&Spanned { - node: - hir::VariantKind { - data: VariantData::Tuple(ref fields, ..), - .. - }, + Ctor(_, data) | Variant(Spanned { + node: hir::VariantKind { data, .. }, .. - }) => { + }) if data.ctor_hir_id().is_some() => { let ty = tcx.type_of(tcx.hir().get_parent_did_by_hir_id(hir_id)); - let inputs = fields + let inputs = data.fields() .iter() .map(|f| tcx.type_of(tcx.hir().local_def_id_from_hir_id(f.hir_id))); ty::Binder::bind(tcx.mk_fn_sig( diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 20eae5d88351..f2406bd8540b 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 c2f79207a562..9b9a6bace96b 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 50c8d5adfa37..ac686e40076e 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 880f67281b96..5969aa758df2 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 ba4481733d59..3ebca05f7dd8 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 9c54b40b422a..7a528e50e9c3 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 7c1a61449a26..ee182237b49e 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 b4db121fb530..a7e2b2155e9f 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 2cbd2dfeb25d..c64ffb1232fb 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 7159c949513a..18173628a260 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 e95f05894491..614967bdeb44 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 5bb1d8a4b947..784d0049ac51 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 992603140541..d7a2170342d7 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 07df14ddc722..946fdc0c4694 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 ef41373d774e..29c97ed6d384 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 | 90 +++++++++++------------ src/libsyntax_ext/deriving/generic/mod.rs | 8 +- 8 files changed, 127 insertions(+), 178 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 6ce7c347c997..7895919e1507 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 bff4190ae792..cdd4043f4bc2 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()?; + 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.print_where_clause(&generics.where_clause)?; - if print_finalizer { - self.s.word(";")?; - } - 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 b85429cd3cfd..4e2aefe62316 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 3ebca05f7dd8..ddd68c483790 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 c64ffb1232fb..bcc8fdf8cd4e 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 946fdc0c4694..f5a9aded8455 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()?; + 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.print_where_clause(&generics.where_clause)?; - if print_finalizer { - self.s.word(";")?; - } - 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 7dc2d007d73d..7c47c6ff79ac 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)); + 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); + 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]); + 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)); - } + // 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 2bb98c1bf625..dc0d72a7830e 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 aa582d48bb66..fe6667a94b81 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 b54b92b798ef..d747f348ac99 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 d732f3ff0408..963b4b439f84 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 0de91af84604..10755a9c0218 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 1af59f314bc2..78a186fbb714 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 77978d7d38ff..2e4f53023f40 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 eb50bd727db1..610c63b208cb 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 9637a111f42a..303ffcb3bfb3 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 8349f21cdb47..2f1c542b4737 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 ad62d2160b1e..32986014282a 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 6d441521a9e9..d56a0dcc0446 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 5d10f531ced4..b1a249d821be 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 f860ab649f99..0060b1031a76 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 fe17f247916b..b6bfa9ce27bd 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 ddd68c483790..61dbf00a1f53 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 87a6065bb75e..6567d9e8c7a9 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 10755a9c0218..3ab3ae0c537b 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 610c63b208cb..27dba512dfb5 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 6426ca12c6c9..dbd323821949 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 d56a0dcc0446..5f46a5a16521 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 b6bfa9ce27bd..e842be0d7e1a 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 2c92d907201d..1a3bbc5ecc49 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 dc23b55c1fcb..1006d813e65e 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 84ce826c6a58..f54e69f352a4 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 3ab3ae0c537b..880f75ab9ddb 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 3d6a2cf9224b..c9a4961a8e04 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 4fb2bfb075c8..ccead14e76b2 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 0fa935199f97..ebd48f0ae1e2 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 c6f7b46d3833..0e750cd15eeb 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 c4e371d5afed..5f0892d1d46e 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 25a3160a498d..d3d6b9862770 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 e842be0d7e1a..f4f17e1dcc51 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 29c97ed6d384..606503151c98 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 0e750cd15eeb..32aa75166aec 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 72197d4a17aa..0cb6872ce765 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 0060b1031a76..26024ece0542 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 | 70 +++++++++++++++---------- src/librustc_resolve/error_reporting.rs | 3 +- src/librustc_typeck/collect.rs | 4 +- 9 files changed, 63 insertions(+), 50 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index e7cd8f113539..75d7d843dea7 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 ce0246dec718..ee3bc72632a7 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 7895919e1507..0ffbb1c8106e 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 ef232c06921d..5b5a7cc9ed85 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 7e38ce6377c8..09de907b7510 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 0283352066cb..7fe86d11c9ee 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 96fdb6a43822..bbd03e82a373 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::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"; + } + } + + return (ctor_vis, span, descr); + } 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(); - } } - - // 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::Expr(expr) => { return (ty::Visibility::Restricted( diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index dbd323821949..fc8452e49ad1 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 56129479f775..06450424776d 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 6567d9e8c7a9..e30d4a1a648e 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 ee3bc72632a7..b94ccd90abda 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 0ffbb1c8106e..1bf7eed71bf0 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 b859a0f389ed..bce559b17fa0 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 786d339e876c..da6242300026 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 a60a145dd216..f92331b35d84 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 fe6667a94b81..c907cbba4fd2 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 880f75ab9ddb..f32b290a7e6b 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 32aa75166aec..ecce27f4969d 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 27dba512dfb5..805d386b190b 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 2f1c542b4737..83a281ac7a79 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 0cb6872ce765..a62df699e050 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 e421a9edf892..5021353b7dff 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 de9a4b92c820..96a0b364678c 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 32986014282a..3d289a5c48df 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 26024ece0542..5c6bbe2dee5a 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 f4f17e1dcc51..1c3c0f479f69 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 e30d4a1a648e..3cc23ccdb642 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 b94ccd90abda..d810a9310c55 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 bce559b17fa0..e7eda5aab133 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 da6242300026..f12367a89bbf 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 f92331b35d84..6c8d9fe29d7a 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 c907cbba4fd2..4b169dea06c7 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 f32b290a7e6b..f0045136f41b 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 ecce27f4969d..fb519407398f 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 805d386b190b..2ca44ecaba22 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 83a281ac7a79..6c532fce57f0 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 a62df699e050..80cb14deac49 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 5021353b7dff..a2b052044ce7 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 96a0b364678c..828ef802dd71 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 3d289a5c48df..3e61b175b76e 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 5c6bbe2dee5a..34a24308e491 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 1c3c0f479f69..94f76b03a643 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 {