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.
This commit is contained in:
David Wood 2019-03-21 23:38:50 +01:00 committed by Vadim Petrochenkov
parent fb5ed488ff
commit 5c3d1e5d76
63 changed files with 818 additions and 520 deletions

View file

@ -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<DefId> {
match *self {
Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) |
Def::Variant(id) | Def::Ctor(_, id, ..) | Def::Enum(id) |
Def::TyAlias(id) | Def::TraitAlias(id) |
Def::AssociatedTy(id) | Def::TyParam(id) | Def::ConstParam(id) | Def::Struct(id) |
Def::StructCtor(id, ..) |
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
Def::AssociatedConst(id) | Def::Macro(id, ..) |
Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) => {
@ -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",

View file

@ -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());
}

View file

@ -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)
},
}

View file

@ -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);
});
}

View file

@ -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,

View file

@ -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}}",
};

View file

@ -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(&param.attrs[..]),
// unit/tuple structs take the attributes straight from
// the struct definition.
Some(Node::StructCtor(_)) => return self.attrs(self.get_parent(id)),
// Unit/tuple structs/variants take the attributes straight from
// the struct/variant definition.
Some(Node::Ctor(..)) => return self.attrs(self.get_parent(id)),
_ => None
};
attrs.unwrap_or(&[])
@ -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)

View file

@ -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<Attribute>,
/// 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<AnonConst>,
@ -2063,7 +2068,7 @@ pub type Variant = Spanned<VariantKind>;
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<StructField>, HirId, /* recovered */ bool),
/// Struct variant.
///
/// e.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
Struct(HirVec<StructField>, /* recovered */ bool),
/// Tuple variant.
///
/// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
Tuple(HirVec<StructField>, 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<HirId> {
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),

View file

@ -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),
_ => ()
}
}

View file

@ -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);
}

View file

@ -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);
})
}

View file

@ -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);

View file

@ -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);

View file

@ -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,

View file

@ -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(_) => {}

View file

@ -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);
}

View file

@ -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(())
})?;

View file

@ -1077,23 +1077,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
_ => ArgKind::empty()
}).collect::<Vec<ArgKind>>())
}
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::<Vec<_>>())
}
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),
}

View file

@ -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
}

View file

@ -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>,
/// `DefId` that identifies this enum variant or struct's constructor. If this is a
/// `Struct`-variant then this is `None`.
ctor_did: Option<DefId>,
/// Variant or struct name.
pub ident: Ident,
/// Discriminant of this variant.
pub discr: VariantDiscr,
/// Fields of this variant.
pub fields: Vec<FieldDef>,
/// 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<DefId>,
ctor_did: Option<DefId>,
discr: VariantDiscr,
fields: Vec<FieldDef>,
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<DefId> {
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<self::layout::VariantIdx, VariantDef>,
/// 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<VariantIdx, VariantDef>,
repr: ReprOptions) -> Self {
/// Creates a new `AdtDef`.
fn new(
tcx: TyCtxt<'_, '_, '_>,
did: DefId,
kind: AdtKind,
variants: IndexVec<VariantIdx, VariantDef>,
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<usize> {
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));
})
}),
}
}
}

View file

@ -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 <unnamed>.
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<F: fmt::Write> 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),
_ => {}
}

View file

@ -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

View file

@ -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");

View file

@ -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<def::Export> {
let mut result = vec![];
self.get_crate_data(def_id.krate)

View file

@ -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<DefId> {
pub fn get_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
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,
}

View file

@ -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<VariantIdx>))
-> Entry<'tcx> {
fn encode_enum_variant_info(
&mut self,
(enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>),
) -> 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<VariantIdx>),
) -> 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));

View file

@ -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<DefIndex>,
/// If this is unit or tuple-variant/struct, then this is the index of the ctor id.
pub ctor: Option<DefIndex>,
/// If this is a tuple struct or variant
/// ctor, this is its "function" signature.
pub ctor_sig: Option<Lazy<ty::PolyFnSig<'tcx>>>,
@ -458,7 +455,7 @@ pub struct VariantData<'tcx> {
impl_stable_hash_for!(struct VariantData<'tcx> {
ctor_kind,
discr,
struct_ctor,
ctor,
ctor_sig
});

View file

@ -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), .. })

View file

@ -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![],

View file

@ -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 } => {

View file

@ -733,8 +733,16 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
ty: Ty<'tcx>,
subpatterns: Vec<FieldPattern<'tcx>>,
) -> 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 }
}

View file

@ -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)
};

View file

@ -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 ")?,

View file

@ -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) => {

View file

@ -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;

View file

@ -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,

View file

@ -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));
}

View file

@ -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 });

View file

@ -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);
}
}
});

View file

@ -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(..) |

View file

@ -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);

View file

@ -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<NodeId>, scx: &SaveContext<'_, '_>) -> Result {
fn make(&self, offset: usize, parent_id: Option<NodeId>, 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,

View file

@ -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 {

View file

@ -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::<Vec<_>>();
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 == "" {

View file

@ -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 {

View file

@ -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);
}

View file

@ -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<ast::Name> {
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 {

View file

@ -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<DefId>,
ctor_did: Option<DefId>,
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<ast::Ident, Span> = 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(

View file

@ -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());
}
}
}

View file

@ -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()
}

View file

@ -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());
}
}
}

View file

@ -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))

View file

@ -3133,7 +3133,7 @@ impl Clean<Item> 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<Item> 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),
}
}
}

View file

@ -125,6 +125,7 @@ pub struct Enum {
pub struct Variant {
pub name: Name,
pub id: hir::HirId,
pub attrs: hir::HirVec<ast::Attribute>,
pub def: hir::VariantData,
pub stab: Option<attr::Stability>,

View file

@ -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))
}
}),

View file

@ -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,
_ => {}
}

View file

@ -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<Attribute>,
/// 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<AnonConst>,
@ -2117,23 +2122,13 @@ pub struct StructField {
pub attrs: Vec<Attribute>,
}
/// 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<StructField>, NodeId, bool),
Struct(Vec<StructField>, 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<NodeId> {
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

View file

@ -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(_) => {}
}
}

View file

@ -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,

View file

@ -450,9 +450,10 @@ pub fn noop_visit_foreign_mod<T: MutVisitor>(foreign_mod: &mut ForeignMod, vis:
}
pub fn noop_visit_variant<T: MutVisitor>(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<T: MutVisitor>(pred: &mut WherePredicate, vis:
pub fn noop_visit_variant_data<T: MutVisitor>(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),
}
}

View file

@ -6844,7 +6844,7 @@ impl<'a> Parser<'a> {
} else {
// If we see: `struct Foo<T> 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<T>;`
} 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,

View file

@ -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,

View file

@ -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