Skip to content

Commit 09f4f7c

Browse files
authored
Rollup merge of #103759 - cjgillot:adt-collect, r=davidtwco
Use `adt_def` during type collection. This removes a wrapper which is close to what `adt_def` does.
2 parents 20528ba + abc1ad7 commit 09f4f7c

File tree

4 files changed

+113
-164
lines changed

4 files changed

+113
-164
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

+62-59
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use super::*;
66
use rustc_attr as attr;
77
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
88
use rustc_hir as hir;
9-
use rustc_hir::def::{DefKind, Res};
9+
use rustc_hir::def::{CtorKind, DefKind, Res};
1010
use rustc_hir::def_id::{DefId, LocalDefId};
1111
use rustc_hir::intravisit::Visitor;
1212
use rustc_hir::{ItemKind, Node, PathSegment};
@@ -75,15 +75,15 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {
7575
check_simd(tcx, span, def_id);
7676
}
7777

78-
check_transparent(tcx, span, def);
78+
check_transparent(tcx, def);
7979
check_packed(tcx, span, def);
8080
}
8181

8282
fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
8383
let def = tcx.adt_def(def_id);
8484
let span = tcx.def_span(def_id);
8585
def.destructor(tcx); // force the destructor to be evaluated
86-
check_transparent(tcx, span, def);
86+
check_transparent(tcx, def);
8787
check_union_fields(tcx, span, def_id);
8888
check_packed(tcx, span, def);
8989
}
@@ -506,11 +506,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
506506
tcx.ensure().typeck(id.owner_id.def_id);
507507
}
508508
DefKind::Enum => {
509-
let item = tcx.hir().item(id);
510-
let hir::ItemKind::Enum(ref enum_definition, _) = item.kind else {
511-
return;
512-
};
513-
check_enum(tcx, &enum_definition.variants, item.owner_id.def_id);
509+
check_enum(tcx, id.owner_id.def_id);
514510
}
515511
DefKind::Fn => {} // entirely within check_item_body
516512
DefKind::Impl => {
@@ -1026,7 +1022,7 @@ pub(super) fn check_packed_inner(
10261022
None
10271023
}
10281024

1029-
pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtDef<'tcx>) {
1025+
pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) {
10301026
if !adt.repr().transparent() {
10311027
return;
10321028
}
@@ -1035,14 +1031,14 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
10351031
feature_err(
10361032
&tcx.sess.parse_sess,
10371033
sym::transparent_unions,
1038-
sp,
1034+
tcx.def_span(adt.did()),
10391035
"transparent unions are unstable",
10401036
)
10411037
.emit();
10421038
}
10431039

10441040
if adt.variants().len() != 1 {
1045-
bad_variant_count(tcx, adt, sp, adt.did());
1041+
bad_variant_count(tcx, adt, tcx.def_span(adt.did()), adt.did());
10461042
if adt.variants().is_empty() {
10471043
// Don't bother checking the fields. No variants (and thus no fields) exist.
10481044
return;
@@ -1103,7 +1099,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
11031099
.filter_map(|(span, zst, _align1, _non_exhaustive)| if !zst { Some(span) } else { None });
11041100
let non_zst_count = non_zst_fields.clone().count();
11051101
if non_zst_count >= 2 {
1106-
bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, sp);
1102+
bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, tcx.def_span(adt.did()));
11071103
}
11081104
let incompatible_zst_fields =
11091105
field_infos.clone().filter(|(_, _, _, opt)| opt.is_some()).count();
@@ -1143,20 +1139,19 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
11431139
}
11441140

11451141
#[allow(trivial_numeric_casts)]
1146-
fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: LocalDefId) {
1142+
fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
11471143
let def = tcx.adt_def(def_id);
1148-
let sp = tcx.def_span(def_id);
11491144
def.destructor(tcx); // force the destructor to be evaluated
11501145

1151-
if vs.is_empty() {
1146+
if def.variants().is_empty() {
11521147
if let Some(attr) = tcx.get_attrs(def_id.to_def_id(), sym::repr).next() {
11531148
struct_span_err!(
11541149
tcx.sess,
11551150
attr.span,
11561151
E0084,
11571152
"unsupported representation for zero-variant enum"
11581153
)
1159-
.span_label(sp, "zero-variant enum")
1154+
.span_label(tcx.def_span(def_id), "zero-variant enum")
11601155
.emit();
11611156
}
11621157
}
@@ -1167,88 +1162,96 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L
11671162
feature_err(
11681163
&tcx.sess.parse_sess,
11691164
sym::repr128,
1170-
sp,
1165+
tcx.def_span(def_id),
11711166
"repr with 128-bit type is unstable",
11721167
)
11731168
.emit();
11741169
}
11751170
}
11761171

