Auto merge of #59382 - davidtwco:rfc-2008-refactoring, r=petrochenkov

Separate `DefId`s for variants and their constructors

Part of #44109. Split off from #59376. See [Zulip topic](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/rfc-2008/near/132663140) for previous discussion.

r? @petrochenkov
This commit is contained in:
bors 2019-03-24 21:26:57 +00:00
commit 3752b3d3a5
73 changed files with 857 additions and 778 deletions

View File

@ -9,6 +9,15 @@ use crate::ty;
use self::Namespace::*;
/// Encodes if a `Def::Ctor` is the constructor of an enum variant or a struct.
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum CtorOf {
/// This `Def::Ctor` is a synthesized constructor of a tuple or unit struct.
Struct,
/// This `Def::Ctor` is a synthesized constructor of a tuple or unit variant.
Variant,
}
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
pub enum CtorKind {
/// Constructor function automatically created by a tuple struct/variant.
@ -37,9 +46,11 @@ pub enum NonMacroAttrKind {
pub enum Def {
// Type namespace
Mod(DefId),
Struct(DefId), // `DefId` refers to `NodeId` of the struct itself
/// `DefId` refers to the struct itself, `Def::Ctor` refers to its constructor if it exists.
Struct(DefId),
Union(DefId),
Enum(DefId),
/// `DefId` refers to the variant itself, `Def::Ctor` refers to its constructor if it exists.
Variant(DefId),
Trait(DefId),
/// `existential type Foo: Bar;`
@ -61,8 +72,8 @@ pub enum Def {
Const(DefId),
ConstParam(DefId),
Static(DefId, bool /* is_mutbl */),
StructCtor(DefId, CtorKind), // `DefId` refers to `NodeId` of the struct's constructor
VariantCtor(DefId, CtorKind), // `DefId` refers to the enum variant
/// `DefId` refers to the struct or enum variant's constructor.
Ctor(DefId, CtorOf, CtorKind),
SelfCtor(DefId /* impl */), // `DefId` refers to the impl
Method(DefId),
AssociatedConst(DefId),
@ -265,10 +276,9 @@ impl Def {
pub fn opt_def_id(&self) -> Option<DefId> {
match *self {
Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) |
Def::Variant(id) | Def::Ctor(id, ..) | Def::Enum(id) |
Def::TyAlias(id) | Def::TraitAlias(id) |
Def::AssociatedTy(id) | Def::TyParam(id) | Def::ConstParam(id) | Def::Struct(id) |
Def::StructCtor(id, ..) |
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
Def::AssociatedConst(id) | Def::Macro(id, ..) |
Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) => {
@ -303,20 +313,21 @@ impl Def {
Def::Fn(..) => "function",
Def::Mod(..) => "module",
Def::Static(..) => "static",
Def::Variant(..) => "variant",
Def::VariantCtor(.., CtorKind::Fn) => "tuple variant",
Def::VariantCtor(.., CtorKind::Const) => "unit variant",
Def::VariantCtor(.., CtorKind::Fictive) => "struct variant",
Def::Enum(..) => "enum",
Def::Variant(..) => "variant",
Def::Ctor(_, CtorOf::Variant, CtorKind::Fn) => "tuple variant",
Def::Ctor(_, CtorOf::Variant, CtorKind::Const) => "unit variant",
Def::Ctor(_, CtorOf::Variant, CtorKind::Fictive) => "struct variant",
Def::Struct(..) => "struct",
Def::Ctor(_, CtorOf::Struct, CtorKind::Fn) => "tuple struct",
Def::Ctor(_, CtorOf::Struct, CtorKind::Const) => "unit struct",
Def::Ctor(_, CtorOf::Struct, CtorKind::Fictive) =>
bug!("impossible struct constructor"),
Def::Existential(..) => "existential type",
Def::TyAlias(..) => "type alias",
Def::TraitAlias(..) => "trait alias",
Def::AssociatedTy(..) => "associated type",
Def::AssociatedExistential(..) => "associated existential type",
Def::Struct(..) => "struct",
Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
Def::StructCtor(.., CtorKind::Const) => "unit struct",
Def::StructCtor(.., CtorKind::Fictive) => bug!("impossible struct constructor"),
Def::SelfCtor(..) => "self constructor",
Def::Union(..) => "union",
Def::Trait(..) => "trait",

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,9 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
this.insert(i.span, i.hir_id, Node::Item(i));
this.with_parent(i.hir_id, |this| {
if let ItemKind::Struct(ref struct_def, _) = i.node {
// If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() {
this.insert(i.span, struct_def.hir_id(), Node::StructCtor(struct_def));
// If this is a tuple or unit-like struct, register the constructor.
if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def));
}
}
intravisit::walk_item(this, i);
@ -515,8 +515,12 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
}
fn visit_variant(&mut self, v: &'hir Variant, g: &'hir Generics, item_id: HirId) {
self.insert(v.span, v.node.data.hir_id(), Node::Variant(v));
self.with_parent(v.node.data.hir_id(), |this| {
self.insert(v.span, v.node.id, Node::Variant(v));
self.with_parent(v.node.id, |this| {
// Register the constructor of this variant.
if let Some(ctor_hir_id) = v.node.data.ctor_hir_id() {
this.insert(v.span, ctor_hir_id, Node::Ctor(&v.node.data));
}
intravisit::walk_variant(this, v, g, item_id);
});
}

View File

@ -158,12 +158,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
self.with_parent(def, |this| {
match i.node {
ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
// If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() {
this.create_def(struct_def.id(),
DefPathData::StructCtor,
REGULAR_SPACE,
i.span);
// If this is a unit or tuple-like struct, register the constructor.
if let Some(ctor_hir_id) = struct_def.ctor_id() {
this.create_def(ctor_hir_id, DefPathData::Ctor, REGULAR_SPACE, i.span);
}
}
_ => {}
@ -193,11 +190,16 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
}
fn visit_variant(&mut self, v: &'a Variant, g: &'a Generics, item_id: NodeId) {
let def = self.create_def(v.node.data.id(),
let def = self.create_def(v.node.id,
DefPathData::EnumVariant(v.node.ident.as_interned_str()),
REGULAR_SPACE,
v.span);
self.with_parent(def, |this| visit::walk_variant(this, v, g, item_id));
self.with_parent(def, |this| {
if let Some(ctor_hir_id) = v.node.data.ctor_id() {
this.create_def(ctor_hir_id, DefPathData::Ctor, REGULAR_SPACE, v.span);
}
visit::walk_variant(this, v, g, item_id)
});
}
fn visit_variant_data(&mut self, data: &'a VariantData, _: Ident,

View File

@ -366,8 +366,8 @@ pub enum DefPathData {
EnumVariant(InternedString),
/// A struct field
Field(InternedString),
/// Implicit ctor for a tuple-like struct
StructCtor,
/// Implicit ctor for a unit or tuple-like struct or enum variant.
Ctor,
/// A constant expression (see {ast,hir}::AnonConst).
AnonConst,
/// An `impl Trait` type node
@ -652,7 +652,7 @@ impl DefPathData {
CrateRoot |
Misc |
ClosureExpr |
StructCtor |
Ctor |
AnonConst |
ImplTrait => None
}
@ -683,7 +683,7 @@ impl DefPathData {
Impl => "{{impl}}",
Misc => "{{misc}}",
ClosureExpr => "{{closure}}",
StructCtor => "{{constructor}}",
Ctor => "{{constructor}}",
AnonConst => "{{constant}}",
ImplTrait => "{{opaque}}",
};

View File

@ -366,12 +366,18 @@ impl<'hir> Map<'hir> {
}
}
Node::Variant(variant) => {
let def_id = self.local_def_id_from_hir_id(variant.node.data.hir_id());
let def_id = self.local_def_id_from_hir_id(variant.node.id);
Some(Def::Variant(def_id))
}
Node::StructCtor(variant) => {
let def_id = self.local_def_id_from_hir_id(variant.hir_id());
Some(Def::StructCtor(def_id, def::CtorKind::from_hir(variant)))
Node::Ctor(variant_data) => {
let ctor_of = match self.find(self.get_parent_node(node_id)) {
Some(Node::Item(..)) => def::CtorOf::Struct,
Some(Node::Variant(..)) => def::CtorOf::Variant,
_ => unreachable!(),
};
variant_data.ctor_hir_id()
.map(|hir_id| self.local_def_id_from_hir_id(hir_id))
.map(|def_id| Def::Ctor(def_id, ctor_of, def::CtorKind::from_hir(variant_data)))
}
Node::AnonConst(_) |
Node::Field(_) |
@ -516,8 +522,7 @@ impl<'hir> Map<'hir> {
Node::AnonConst(_) => {
BodyOwnerKind::Const
}
Node::Variant(&Spanned { node: VariantKind { data: VariantData::Tuple(..), .. }, .. }) |
Node::StructCtor(..) |
Node::Ctor(..) |
Node::Item(&Item { node: ItemKind::Fn(..), .. }) |
Node::TraitItem(&TraitItem { node: TraitItemKind::Method(..), .. }) |
Node::ImplItem(&ImplItem { node: ImplItemKind::Method(..), .. }) => {
@ -948,8 +953,8 @@ impl<'hir> Map<'hir> {
_ => bug!("struct ID bound to non-struct {}", self.hir_to_string(id))
}
}
Some(Node::StructCtor(data)) => data,
Some(Node::Variant(variant)) => &variant.node.data,
Some(Node::Ctor(data)) => data,
_ => bug!("expected struct or variant, found {}", self.hir_to_string(id))
}
}
@ -993,7 +998,7 @@ impl<'hir> Map<'hir> {
Node::Lifetime(lt) => lt.name.ident().name,
Node::GenericParam(param) => param.name.ident().name,
Node::Binding(&Pat { node: PatKind::Binding(_, _, l, _), .. }) => l.name,
Node::StructCtor(_) => self.name(self.get_parent(id)),
Node::Ctor(..) => self.name(self.get_parent(id)),
_ => bug!("no name for {}", self.node_to_string(id))
}
}
@ -1019,9 +1024,9 @@ impl<'hir> Map<'hir> {
Some(Node::Expr(ref e)) => Some(&*e.attrs),
Some(Node::Stmt(ref s)) => Some(s.node.attrs()),
Some(Node::GenericParam(param)) => Some(&param.attrs[..]),
// unit/tuple structs take the attributes straight from
// the struct definition.
Some(Node::StructCtor(_)) => return self.attrs(self.get_parent(id)),
// Unit/tuple structs/variants take the attributes straight from
// the struct/variant definition.
Some(Node::Ctor(..)) => return self.attrs(self.get_parent(id)),
_ => None
};
attrs.unwrap_or(&[])
@ -1068,7 +1073,11 @@ impl<'hir> Map<'hir> {
Some(Node::Binding(pat)) => pat.span,
Some(Node::Pat(pat)) => pat.span,
Some(Node::Block(block)) => block.span,
Some(Node::StructCtor(_)) => self.expect_item(self.get_parent(id)).span,
Some(Node::Ctor(..)) => match self.find(self.get_parent_node(id)) {
Some(Node::Item(item)) => item.span,
Some(Node::Variant(variant)) => variant.span,
_ => unreachable!(),
}
Some(Node::Lifetime(lifetime)) => lifetime.span,
Some(Node::GenericParam(param)) => param.span,
Some(Node::Visibility(&Spanned {
@ -1324,7 +1333,7 @@ impl<'a> print::State<'a> {
// these cases do not carry enough information in the
// hir_map to reconstruct their full structure for pretty
// printing.
Node::StructCtor(_) => bug!("cannot print isolated StructCtor"),
Node::Ctor(..) => bug!("cannot print isolated Ctor"),
Node::Local(a) => self.print_local_decl(&a),
Node::MacroDef(_) => bug!("cannot print MacroDef"),
Node::Crate => bug!("cannot print Crate"),
@ -1443,8 +1452,8 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String {
Some(Node::Local(_)) => {
format!("local {}{}", map.node_to_pretty_string(id), id_str)
}
Some(Node::StructCtor(_)) => {
format!("struct_ctor {}{}", path_str(), id_str)
Some(Node::Ctor(..)) => {
format!("ctor {}{}", path_str(), id_str)
}
Some(Node::Lifetime(_)) => {
format!("lifetime {}{}", map.node_to_pretty_string(id), id_str)

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,57 +2175,37 @@ 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,
}
}
pub fn is_struct(&self) -> bool {
if let VariantData::Struct(..) = *self {
true
} else {
false
}
}
pub fn is_tuple(&self) -> bool {
if let VariantData::Tuple(..) = *self {
true
} else {
false
}
}
pub fn is_unit(&self) -> bool {
if let VariantData::Unit(..) = *self {
true
} else {
false
VariantData::Struct(_, _) => None,
VariantData::Tuple(_, hir_id) | VariantData::Unit(hir_id) => Some(hir_id),
}
}
}
@ -2594,8 +2579,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(&'hir VariantData),
Lifetime(&'hir Lifetime),
GenericParam(&'hir GenericParam),

View File

@ -1,4 +1,4 @@
use crate::hir::def::Def;
use crate::hir::def::{CtorOf, Def};
use crate::hir::def_id::DefId;
use crate::hir::{self, HirId, PatKind};
use syntax::ast;
@ -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(id, CtorOf::Variant, ..) => variants.push(id),
_ => ()
}
}

View File

@ -860,41 +860,44 @@ impl<'a> State<'a> {
-> io::Result<()> {
self.print_name(name)?;
self.print_generic_params(&generics.params)?;
if !struct_def.is_struct() {
if struct_def.is_tuple() {
self.popen()?;
self.commasep(Inconsistent, struct_def.fields(), |s, field| {
s.maybe_print_comment(field.span.lo())?;
s.print_outer_attributes(&field.attrs)?;
s.print_visibility(&field.vis)?;
s.print_type(&field.ty)
})?;
self.pclose()?;
match struct_def {
hir::VariantData::Tuple(..) | hir::VariantData::Unit(..) => {
if let hir::VariantData::Tuple(..) = struct_def {
self.popen()?;
self.commasep(Inconsistent, struct_def.fields(), |s, field| {
s.maybe_print_comment(field.span.lo())?;
s.print_outer_attributes(&field.attrs)?;
s.print_visibility(&field.vis)?;
s.print_type(&field.ty)
})?;
self.pclose()?;
}
self.print_where_clause(&generics.where_clause)?;
if print_finalizer {
self.s.word(";")?;
}
self.end()?;
self.end() // close the outer-box
}
self.print_where_clause(&generics.where_clause)?;
if print_finalizer {
self.s.word(";")?;
}
self.end()?;
self.end() // close the outer-box
} else {
self.print_where_clause(&generics.where_clause)?;
self.nbsp()?;
self.bopen()?;
self.hardbreak_if_not_bol()?;
for field in struct_def.fields() {
hir::VariantData::Struct(..) => {
self.print_where_clause(&generics.where_clause)?;
self.nbsp()?;
self.bopen()?;
self.hardbreak_if_not_bol()?;
self.maybe_print_comment(field.span.lo())?;
self.print_outer_attributes(&field.attrs)?;
self.print_visibility(&field.vis)?;
self.print_ident(field.ident)?;
self.word_nbsp(":")?;
self.print_type(&field.ty)?;
self.s.word(",")?;
}
self.bclose(span)
for field in struct_def.fields() {
self.hardbreak_if_not_bol()?;
self.maybe_print_comment(field.span.lo())?;
self.print_outer_attributes(&field.attrs)?;
self.print_visibility(&field.vis)?;
self.print_ident(field.ident)?;
self.word_nbsp(":")?;
self.print_type(&field.ty)?;
self.s.word(",")?;
}
self.bclose(span)
}
}
}

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

@ -7,7 +7,7 @@ use crate::hir::{self, PatKind, TyKind};
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
use crate::hir::itemlikevisit::ItemLikeVisitor;
use crate::hir::def::Def;
use crate::hir::def::{CtorOf, Def};
use crate::hir::CodegenFnAttrFlags;
use crate::hir::def_id::{DefId, LOCAL_CRATE};
use crate::lint;
@ -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(ctor_def_id, CtorOf::Variant, ..) => {
let variant_id = self.tcx.parent(ctor_def_id).unwrap();
let enum_id = self.tcx.parent(variant_id).unwrap();
self.check_def_id(enum_id);
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

@ -9,12 +9,12 @@ pub use self::MatchMode::*;
use self::TrackMatchMode::*;
use self::OverloadedCallType::*;
use crate::hir::def::Def;
use crate::hir::def::{CtorOf, Def};
use crate::hir::def_id::DefId;
use crate::infer::InferCtxt;
use crate::middle::mem_categorization as mc;
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(variant_ctor_did, CtorOf::Variant, ..) => {
let variant_did = mc.tcx.parent(variant_ctor_did).unwrap();
let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did);
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

@ -62,7 +62,7 @@ use crate::middle::region;
use crate::hir::def_id::{DefId, LocalDefId};
use crate::hir::Node;
use crate::infer::InferCtxt;
use crate::hir::def::{Def, CtorKind};
use crate::hir::def::{CtorOf, Def, CtorKind};
use crate::ty::adjustment;
use crate::ty::{self, DefIdTree, Ty, TyCtxt};
use crate::ty::fold::TypeFoldable;
@ -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(variant_ctor_did, CtorOf::Variant, CtorKind::Fn) => {
let variant_did = self.tcx.parent(variant_ctor_did).unwrap();
let enum_did = self.tcx.parent(variant_did).unwrap();
(self.cat_downcast_if_needed(pat, cmt, variant_did),
self.tcx.adt_def(enum_did)
.variant_with_ctor_id(variant_ctor_did).fields.len())
}
Def::StructCtor(_, CtorKind::Fn) | Def::SelfCtor(..) => {
Def::Ctor(_, CtorOf::Struct, CtorKind::Fn) | Def::SelfCtor(..) => {
let ty = self.pat_ty_unadjusted(&pat)?;
match ty.sty {
ty::Adt(adt_def, _) => {
@ -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(variant_ctor_did, CtorOf::Variant, _) => {
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

@ -2410,7 +2410,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
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(variant_def.def_id, 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

@ -104,33 +104,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
fn ty_inhabitedness_forest(self, ty: Ty<'tcx>) -> DefIdForest {
ty.uninhabited_from(self)
}
pub fn is_enum_variant_uninhabited_from(self,
module: DefId,
variant: &'tcx VariantDef,
substs: SubstsRef<'tcx>)
-> bool
{
self.variant_inhabitedness_forest(variant, substs).contains(self, module)
}
pub fn is_variant_uninhabited_from_all_modules(self,
variant: &'tcx VariantDef,
substs: SubstsRef<'tcx>)
-> bool
{
!self.variant_inhabitedness_forest(variant, substs).is_empty()
}
fn variant_inhabitedness_forest(self, variant: &'tcx VariantDef, substs: SubstsRef<'tcx>)
-> DefIdForest {
// Determine the ADT kind:
let adt_def_id = self.adt_def_id_of_variant(variant);
let adt_kind = self.adt_def(adt_def_id).adt_kind();
// Compute inhabitedness forest:
variant.uninhabited_from(self, substs, adt_kind)
}
}
impl<'a, 'gcx, 'tcx> AdtDef {
@ -148,7 +121,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
impl<'a, 'gcx, 'tcx> VariantDef {
/// Calculate the forest of DefIds from which this variant is visibly uninhabited.
fn uninhabited_from(
pub fn uninhabited_from(
&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
substs: SubstsRef<'tcx>,

View File

@ -150,9 +150,7 @@ impl<'tcx> InstanceDef<'tcx> {
_ => return true
};
match tcx.def_key(def_id).disambiguated_data.data {
DefPathData::StructCtor |
DefPathData::EnumVariant(..) |
DefPathData::ClosureExpr => true,
DefPathData::Ctor | DefPathData::ClosureExpr => true,
_ => false
}
}

View File

@ -6,9 +6,8 @@ pub use self::fold::TypeFoldable;
use crate::hir::{map as hir_map, FreevarMap, GlobMap, TraitMap};
use crate::hir::{HirId, Node};
use crate::hir::def::{Def, CtorKind, ExportMap};
use crate::hir::def::{Def, CtorOf, CtorKind, ExportMap};
use crate::hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use 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,55 +1807,73 @@ 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 the variant itself.
/// If this variant belongs to a struct or union, then this is a copy of its `DefId`.
pub def_id: DefId,
/// `DefId` that identifies the variant's constructor.
/// If this variant is a struct variant, then this is `None`.
pub ctor_def_id: Option<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,
/// 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_def_id: 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_def_id = {:?}, discr = {:?},
fields = {:?}, ctor_kind = {:?}, adt_kind = {:?}, parent_did = {:?})",
ident, variant_did, ctor_def_id, discr, fields, ctor_kind, adt_kind, parent_did,
);
let mut flags = VariantFlags::NO_VARIANT_FLAGS;
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,
def_id: variant_did.unwrap_or(parent_did),
ctor_def_id,
ident,
discr,
fields,
@ -1859,6 +1883,7 @@ impl<'a, 'gcx, 'tcx> VariantDef {
}
}
/// 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)
@ -1866,7 +1891,8 @@ impl<'a, 'gcx, 'tcx> VariantDef {
}
impl_stable_hash_for!(struct VariantDef {
did,
def_id,
ctor_def_id,
ident -> (ident.name),
discr,
fields,
@ -1898,12 +1924,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 +2131,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 +2152,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_def_id.is_some() {
flags |= AdtFlags::HAS_CTOR;
}
let attrs = tcx.get_attrs(did);
@ -2154,21 +2181,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 +2217,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 +2226,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() {
@ -2267,24 +2300,30 @@ impl<'a, 'gcx, 'tcx> AdtDef {
}
pub fn variant_with_id(&self, vid: DefId) -> &VariantDef {
self.variants
.iter()
.find(|v| v.did == vid)
self.variants.iter().find(|v| v.def_id == vid)
.expect("variant_with_id: unknown variant")
}
pub fn variant_with_ctor_id(&self, cid: DefId) -> &VariantDef {
self.variants.iter().find(|v| v.ctor_def_id == Some(cid))
.expect("variant_with_ctor_id: unknown variant")
}
pub fn variant_index_with_id(&self, vid: DefId) -> VariantIdx {
self.variants
.iter_enumerated()
.find(|(_, v)| v.did == vid)
.expect("variant_index_with_id: unknown variant")
.0
self.variants.iter_enumerated().find(|(_, v)| v.def_id == vid)
.expect("variant_index_with_id: unknown variant").0
}
pub fn variant_index_with_ctor_id(&self, cid: DefId) -> VariantIdx {
self.variants.iter_enumerated().find(|(_, v)| v.ctor_def_id == Some(cid))
.expect("variant_index_with_ctor_id: unknown variant").0
}
pub fn variant_of_def(&self, def: Def) -> &VariantDef {
match def {
Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
Def::Variant(vid) => self.variant_with_id(vid),
Def::Ctor(cid, ..) => self.variant_with_ctor_id(cid),
Def::Struct(..) | Def::Union(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) |
Def::SelfCtor(..) => self.non_enum_variant(),
_ => bug!("unexpected def {:?} in variant_of_def", def)
@ -2820,7 +2859,7 @@ 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()
self.adjust_ident(ident, variant.def_id, hir::DUMMY_HIR_ID).0 == field.ident.modern()
})
}
@ -2895,50 +2934,41 @@ 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)
}
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(variant_ctor_did, CtorOf::Variant, ..) => {
let variant_did = self.parent(variant_ctor_did).unwrap();
let enum_did = self.parent(variant_did).unwrap();
self.adt_def(enum_did).variant_with_ctor_id(variant_ctor_did)
}
Def::Ctor(ctor_did, CtorOf::Struct, ..) => {
let struct_did = self.parent(ctor_did).expect("struct ctor has no parent");
self.adt_def(struct_did).non_enum_variant()
}
_ => bug!("expect_variant_def used with unexpected def {:?}", def)
}
}
/// 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,
}
}
pub fn item_name(self, id: DefId) -> InternedString {
if id.index == CRATE_DEF_INDEX {
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 constructor is that of its parent.
hir_map::DefPathData::Ctor =>
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

@ -285,14 +285,18 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
let mut cur_def_key = self.tcx().def_key(def_id);
debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key);
// For a UnitStruct or TupleStruct we want the name of its parent rather than <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"),
};
// For a constructor we want the name of its parent rather than <unnamed>.
match cur_def_key.disambiguated_data.data {
DefPathData::Ctor => {
let parent = DefId {
krate: def_id.krate,
index: cur_def_key.parent
.expect("DefPathData::Ctor/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,7 +864,7 @@ impl TyCtxt<'_, '_, '_> {
DefPathData::AnonConst |
DefPathData::ConstParam(..) |
DefPathData::ClosureExpr |
DefPathData::StructCtor => Namespace::ValueNS,
DefPathData::Ctor => Namespace::ValueNS,
DefPathData::MacroDef(..) => Namespace::MacroNS,
@ -1024,7 +1028,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::Ctor => return Ok(self),
_ => {}
}

View File

@ -549,8 +549,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// Returns `true` if this `DefId` refers to the implicit constructor for
/// a tuple struct like `struct Foo(u32)`, and `false` otherwise.
pub fn is_struct_constructor(self, def_id: DefId) -> bool {
self.def_key(def_id).disambiguated_data.data == DefPathData::StructCtor
pub fn is_constructor(self, def_id: DefId) -> bool {
self.def_key(def_id).disambiguated_data.data == DefPathData::Ctor
}
/// Given the `DefId` of a fn or closure, returns the `DefId` of

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

@ -522,7 +522,7 @@ impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> {
// Skip `::{{constructor}}` on tuple/unit structs.
match disambiguated_data.data {
DefPathData::StructCtor => return Ok(self),
DefPathData::Ctor => return Ok(self),
_ => {}
}

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

@ -8,7 +8,7 @@ use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions};
use rustc::hir;
use rustc::middle::cstore::LinkagePreference;
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use rustc::hir::def::{self, Def, CtorKind};
use rustc::hir::def::{self, Def, CtorOf, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, DefIndexAddressSpace,
CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId};
use rustc::hir::map::definitions::DefPathTable;
@ -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,22 +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(ctor_def_id, CtorOf::Struct, ctor_kind);
let vis = self.get_visibility(ctor_def_id.index);
callback(def::Export { def: ctor_def, vis, ident, span });
}
}
Def::Variant(def_id) => {
// Braced variants, unlike structs, generate unusable names in
// value namespace, they are reserved for possible future use.
// It's ok to use the variant's id as a ctor id since an
// error will be reported on any use of such resolution anyway.
let ctor_def_id = self.get_ctor_def_id(child_index).unwrap_or(def_id);
let ctor_kind = self.get_ctor_kind(child_index);
let ctor_def = Def::VariantCtor(def_id, ctor_kind);
let vis = self.get_visibility(child_index);
let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Variant, ctor_kind);
let vis = self.get_visibility(ctor_def_id.index);
callback(def::Export { def: ctor_def, ident, vis, span });
}
_ => {}
@ -925,10 +931,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,
}
@ -939,11 +948,11 @@ impl<'a, 'tcx> CrateMetadata {
return Lrc::new([]);
}
// The attributes for a tuple struct are attached to the definition, not the ctor;
// The attributes for a tuple struct/variant are attached to the definition, not the ctor;
// we assume that someone passing in a tuple struct ctor is actually wanting to
// look at the definition
let def_key = self.def_key(node_id);
let item_id = if def_key.disambiguated_data.data == DefPathData::StructCtor {
let item_id = if def_key.disambiguated_data.data == DefPathData::Ctor {
def_key.parent.unwrap()
} else {
node_id

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.def_id;
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_def_id.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_def_id.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,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
let def_id = field.did;
debug!("IsolatedEncoder::encode_field({:?})", def_id);
let variant_id = tcx.hir().as_local_hir_id(variant.did).unwrap();
let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap();
let variant_data = tcx.hir().expect_variant_data(variant_id);
Entry {
@ -710,7 +758,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 +1120,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 +1139,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 +1216,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
hir::ItemKind::Enum(..) => {
let def = self.tcx.adt_def(def_id);
self.lazy_seq(def.variants.iter().map(|v| {
assert!(v.did.is_local());
v.did.index
assert!(v.def_id.is_local());
v.def_id.index
}))
}
hir::ItemKind::Struct(..) |
@ -1765,17 +1810,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.def_id,
IsolatedEncoder::encode_enum_variant_info,
(def_id, Untracked(i)));
if let Some(ctor_def_id) = variant.ctor_def_id {
self.record(ctor_def_id,
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

@ -75,8 +75,8 @@ fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> BorrowC
// Return early if we are not supposed to use MIR borrow checker for this function.
return_early = !tcx.has_attr(def_id, "rustc_mir") && !tcx.use_mir_borrowck();
if tcx.is_struct_constructor(def_id) {
// We are not borrow checking the automatically generated struct constructors
if tcx.is_constructor(def_id) {
// We are not borrow checking the automatically generated struct/variant constructors
// because we want to accept structs such as this (taken from the `linked-hash-map`
// crate):
// ```rust

View File

@ -2685,8 +2685,8 @@ impl MirPass for TypeckMir {
return;
}
if tcx.is_struct_constructor(def_id) {
// We just assume that the automatically generated struct constructors are
if tcx.is_constructor(def_id) {
// We just assume that the automatically generated struct/variant constructors are
// correct. See the comment in the `mir_borrowck` implementation for an
// explanation why we need this.
return;

View File

@ -163,7 +163,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
i == variant_index || {
self.hir.tcx().features().never_type &&
self.hir.tcx().features().exhaustive_patterns &&
self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs)
!v.uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind()).is_empty()
}
});
if irrefutable {

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

@ -4,7 +4,7 @@ use crate::hair::cx::block;
use crate::hair::cx::to_ref::ToRef;
use crate::hair::util::UserAnnotatedTyHelpers;
use rustc_data_structures::indexed_vec::Idx;
use rustc::hir::def::{Def, CtorKind};
use rustc::hir::def::{CtorOf, Def, CtorKind};
use rustc::mir::interpret::{GlobalId, ErrorHandled, ConstValue};
use rustc::ty::{self, AdtKind, Ty};
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
@ -261,10 +261,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
// Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
expr_ty.ty_adt_def().and_then(|adt_def| {
match path.def {
Def::VariantCtor(variant_id, CtorKind::Fn) => {
Some((adt_def, adt_def.variant_index_with_id(variant_id)))
}
Def::StructCtor(_, CtorKind::Fn) |
Def::Ctor(ctor_id, _, CtorKind::Fn) =>
Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id))),
Def::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))),
_ => None,
}
@ -677,8 +675,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(variant_ctor_id, CtorOf::Variant, CtorKind::Const) => {
let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id);
let (d, o) = adt_def.discriminant_def_for_variant(idx);
use rustc::ty::util::IntTypeExt;
let ty = adt_def.repr.discr_type();
@ -804,8 +802,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 +810,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 +907,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 +951,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 +962,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

@ -168,7 +168,7 @@ use super::{PatternFoldable, PatternFolder, compare_const_vals};
use rustc::hir::def_id::DefId;
use rustc::hir::RangeEnd;
use rustc::ty::{self, subst::SubstsRef, Ty, TyCtxt, TypeFoldable, Const};
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const};
use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size};
use rustc::mir::Field;
@ -399,22 +399,10 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
_ => false,
}
}
fn is_variant_uninhabited(&self,
variant: &'tcx ty::VariantDef,
substs: SubstsRef<'tcx>)
-> bool
{
if self.tcx.features().exhaustive_patterns {
self.tcx.is_enum_variant_uninhabited_from(self.module, variant, substs)
} else {
false
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Constructor<'tcx> {
enum Constructor<'tcx> {
/// The constructor of all patterns that don't vary by constructor,
/// e.g., struct patterns and fixed-length arrays.
Single,
@ -435,7 +423,7 @@ impl<'tcx> Constructor<'tcx> {
adt: &'tcx ty::AdtDef,
) -> VariantIdx {
match self {
&Variant(vid) => adt.variant_index_with_id(vid),
&Variant(id) => adt.variant_index_with_id(id),
&Single => {
assert!(!adt.is_enum());
VariantIdx::new(0)
@ -658,8 +646,11 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
}
ty::Adt(def, substs) if def.is_enum() => {
def.variants.iter()
.filter(|v| !cx.is_variant_uninhabited(v, substs))
.map(|v| Variant(v.did))
.filter(|v| {
!cx.tcx.features().exhaustive_patterns ||
!v.uninhabited_from(cx.tcx, substs, def.adt_kind()).contains(cx.tcx, cx.module)
})
.map(|v| Variant(v.def_id))
.collect()
}
ty::Char => {
@ -1307,7 +1298,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>,
PatternKind::Binding { .. } | PatternKind::Wild => None,
PatternKind::Leaf { .. } | PatternKind::Deref { .. } => Some(vec![Single]),
PatternKind::Variant { adt_def, variant_index, .. } => {
Some(vec![Variant(adt_def.variants[variant_index].did)])
Some(vec![Variant(adt_def.variants[variant_index].def_id)])
}
PatternKind::Constant { value } => Some(vec![ConstantValue(value)]),
PatternKind::Range(PatternRange { lo, hi, ty, end }) =>
@ -1742,11 +1733,9 @@ 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
}
Some(Variant(variant.def_id))
.filter(|variant_constructor| variant_constructor == constructor)
.map(|_| patterns_for_variant(subpatterns, wild_patterns))
}
PatternKind::Leaf { ref subpatterns } => {

View File

@ -18,7 +18,7 @@ use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTyp
use rustc::ty::subst::{SubstsRef, Kind};
use rustc::ty::layout::VariantIdx;
use rustc::hir::{self, PatKind, RangeEnd};
use rustc::hir::def::{Def, CtorKind};
use rustc::hir::def::{CtorOf, Def, CtorKind};
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
use rustc_data_structures::indexed_vec::Idx;
@ -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(variant_ctor_id, CtorOf::Variant, ..) => {
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() {
@ -757,7 +765,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
}
}
Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
Def::Struct(..) | Def::Ctor(_, 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

@ -661,7 +661,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
}
ItemKind::Union(ref vdata, _) => {
if !vdata.is_struct() {
if let VariantData::Tuple(..) | VariantData::Unit(..) = vdata {
self.err_handler().span_err(item.span,
"tuple and unit unions are not permitted");
}

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

@ -239,36 +239,48 @@ fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
node => bug!("unexpected node kind: {:?}", node),
}
}
Node::StructCtor(vdata) => {
let struct_hir_id = tcx.hir().get_parent_item(hir_id);
let item = match tcx.hir().get_by_hir_id(struct_hir_id) {
Node::Item(item) => item,
Node::Ctor(vdata) => {
let parent_hir_id = tcx.hir().get_parent_node_by_hir_id(hir_id);
match tcx.hir().get_by_hir_id(parent_hir_id) {
Node::Variant(..) => {
let parent_did = tcx.hir().local_def_id_from_hir_id(parent_hir_id);
return def_id_visibility(tcx, parent_did);
}
Node::Item(..) => {
let item = match tcx.hir().get_by_hir_id(parent_hir_id) {
Node::Item(item) => item,
node => bug!("unexpected node kind: {:?}", node),
};
let (mut ctor_vis, mut span, mut descr) =
(ty::Visibility::from_hir(&item.vis, parent_hir_id, tcx),
item.vis.span, item.vis.node.descr());
for field in vdata.fields() {
let field_vis = ty::Visibility::from_hir(&field.vis, hir_id, tcx);
if ctor_vis.is_at_least(field_vis, tcx) {
ctor_vis = field_vis;
span = field.vis.span;
descr = field.vis.node.descr();
}
}
// If the structure is marked as non_exhaustive then lower the
// visibility to within the crate.
if ctor_vis == ty::Visibility::Public {
let adt_def =
tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id));
if adt_def.non_enum_variant().is_field_list_non_exhaustive() {
ctor_vis =
ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
span = attr::find_by_name(&item.attrs, "non_exhaustive")
.unwrap().span;
descr = "crate-visible";
}
}
return (ctor_vis, span, descr);
}
node => bug!("unexpected node kind: {:?}", node),
};
let (mut ctor_vis, mut span, mut descr) =
(ty::Visibility::from_hir(&item.vis, struct_hir_id, tcx),
item.vis.span, item.vis.node.descr());
for field in vdata.fields() {
let field_vis = ty::Visibility::from_hir(&field.vis, hir_id, tcx);
if ctor_vis.is_at_least(field_vis, tcx) {
ctor_vis = field_vis;
span = field.vis.span;
descr = field.vis.node.descr();
}
}
// If the structure is marked as non_exhaustive then lower the
// visibility to within the crate.
if ctor_vis == ty::Visibility::Public {
let adt_def = tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id));
if adt_def.non_enum_variant().is_field_list_non_exhaustive() {
ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX));
span = attr::find_by_name(&item.attrs, "non_exhaustive").unwrap().span;
descr = "crate-visible";
}
}
return (ctor_vis, span, descr);
}
Node::Expr(expr) => {
return (ty::Visibility::Restricted(
@ -504,7 +516,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 +538,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 +639,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 +1483,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

@ -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(self.definitions.local_def_id(ctor_node_id),
CtorOf::Struct,
CtorKind::from_ast(struct_def));
self.define(parent, ident, ValueNS, (ctor_def, ctor_vis, sp, expansion));
self.struct_constructors.insert(def.def_id(), (ctor_def, ctor_vis));
}
@ -581,18 +582,21 @@ 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());
// Define a name in the type namespace.
let def_id = self.definitions.local_def_id(variant.node.id);
let def = Def::Variant(def_id);
self.define(parent, ident, TypeNS, (def, vis, variant.span, expansion));
// Define a constructor name in the value namespace.
// Braced variants, unlike structs, generate unusable names in
// value namespace, they are reserved for possible future use.
// It's ok to use the variant's id as a ctor id since an
// error will be reported on any use of such resolution anyway.
let ctor_node_id = variant.node.data.ctor_id().unwrap_or(variant.node.id);
let ctor_def_id = self.definitions.local_def_id(ctor_node_id);
let ctor_kind = CtorKind::from_ast(&variant.node.data);
let ctor_def = Def::VariantCtor(def_id, ctor_kind);
let ctor_def = Def::Ctor(ctor_def_id, CtorOf::Variant, ctor_kind);
self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion));
}
@ -649,10 +653,11 @@ impl<'a> Resolver<'a> {
Def::TraitAlias(..) | Def::PrimTy(..) | Def::ToolMod => {
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
}
Def::Fn(..) | Def::Static(..) | Def::Const(..) | Def::VariantCtor(..) => {
Def::Fn(..) | Def::Static(..) | Def::Const(..) |
Def::Ctor(_, CtorOf::Variant, ..) => {
self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion));
}
Def::StructCtor(def_id, ..) => {
Def::Ctor(def_id, CtorOf::Struct, ..) => {
self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, expansion));
if let Some(struct_def_id) =

View File

@ -2,8 +2,7 @@ use std::cmp::Reverse;
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use log::debug;
use rustc::hir::def::*;
use rustc::hir::def::Namespace::*;
use rustc::hir::def::{Def, CtorKind, Namespace::*};
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::session::config::nightly_options;
use syntax::ast::{ExprKind};
@ -417,7 +416,7 @@ impl<'a> Resolver<'a> {
}
(Def::Union(..), _) |
(Def::Variant(..), _) |
(Def::VariantCtor(_, CtorKind::Fictive), _) if ns == ValueNS => {
(Def::Ctor(_, _, 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 {
@ -1368,7 +1364,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(_, CtorOf::Variant, ..), _) => true,
_ => false,
}
}
@ -3093,16 +3089,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),
@ -4465,8 +4459,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

@ -14,7 +14,7 @@ mod span_utils;
mod sig;
use rustc::hir;
use rustc::hir::def::Def as HirDef;
use rustc::hir::def::{CtorOf, Def as HirDef};
use rustc::hir::Node;
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::middle::privacy::AccessLevels;
@ -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(def_id, CtorOf::Struct, ..) => {
// This is a reference to a tuple struct where the def_id points
// to an invisible constructor function. That is not a very useful
// def, so adjust to point to the tuple struct itself.
@ -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

@ -4,7 +4,7 @@
use errors::{Applicability, DiagnosticId};
use crate::hir::{self, GenericArg, GenericArgs, ExprKind};
use crate::hir::def::Def;
use crate::hir::def::{CtorOf, Def};
use crate::hir::def_id::DefId;
use crate::hir::HirVec;
use crate::lint;
@ -1318,10 +1318,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did)
});
if let Some(variant_def) = variant_def {
let def = Def::Variant(variant_def.did);
let def = Def::Variant(variant_def.def_id);
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(variant_def.def_id, Some(hir_ref_id), span);
return (qself_ty, def);
} else {
variant_resolution = Some(def);
@ -1596,7 +1596,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(def_id, CtorOf::Struct, ..) |
Def::SelfCtor(.., def_id) => {
// Everything but the final segment should have no
// parameters at all.
@ -1608,8 +1608,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(def_id, CtorOf::Variant, ..) | Def::Variant(def_id, ..) => {
let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap());
let (generics_def_id, index) = if let Some(adt_def) = adt_def {
debug_assert!(adt_def.is_enum());
@ -1617,6 +1616,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,14 +807,12 @@ 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(_, _, CtorKind::Fictive) |
Def::Ctor(_, _, 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::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,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
let mut inexistent_fields = vec![];
// Typecheck each field.
for &Spanned { node: ref field, span } in fields {
let ident = tcx.adjust_ident(field.ident, variant.did, self.body_id).0;
let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
let field_ty = match used_fields.entry(ident) {
Occupied(occupied) => {
struct_span_err!(tcx.sess, span, E0025,
@ -1003,13 +1000,13 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
E0026,
"{} `{}` does not have {}",
kind_name,
tcx.def_path_str(variant.did),
tcx.def_path_str(variant.def_id),
field_names);
if let Some((span, ident)) = inexistent_fields.last() {
err.span_label(*span,
format!("{} `{}` does not have {} field{}",
kind_name,
tcx.def_path_str(variant.did),
tcx.def_path_str(variant.def_id),
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.def_id);
// FIXME #56861: DRYer prelude filtering
Some(variant_path.trim_start_matches("std::prelude::v1::").to_string())
} else {

View File

@ -15,7 +15,7 @@ use crate::namespace::Namespace;
use errors::{Applicability, DiagnosticBuilder};
use rustc_data_structures::sync::Lrc;
use rustc::hir;
use rustc::hir::def::Def;
use rustc::hir::def::{CtorOf, Def};
use rustc::hir::def_id::DefId;
use rustc::traits;
use rustc::ty::subst::{InternalSubsts, SubstsRef};
@ -417,7 +417,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if let Some(variant_def) = variant_def {
check_type_alias_enum_variants_enabled(tcx, span);
let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind);
// Braced variants generate unusable names in value namespace (reserved for
// possible future use), so variants resolved as associated items may refer to
// them as well. It's ok to use the variant's id as a ctor id since an
// error will be reported on any use of such resolution anyway.
let ctor_def_id = variant_def.ctor_def_id.unwrap_or(variant_def.def_id);
let def = Def::Ctor(ctor_def_id, CtorOf::Variant, variant_def.ctor_kind);
tcx.check_stability(def.def_id(), Some(expr_id), span);
return Ok(def);
}

View File

@ -86,7 +86,7 @@ mod op;
use crate::astconv::{AstConv, PathSeg};
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use rustc::hir::{self, ExprKind, GenericArg, ItemKind, Node, PatKind, QPath};
use rustc::hir::def::{CtorKind, Def};
use rustc::hir::def::{CtorOf, CtorKind, Def};
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
@ -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)].def_id;
let variant_i_hir_id = tcx.hir().as_local_hir_id(variant_did).unwrap();
let variant_i = tcx.hir().expect_variant(variant_i_hir_id);
let i_span = match variant_i.node.disr_expr {
@ -3693,7 +3693,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.def_id.is_local() && field.vis != Visibility::Public)
{
None
} else {
Some(&field.ident.name)
@ -3705,7 +3706,7 @@ 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 def_scope = self.tcx.adjust_ident(field.ident, variant.def_id, self.body_id).1;
field.vis.is_accessible_from(def_scope, self.tcx)
})
.map(|field| field.ident.name)
@ -3823,7 +3824,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// Type-check each field.
for field in ast_fields {
let ident = tcx.adjust_ident(field.ident, variant.did, self.body_id).0;
let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) {
seen_fields.insert(ident, field.span);
self.write_field_index(field.hir_id, i);
@ -4237,7 +4238,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.set_tainted_by_errors();
tcx.types.err
}
Def::VariantCtor(_, CtorKind::Fictive) => {
Def::Ctor(_, _, CtorKind::Fictive) => {
report_unexpected_variant_def(tcx, &def, expr.span, qpath);
tcx.types.err
}
@ -5333,7 +5334,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
Some(original_span.with_lo(original_span.hi() - BytePos(1)))
}
// Rewrite `SelfCtor` to `StructCtor`
// Rewrite `SelfCtor` to `Ctor`
pub fn rewrite_self_ctor(&self, def: Def, span: Span) -> (Def, DefId, Ty<'tcx>) {
let tcx = self.tcx;
if let Def::SelfCtor(impl_def_id) = def {
@ -5343,8 +5344,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
match adt_def {
Some(adt_def) if adt_def.has_ctor() => {
let variant = adt_def.non_enum_variant();
let def = Def::StructCtor(variant.did, variant.ctor_kind);
(def, variant.did, tcx.type_of(variant.did))
let ctor_def_id = variant.ctor_def_id.unwrap();
let def = Def::Ctor(ctor_def_id, CtorOf::Struct, variant.ctor_kind);
(def, ctor_def_id, tcx.type_of(ctor_def_id))
}
_ => {
let mut err = tcx.sess.struct_span_err(span,
@ -5416,7 +5418,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let mut user_self_ty = None;
let mut is_alias_variant_ctor = false;
match def {
Def::VariantCtor(_, _) => {
Def::Ctor(_, CtorOf::Variant, _) => {
if let Some(self_ty) = self_ty {
let adt_def = self_ty.ty_adt_def().unwrap();
user_self_ty = Some(UserSelfTy {

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),
}),
@ -3171,13 +3171,13 @@ impl<'tcx> Clean<Item> for ty::VariantDef {
};
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, self.def_id),
source: cx.tcx.def_span(self.def_id).clean(cx),
visibility: Some(Inherited),
def_id: self.did,
def_id: self.def_id,
inner: VariantItem(Variant { kind }),
stability: get_stability(cx, self.did),
deprecation: get_deprecation(cx, self.did),
stability: get_stability(cx, self.def_id),
deprecation: get_deprecation(cx, self.def_id),
}
}
}
@ -3191,12 +3191,11 @@ pub enum VariantKind {
impl Clean<VariantKind> for hir::VariantData {
fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
if self.is_struct() {
VariantKind::Struct(self.clean(cx))
} else if self.is_unit() {
VariantKind::CLike
} else {
VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
match self {
hir::VariantData::Struct(..) => VariantKind::Struct(self.clean(cx)),
hir::VariantData::Tuple(..) =>
VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect()),
hir::VariantData::Unit(..) => VariantKind::CLike,
}
}
}

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,36 +2140,19 @@ 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,
}
}
pub fn is_struct(&self) -> bool {
if let VariantData::Struct(..) = *self {
true
} else {
false
}
}
pub fn is_tuple(&self) -> bool {
if let VariantData::Tuple(..) = *self {
true
} else {
false
}
}
pub fn is_unit(&self) -> bool {
if let VariantData::Unit(..) = *self {
true
} else {
false
VariantData::Struct(..) => None,
VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id),
}
}
}

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

@ -1550,44 +1550,47 @@ impl<'a> State<'a> {
print_finalizer: bool) -> io::Result<()> {
self.print_ident(ident)?;
self.print_generic_params(&generics.params)?;
if !struct_def.is_struct() {
if struct_def.is_tuple() {
self.popen()?;
self.commasep(
Inconsistent, struct_def.fields(),
|s, field| {
s.maybe_print_comment(field.span.lo())?;
s.print_outer_attributes(&field.attrs)?;
s.print_visibility(&field.vis)?;
s.print_type(&field.ty)
}
)?;
self.pclose()?;
match struct_def {
ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
if let ast::VariantData::Tuple(..) = struct_def {
self.popen()?;
self.commasep(
Inconsistent, struct_def.fields(),
|s, field| {
s.maybe_print_comment(field.span.lo())?;
s.print_outer_attributes(&field.attrs)?;
s.print_visibility(&field.vis)?;
s.print_type(&field.ty)
}
)?;
self.pclose()?;
}
self.print_where_clause(&generics.where_clause)?;
if print_finalizer {
self.s.word(";")?;
}
self.end()?;
self.end() // close the outer-box
}
self.print_where_clause(&generics.where_clause)?;
if print_finalizer {
self.s.word(";")?;
}
self.end()?;
self.end() // close the outer-box
} else {
self.print_where_clause(&generics.where_clause)?;
self.nbsp()?;
self.bopen()?;
self.hardbreak_if_not_bol()?;
for field in struct_def.fields() {
ast::VariantData::Struct(..) => {
self.print_where_clause(&generics.where_clause)?;
self.nbsp()?;
self.bopen()?;
self.hardbreak_if_not_bol()?;
self.maybe_print_comment(field.span.lo())?;
self.print_outer_attributes(&field.attrs)?;
self.print_visibility(&field.vis)?;
self.print_ident(field.ident.unwrap())?;
self.word_nbsp(":")?;
self.print_type(&field.ty)?;
self.s.word(",")?;
}
self.bclose(span)
for field in struct_def.fields() {
self.hardbreak_if_not_bol()?;
self.maybe_print_comment(field.span.lo())?;
self.print_outer_attributes(&field.attrs)?;
self.print_visibility(&field.vis)?;
self.print_ident(field.ident.unwrap())?;
self.word_nbsp(":")?;
self.print_type(&field.ty)?;
self.s.word(",")?;
}
self.bclose(span)
}
}
}
@ -3266,6 +3269,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

@ -51,9 +51,9 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
// build fmt.debug_struct(<name>).field(<fieldname>, &<fieldval>)....build()
// or fmt.debug_tuple(<name>).field(&<fieldval>)....build()
// based on the "shape".
let (ident, is_struct) = match *substr.fields {
Struct(vdata, _) => (substr.type_ident, vdata.is_struct()),
EnumMatching(_, _, v, _) => (v.node.ident, v.node.data.is_struct()),
let (ident, vdata, fields) = match substr.fields {
Struct(vdata, fields) => (substr.type_ident, *vdata, fields),
EnumMatching(_, _, v, fields) => (v.node.ident, &v.node.data, fields),
EnumNonMatchingCollapsed(..) |
StaticStruct(..) |
StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"),
@ -67,55 +67,51 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
let fmt = substr.nonself_args[0].clone();
let mut stmts = match *substr.fields {
Struct(_, ref fields) |
EnumMatching(.., ref fields) => {
let mut stmts = vec![];
if !is_struct {
// tuple struct/"normal" variant
let expr =
cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]);
stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
let mut stmts = vec![];
match vdata {
ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
// tuple struct/"normal" variant
let expr =
cx.expr_method_call(span, fmt, Ident::from_str("debug_tuple"), vec![name]);
stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
for field in fields {
// Use double indirection to make sure this works for unsized types
let field = cx.expr_addr_of(field.span, field.self_.clone());
let field = cx.expr_addr_of(field.span, field);
for field in fields {
// Use double indirection to make sure this works for unsized types
let field = cx.expr_addr_of(field.span, field.self_.clone());
let field = cx.expr_addr_of(field.span, field);
let expr = cx.expr_method_call(span,
builder_expr.clone(),
Ident::from_str("field"),
vec![field]);
let expr = cx.expr_method_call(span,
builder_expr.clone(),
Ident::from_str("field"),
vec![field]);
// Use `let _ = expr;` to avoid triggering the
// unused_results lint.
stmts.push(stmt_let_undescore(cx, span, expr));
}
} else {
// normal struct/struct variant
let expr =
cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]);
stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
for field in fields {
let name = cx.expr_lit(field.span,
ast::LitKind::Str(field.name.unwrap().name,
ast::StrStyle::Cooked));
// Use double indirection to make sure this works for unsized types
let field = cx.expr_addr_of(field.span, field.self_.clone());
let field = cx.expr_addr_of(field.span, field);
let expr = cx.expr_method_call(span,
builder_expr.clone(),
Ident::from_str("field"),
vec![name, field]);
stmts.push(stmt_let_undescore(cx, span, expr));
}
// Use `let _ = expr;` to avoid triggering the
// unused_results lint.
stmts.push(stmt_let_undescore(cx, span, expr));
}
stmts
}
_ => unreachable!(),
};
ast::VariantData::Struct(..) => {
// normal struct/struct variant
let expr =
cx.expr_method_call(span, fmt, Ident::from_str("debug_struct"), vec![name]);
stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
for field in fields {
let name = cx.expr_lit(field.span,
ast::LitKind::Str(field.name.unwrap().name,
ast::StrStyle::Cooked));
// Use double indirection to make sure this works for unsized types
let field = cx.expr_addr_of(field.span, field.self_.clone());
let field = cx.expr_addr_of(field.span, field);
let expr = cx.expr_method_call(span,
builder_expr.clone(),
Ident::from_str("field"),
vec![name, field]);
stmts.push(stmt_let_undescore(cx, span, expr));
}
}
}
let expr = cx.expr_method_call(span, builder_expr, Ident::from_str("finish"), vec![]);

View File

@ -1539,6 +1539,7 @@ impl<'a> TraitDef<'a> {
}
}
let is_tuple = if let ast::VariantData::Tuple(..) = struct_def { true } else { false };
match (just_spans.is_empty(), named_idents.is_empty()) {
(false, false) => {
cx.span_bug(self.span,
@ -1547,9 +1548,10 @@ impl<'a> TraitDef<'a> {
}
// named fields
(_, false) => Named(named_idents),
// empty structs
_ if struct_def.is_struct() => Named(named_idents),
_ => Unnamed(just_spans, struct_def.is_tuple()),
// unnamed fields
(false, _) => Unnamed(just_spans, is_tuple),
// empty
_ => Named(Vec::new()),
}
}

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-{{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-{{constructor}}.mir_map.0.mir