Skip to content

Commit

Permalink
Auto merge of #103578 - petrochenkov:nofict, r=nagisa
Browse files Browse the repository at this point in the history
Unreserve braced enum variants in value namespace

With this PR braced enum variants (`enum E { V { /*...*/ } }`) no longer take a slot in value namespace, so the special case mentioned in the note in https://github.com/rust-lang/rfcs/blob/master/text/1506-adt-kinds.md#braced-structs is removed.

Report - #103578 (comment).
  • Loading branch information
bors committed Nov 22, 2022
2 parents a78c9be + 7a5376d commit b7463e8
Show file tree
Hide file tree
Showing 71 changed files with 364 additions and 642 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2675,7 +2675,7 @@ impl VariantData {
}

/// Return the `NodeId` of this variant's constructor, if it has one.
pub fn ctor_id(&self) -> Option<NodeId> {
pub fn ctor_node_id(&self) -> Option<NodeId> {
match *self {
VariantData::Struct(..) => None,
VariantData::Tuple(_, id) | VariantData::Unit(id) => Some(id),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else {
def.non_enum_variant()
};
if !including_tuple_field.0 && variant.ctor_kind == CtorKind::Fn {
if !including_tuple_field.0 && variant.ctor_kind() == Some(CtorKind::Fn) {
return None;
}
Some(variant.fields[field.index()].name.to_string())
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
.iter()
.enumerate()
.map(|(i, f)| {
let field_name = if variant_def.ctor_kind == CtorKind::Fn {
let field_name = if variant_def.ctor_kind() == Some(CtorKind::Fn) {
// This is a tuple struct
tuple_field_name(i)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
|cx, struct_type_di_node| {
(0..variant_layout.fields.count())
.map(|field_index| {
let field_name = if variant_def.ctor_kind != CtorKind::Fn {
let field_name = if variant_def.ctor_kind() != Some(CtorKind::Fn) {
// Fields have names
Cow::from(variant_def.fields[field_index].name.as_str())
} else {
Expand Down
22 changes: 4 additions & 18 deletions compiler/rustc_hir/src/def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ pub enum CtorKind {
Fn,
/// Constructor constant automatically created by a unit struct/variant.
Const,
/// Unusable name in value namespace created by a struct variant.
Fictive,
}

/// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`.
Expand Down Expand Up @@ -132,13 +130,9 @@ impl DefKind {
DefKind::Variant => "variant",
DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant",
DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => "unit variant",
DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive) => "struct variant",
DefKind::Struct => "struct",
DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct",
DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct",
DefKind::Ctor(CtorOf::Struct, CtorKind::Fictive) => {
panic!("impossible struct constructor")
}
DefKind::OpaqueTy => "opaque type",
DefKind::ImplTraitPlaceholder => "opaque type in trait",
DefKind::TyAlias => "type alias",
Expand Down Expand Up @@ -562,19 +556,11 @@ impl<T> PerNS<Option<T>> {
}

impl CtorKind {
pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
match *vdata {
ast::VariantData::Tuple(..) => CtorKind::Fn,
ast::VariantData::Unit(..) => CtorKind::Const,
ast::VariantData::Struct(..) => CtorKind::Fictive,
}
}

pub fn from_hir(vdata: &hir::VariantData<'_>) -> CtorKind {
pub fn from_ast(vdata: &ast::VariantData) -> Option<(CtorKind, NodeId)> {
match *vdata {
hir::VariantData::Tuple(..) => CtorKind::Fn,
hir::VariantData::Unit(..) => CtorKind::Const,
hir::VariantData::Struct(..) => CtorKind::Fictive,
ast::VariantData::Tuple(_, node_id) => Some((CtorKind::Fn, node_id)),
ast::VariantData::Unit(node_id) => Some((CtorKind::Const, node_id)),
ast::VariantData::Struct(..) => None,
}
}
}
Expand Down
25 changes: 17 additions & 8 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2913,20 +2913,29 @@ impl<'hir> VariantData<'hir> {
}
}

/// Return the `LocalDefId` of this variant's constructor, if it has one.
pub fn ctor_def_id(&self) -> Option<LocalDefId> {
pub fn ctor(&self) -> Option<(CtorKind, HirId, LocalDefId)> {
match *self {
VariantData::Struct(_, _) => None,
VariantData::Tuple(_, _, def_id) | VariantData::Unit(_, def_id) => Some(def_id),
VariantData::Tuple(_, hir_id, def_id) => Some((CtorKind::Fn, hir_id, def_id)),
VariantData::Unit(hir_id, def_id) => Some((CtorKind::Const, hir_id, def_id)),
VariantData::Struct(..) => None,
}
}

#[inline]
pub fn ctor_kind(&self) -> Option<CtorKind> {
self.ctor().map(|(kind, ..)| kind)
}

/// Return the `HirId` of this variant's constructor, if it has one.
#[inline]
pub fn ctor_hir_id(&self) -> Option<HirId> {
match *self {
VariantData::Struct(_, _) => None,
VariantData::Tuple(_, hir_id, _) | VariantData::Unit(hir_id, _) => Some(hir_id),
}
self.ctor().map(|(_, hir_id, _)| hir_id)
}

/// Return the `LocalDefId` of this variant's constructor, if it has one.
#[inline]
pub fn ctor_def_id(&self) -> Option<LocalDefId> {
self.ctor().map(|(.., def_id)| def_id)
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1165,7 +1165,7 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
}

if def.repr().int.is_none() {
let is_unit = |var: &ty::VariantDef| matches!(var.ctor_kind, CtorKind::Const);
let is_unit = |var: &ty::VariantDef| matches!(var.ctor_kind(), Some(CtorKind::Const));
let has_disr = |var: &ty::VariantDef| matches!(var.discr, ty::VariantDiscr::Explicit(_));

let has_non_units = def.variants().iter().any(|var| !is_unit(var));
Expand Down
36 changes: 10 additions & 26 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
Expand Down Expand Up @@ -794,7 +793,7 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {

// Convert the ctor, if any. This also registers the variant as
// an item.
if let Some(ctor_def_id) = variant.ctor_def_id {
if let Some(ctor_def_id) = variant.ctor_def_id() {
convert_variant_ctor(tcx, ctor_def_id.expect_local());
}
}
Expand All @@ -803,7 +802,6 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
fn convert_variant(
tcx: TyCtxt<'_>,
variant_did: Option<LocalDefId>,
ctor_did: Option<LocalDefId>,
ident: Ident,
discr: ty::VariantDiscr,
def: &hir::VariantData<'_>,
Expand Down Expand Up @@ -840,10 +838,9 @@ fn convert_variant(
ty::VariantDef::new(
ident.name,
variant_did.map(LocalDefId::to_def_id),
ctor_did.map(LocalDefId::to_def_id),
def.ctor().map(|(kind, _, def_id)| (kind, def_id.to_def_id())),
discr,
fields,
CtorKind::from_hir(def),
adt_kind,
parent_did.to_def_id(),
recovered,
Expand Down Expand Up @@ -882,7 +879,6 @@ fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {
convert_variant(
tcx,
Some(v.def_id),
v.data.ctor_def_id(),
v.ident,
discr,
&v.data,
Expand All @@ -894,35 +890,23 @@ fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {

(AdtKind::Enum, variants)
}
ItemKind::Struct(ref def, _) => {
let variants = std::iter::once(convert_variant(
tcx,
None,
def.ctor_def_id(),
item.ident,
ty::VariantDiscr::Relative(0),
def,
AdtKind::Struct,
def_id,
))
.collect();

(AdtKind::Struct, variants)
}
ItemKind::Union(ref def, _) => {
ItemKind::Struct(ref def, _) | ItemKind::Union(ref def, _) => {
let adt_kind = match item.kind {
ItemKind::Struct(..) => AdtKind::Struct,
_ => AdtKind::Union,
};
let variants = std::iter::once(convert_variant(
tcx,
None,
def.ctor_def_id(),
item.ident,
ty::VariantDiscr::Relative(0),
def,
AdtKind::Union,
adt_kind,
def_id,
))
.collect();

(AdtKind::Union, variants)
(adt_kind, variants)
}
_ => bug!(),
};
Expand Down Expand Up @@ -1171,7 +1155,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
compute_sig_of_foreign_fn_decl(tcx, def_id.to_def_id(), fn_decl, abi)
}

Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor_hir_id().is_some() => {
Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
let ty = tcx.type_of(tcx.hir().get_parent_item(hir_id));
let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id));
ty::Binder::dummy(tcx.mk_fn_sig(
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/variance/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ pub fn add_constraints_from_crate<'a, 'tcx>(

let adt = tcx.adt_def(def_id);
for variant in adt.variants() {
if let Some(ctor) = variant.ctor_def_id {
constraint_cx.build_constraints_for_item(ctor.expect_local());
if let Some(ctor_def_id) = variant.ctor_def_id() {
constraint_cx.build_constraints_for_item(ctor_def_id.expect_local());
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/variance/terms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(

let adt = tcx.adt_def(def_id);
for variant in adt.variants() {
if let Some(ctor) = variant.ctor_def_id {
terms_cx.add_inferreds_for_item(ctor.expect_local());
if let Some(ctor_def_id) = variant.ctor_def_id() {
terms_cx.add_inferreds_for_item(ctor_def_id.expect_local());
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::type_error_struct;
use rustc_ast::util::parser::PREC_POSTFIX;
use rustc_errors::{struct_span_err, Applicability, Diagnostic, StashKey};
use rustc_hir as hir;
use rustc_hir::def::{self, Namespace, Res};
use rustc_hir::def::{self, CtorKind, Namespace, Res};
use rustc_hir::def_id::DefId;
use rustc_infer::{
infer,
Expand Down Expand Up @@ -595,7 +595,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
let mut unit_variant = None;
if let hir::ExprKind::Path(qpath) = &callee_expr.kind
&& let Res::Def(def::DefKind::Ctor(kind, def::CtorKind::Const), _)
&& let Res::Def(def::DefKind::Ctor(kind, CtorKind::Const), _)
= self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
// Only suggest removing parens if there are no arguments
&& arg_exprs.is_empty()
Expand Down
15 changes: 8 additions & 7 deletions compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::FnCtxt;
use rustc_ast::util::parser::PREC_POSTFIX;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::def::CtorKind;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{is_range_literal, Node};
use rustc_infer::infer::InferOk;
Expand Down Expand Up @@ -404,27 +405,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(path) = variant_path.strip_prefix("std::prelude::")
&& let Some((_, path)) = path.split_once("::")
{
return Some((path.to_string(), variant.ctor_kind, sole_field.name, note_about_variant_field_privacy));
return Some((path.to_string(), variant.ctor_kind(), sole_field.name, note_about_variant_field_privacy));
}
Some((variant_path, variant.ctor_kind, sole_field.name, note_about_variant_field_privacy))
Some((variant_path, variant.ctor_kind(), sole_field.name, note_about_variant_field_privacy))
} else {
None
}
})
.collect();

let suggestions_for = |variant: &_, ctor, field_name| {
let suggestions_for = |variant: &_, ctor_kind, field_name| {
let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
Some(ident) => format!("{ident}: "),
None => String::new(),
};

let (open, close) = match ctor {
hir::def::CtorKind::Fn => ("(".to_owned(), ")"),
hir::def::CtorKind::Fictive => (format!(" {{ {field_name}: "), " }"),
let (open, close) = match ctor_kind {
Some(CtorKind::Fn) => ("(".to_owned(), ")"),
None => (format!(" {{ {field_name}: "), " }"),

// unit variants don't have fields
hir::def::CtorKind::Const => unreachable!(),
Some(CtorKind::Const) => unreachable!(),
};

// Suggest constructor as deep into the block tree as possible.
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -533,8 +533,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.set_tainted_by_errors(e);
tcx.ty_error_with_guaranteed(e)
}
Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) => {
let e = report_unexpected_variant_res(tcx, res, qpath, expr.span);
Res::Def(DefKind::Variant, _) => {
let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, "E0533", "value");
tcx.ty_error_with_guaranteed(e)
}
_ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
Expand Down Expand Up @@ -2024,8 +2024,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);

let variant_ident_span = self.tcx.def_ident_span(variant.def_id).unwrap();
match variant.ctor_kind {
CtorKind::Fn => match ty.kind() {
match variant.ctor_kind() {
Some(CtorKind::Fn) => match ty.kind() {
ty::Adt(adt, ..) if adt.is_enum() => {
err.span_label(
variant_ident_span,
Expand Down
7 changes: 2 additions & 5 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1164,11 +1164,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match *ty.kind() {
ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
let variant = adt_def.non_enum_variant();
let ctor_def_id = variant.ctor_def_id.unwrap();
(
Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id),
Some(substs),
)
let (ctor_kind, ctor_def_id) = variant.ctor.unwrap();
(Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id), Some(substs))
}
_ => {
let mut err = tcx.sess.struct_span_err(
Expand Down
30 changes: 21 additions & 9 deletions compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ use crate::check::check_fn;
use crate::coercion::DynamicCoerceMany;
use crate::gather_locals::GatherLocalsVisitor;
use rustc_data_structures::unord::UnordSet;
use rustc_errors::{struct_span_err, ErrorGuaranteed, MultiSpan};
use rustc_errors::{struct_span_err, DiagnosticId, ErrorGuaranteed, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::Visitor;
use rustc_hir::{HirIdMap, Node};
use rustc_hir_analysis::astconv::AstConv;
Expand Down Expand Up @@ -433,15 +433,27 @@ fn report_unexpected_variant_res(
res: Res,
qpath: &hir::QPath<'_>,
span: Span,
err_code: &str,
expected: &str,
) -> ErrorGuaranteed {
struct_span_err!(
tcx.sess,
let res_descr = match res {
Res::Def(DefKind::Variant, _) => "struct variant",
_ => res.descr(),
};
let path_str = rustc_hir_pretty::qpath_to_string(qpath);
let mut err = tcx.sess.struct_span_err_with_code(
span,
E0533,
"expected unit struct, unit variant or constant, found {} `{}`",
res.descr(),
rustc_hir_pretty::qpath_to_string(qpath),
)
format!("expected {expected}, found {res_descr} `{path_str}`"),
DiagnosticId::Error(err_code.into()),
);
match res {
Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == "E0164" => {
let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html";
err.span_label(span, "`fn` calls are not allowed in patterns");
err.help(format!("for more information, visit {patterns_url}"))
}
_ => err.span_label(span, format!("not a {expected}")),
}
.emit()
}

Expand Down
Loading

0 comments on commit b7463e8

Please sign in to comment.