1177-
for v in vs {
1178-
if let Some(ref e) = v.disr_expr {
1179-
tcx.ensure().typeck(tcx.hir().local_def_id(e.hir_id));
1172+
for v in def.variants() {
1173+
if let ty::VariantDiscr::Explicit(discr_def_id) = v.discr {
1174+
tcx.ensure().typeck(discr_def_id.expect_local());
11801175
}
11811176
}
11821177

1183-
if tcx.adt_def(def_id).repr().int.is_none() {
1184-
let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..));
1178+
if def.repr().int.is_none() {
1179+
let is_unit = |var: &ty::VariantDef| matches!(var.ctor_kind, CtorKind::Const);
1180+
let has_disr = |var: &ty::VariantDef| matches!(var.discr, ty::VariantDiscr::Explicit(_));
11851181

1186-
let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();
1187-
let has_non_units = vs.iter().any(|var| !is_unit(var));
1188-
let disr_units = vs.iter().any(|var| is_unit(&var) && has_disr(&var));
1189-
let disr_non_unit = vs.iter().any(|var| !is_unit(&var) && has_disr(&var));
1182+
let has_non_units = def.variants().iter().any(|var| !is_unit(var));
1183+
let disr_units = def.variants().iter().any(|var| is_unit(&var) && has_disr(&var));
1184+
let disr_non_unit = def.variants().iter().any(|var| !is_unit(&var) && has_disr(&var));
11901185

11911186
if disr_non_unit || (disr_units && has_non_units) {
1192-
let mut err =
1193-
struct_span_err!(tcx.sess, sp, E0732, "`#[repr(inttype)]` must be specified");
1187+
let mut err = struct_span_err!(
1188+
tcx.sess,
1189+
tcx.def_span(def_id),
1190+
E0732,
1191+
"`#[repr(inttype)]` must be specified"
1192+
);
11941193
err.emit();
11951194
}
11961195
}
11971196

1198-
detect_discriminant_duplicate(tcx, def.discriminants(tcx).collect(), vs, sp);
1199-
1200-
check_transparent(tcx, sp, def);
1197+
detect_discriminant_duplicate(tcx, def);
1198+
check_transparent(tcx, def);
12011199
}
12021200

