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:
commit
3752b3d3a5
@ -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",
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
},
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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}}",
|
||||
};
|
||||
|
@ -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(¶m.attrs[..]),
|
||||
// unit/tuple structs take the attributes straight from
|
||||
// the struct definition.
|
||||
Some(Node::StructCtor(_)) => return self.attrs(self.get_parent(id)),
|
||||
// Unit/tuple structs/variants take the attributes straight from
|
||||
// the struct/variant definition.
|
||||
Some(Node::Ctor(..)) => return self.attrs(self.get_parent(id)),
|
||||
_ => None
|
||||
};
|
||||
attrs.unwrap_or(&[])
|
||||
@ -1068,7 +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)
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
})
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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(_) => {}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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(())
|
||||
})?;
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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>,
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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));
|
||||
})
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
});
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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), .. })
|
||||
|
@ -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![],
|
||||
|
@ -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 } => {
|
||||
|
@ -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 }
|
||||
}
|
||||
|
@ -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)
|
||||
};
|
||||
|
@ -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 ")?,
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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) => {
|
||||
|
@ -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;
|
||||
|
@ -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) =
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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 });
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -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(..) |
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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 == "" {
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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(
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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>,
|
||||
|
@ -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))
|
||||
}
|
||||
}),
|
||||
|
@ -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,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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![]);
|
||||
|
||||
|
@ -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()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user