12031201
/// Part of enum check. Given the discriminants of an enum, errors if two or more discriminants are equal
1204-
fn detect_discriminant_duplicate<'tcx>(
1205-
tcx: TyCtxt<'tcx>,
1206-
mut discrs: Vec<(VariantIdx, Discr<'tcx>)>,
1207-
vs: &'tcx [hir::Variant<'tcx>],
1208-
self_span: Span,
1209-
) {
1202+
fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) {
12101203
// Helper closure to reduce duplicate code. This gets called everytime we detect a duplicate.
12111204
// Here `idx` refers to the order of which the discriminant appears, and its index in `vs`
1212-
let report = |dis: Discr<'tcx>, idx: usize, err: &mut Diagnostic| {
1213-
let var = &vs[idx]; // HIR for the duplicate discriminant
1214-
let (span, display_discr) = match var.disr_expr {
1215-
Some(ref expr) => {
1205+
let report = |dis: Discr<'tcx>, idx, err: &mut Diagnostic| {
1206+
let var = adt.variant(idx); // HIR for the duplicate discriminant
1207+
let (span, display_discr) = match var.discr {
1208+
ty::VariantDiscr::Explicit(discr_def_id) => {
12161209
// In the case the discriminant is both a duplicate and overflowed, let the user know
1217-
if let hir::ExprKind::Lit(lit) = &tcx.hir().body(expr.body).value.kind
1210+
if let hir::Node::AnonConst(expr) = tcx.hir().get_by_def_id(discr_def_id.expect_local())
1211+
&& let hir::ExprKind::Lit(lit) = &tcx.hir().body(expr.body).value.kind
12181212
&& let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node
12191213
&& *lit_value != dis.val
12201214
{
1221-
(tcx.hir().span(expr.hir_id), format!("`{dis}` (overflowed from `{lit_value}`)"))
1222-
// Otherwise, format the value as-is
1215+
(tcx.def_span(discr_def_id), format!("`{dis}` (overflowed from `{lit_value}`)"))
12231216
} else {
1224-
(tcx.hir().span(expr.hir_id), format!("`{dis}`"))
1217+
// Otherwise, format the value as-is
1218+
(tcx.def_span(discr_def_id), format!("`{dis}`"))
12251219
}
12261220
}
1227-
None => {
1221+
// This should not happen.
1222+
ty::VariantDiscr::Relative(0) => (tcx.def_span(var.def_id), format!("`{dis}`")),
1223+
ty::VariantDiscr::Relative(distance_to_explicit) => {
12281224
// At this point we know this discriminant is a duplicate, and was not explicitly
12291225
// assigned by the user. Here we iterate backwards to fetch the HIR for the last
12301226
// explicitly assigned discriminant, and letting the user know that this was the
12311227
// increment startpoint, and how many steps from there leading to the duplicate
1232-
if let Some((n, hir::Variant { span, ident, .. })) =
1233-
vs[..idx].iter().rev().enumerate().find(|v| v.1.disr_expr.is_some())
1228+
if let Some(explicit_idx) =
1229+
idx.as_u32().checked_sub(distance_to_explicit).map(VariantIdx::from_u32)
12341230
{
1235-
let ve_ident = var.ident;
1236-
let n = n + 1;
1237-
let sp = if n > 1 { "variants" } else { "variant" };
1231+
let explicit_variant = adt.variant(explicit_idx);
1232+
let ve_ident = var.name;
1233+
let ex_ident = explicit_variant.name;
1234+
let sp = if distance_to_explicit > 1 { "variants" } else { "variant" };
12381235

12391236
err.span_label(
1240-
*span,
1241-
format!("discriminant for `{ve_ident}` incremented from this startpoint (`{ident}` + {n} {sp} later => `{ve_ident}` = {dis})"),
1237+
tcx.def_span(explicit_variant.def_id),
1238+
format!(
1239+
"discriminant for `{ve_ident}` incremented from this startpoint \
1240+
(`{ex_ident}` + {distance_to_explicit} {sp} later \
1241+
=> `{ve_ident}` = {dis})"
1242+
),
12421243
);
12431244
}
12441245

1245-
(vs[idx].span, format!("`{dis}`"))
1246+
(tcx.def_span(var.def_id), format!("`{dis}`"))
12461247
}
12471248
};
12481249

12491250
err.span_label(span, format!("{display_discr} assigned here"));
12501251
};
12511252

1253+
let mut discrs = adt.discriminants(tcx).collect::<Vec<_>>();
1254+
12521255
// Here we loop through the discriminants, comparing each discriminant to another.
12531256
// When a duplicate is detected, we instantiate an error and point to both
12541257
// initial and duplicate value. The duplicate discriminant is then discarded by swapping
@@ -1257,29 +1260,29 @@ fn detect_discriminant_duplicate<'tcx>(
12571260
// style as we are mutating `discrs` on the fly).
12581261
let mut i = 0;
12591262
while i < discrs.len() {
1260-
let hir_var_i_idx = discrs[i].0.index();
1263+
let var_i_idx = discrs[i].0;
12611264
let mut error: Option<DiagnosticBuilder<'_, _>> = None;
12621265

12631266
let mut o = i + 1;
12641267
while o < discrs.len() {
1265-
let hir_var_o_idx = discrs[o].0.index();
1268+
let var_o_idx = discrs[o].0;
12661269

12671270
if discrs[i].1.val == discrs[o].1.val {
12681271
let err = error.get_or_insert_with(|| {
12691272
let mut ret = struct_span_err!(
12701273
tcx.sess,
1271-
self_span,
1274+
tcx.def_span(adt.did()),
12721275
E0081,
12731276
"discriminant value `{}` assigned more than once",
12741277
discrs[i].1,
12751278
);
12761279

1277-
report(discrs[i].1, hir_var_i_idx, &mut ret);
1280+
report(discrs[i].1, var_i_idx, &mut ret);
12781281

12791282
ret
12801283
});
12811284

1282-
report(discrs[o].1, hir_var_o_idx, err);
1285+
report(discrs[o].1, var_o_idx, err);
12831286

12841287
// Safe to unwrap here, as we wouldn't reach this point if `discrs` was empty
12851288
discrs[o] = *discrs.last().unwrap();

0 commit comments

Comments
 (0)