Skip to content

Avoid later diagnostics and ice from typeck for recovered struct variants #127502

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
return;
};
let mut sugg = vec![];
for field in &variant.fields {
for field in variant.fields() {
// In practice unless there are more than one field with the same type, we'll be
// suggesting a single field at a type, because we don't aggregate multiple borrow
// checker errors involving the functional record update sytnax into a single one.
Expand All @@ -1034,7 +1034,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
}
let (span, sugg) = match fields {
[.., last] => (
if final_field_count == variant.fields.len() {
if final_field_count == variant.fields().len() {
// We'll remove the `..base` as there aren't any fields left.
last.span.shrink_to_hi().with_hi(base.span.hi())
} else {
Expand All @@ -1045,7 +1045,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
// Account for no fields in suggestion span.
[] => (
expr.span.with_lo(struct_qpath.span().hi()),
if final_field_count == variant.fields.len() {
if final_field_count == variant.fields().len() {
// We'll remove the `..base` as there aren't any fields left.
format!(" {{ {} }}", sugg.join(", "))
} else {
Expand Down Expand Up @@ -1185,7 +1185,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
&& def.did().as_local().is_some()
&& def.variants().iter().all(|variant| {
variant
.fields
.fields()
.iter()
.all(|field| self.implements_clone(field.ty(self.infcx.tcx, args)))
})
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 @@ -361,7 +361,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
if !including_tuple_field.0 && variant.ctor_kind() == Some(CtorKind::Fn) {
return None;
}
Some(variant.fields[field].name.to_string())
Some(variant.fields()[field].name.to_string())
}
ty::Tuple(_) => Some(field.index().to_string()),
ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,10 +845,10 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
},
};

if let Some(field) = variant.fields.get(field) {
if let Some(field) = variant.fields().get(field) {
Ok(self.cx.normalize(field.ty(tcx, args), location))
} else {
Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
Err(FieldAccessError::OutOfRange { field_count: variant.fields().len() })
}
}
}
Expand Down Expand Up @@ -1826,10 +1826,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let def = tcx.adt_def(adt_did);
let variant = &def.variant(variant_index);
let adj_field_index = active_field_index.unwrap_or(field_index);
if let Some(field) = variant.fields.get(adj_field_index) {
if let Some(field) = variant.fields().get(adj_field_index) {
Ok(self.normalize(field.ty(tcx, args), location))
} else {
Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
Err(FieldAccessError::OutOfRange { field_count: variant.fields().len() })
}
}
AggregateKind::Closure(_, args) => {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_cranelift/src/inline_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,7 @@ fn asm_clif_type<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> Option<ty
match ty.kind() {
// Adapted from https://github.com/rust-lang/rust/blob/f3c66088610c1b80110297c2d9a8b5f9265b013f/compiler/rustc_hir_analysis/src/check/intrinsicck.rs#L136-L151
ty::Adt(adt, args) if fx.tcx.is_lang_item(adt.did(), LangItem::MaybeUninit) => {
let fields = &adt.non_enum_variant().fields;
let fields = &adt.non_enum_variant().fields();
let ty = fields[FieldIdx::from_u32(1)].ty(fx.tcx, args);
let ty::Adt(ty, args) = ty.kind() else {
unreachable!("expected first field of `MaybeUninit` to be an ADT")
Expand All @@ -926,7 +926,7 @@ fn asm_clif_type<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> Option<ty
ty.is_manually_drop(),
"expected first field of `MaybeUninit` to be `ManuallyDrop`"
);
let fields = &ty.non_enum_variant().fields;
let fields = &ty.non_enum_variant().fields();
let ty = fields[FieldIdx::ZERO].ty(fx.tcx, args);
fx.clif_type(ty)
}
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
// Fields:
|cx, owner| {
variant_def
.fields
.fields()
.iter()
.enumerate()
.map(|(i, f)| {
Expand Down Expand Up @@ -1222,7 +1222,7 @@ fn build_union_type_di_node<'ll, 'tcx>(
// Fields:
|cx, owner| {
variant_def
.fields
.fields()
.iter()
.enumerate()
.map(|(i, f)| {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
.map(|field_index| {
let field_name = if variant_def.ctor_kind() != Some(CtorKind::Fn) {
// Fields have names
let field = &variant_def.fields[FieldIdx::from_usize(field_index)];
let field = &variant_def.fields()[FieldIdx::from_usize(field_index)];
Cow::from(field.name.as_str())
} else {
// Tuple-like
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
assert_eq!(def_a, def_b); // implies same number of fields

for i in def_a.variant(FIRST_VARIANT).fields.indices() {
for i in def_a.variant(FIRST_VARIANT).fields().indices() {
let src_f = src.project_field(bx, i.as_usize());
let dst_f = dst.project_field(bx, i.as_usize());

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/const_eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>(
ty::Adt(def, _) => {
let variant = ecx.read_discriminant(&op).ok()?;
let down = ecx.project_downcast(&op, variant).ok()?;
(def.variants()[variant].fields.len(), Some(variant), down)
(def.variants()[variant].fields().len(), Some(variant), down)
}
ty::Tuple(args) => (args.len(), None, op),
_ => bug!("cannot destructure mir constant {:?}", val),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/const_eval/valtrees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ fn const_to_valtree_inner<'tcx>(
}

let variant = ecx.read_discriminant(place)?;
branches(ecx, place, def.variant(variant).fields.len(), def.is_enum().then_some(variant), num_nodes)
branches(ecx, place, def.variant(variant).fields().len(), def.is_enum().then_some(variant), num_nodes)
}

ty::Never
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,15 +269,17 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
match layout.variants {
Variants::Single { index } => {
// Inside a variant
PathElem::Field(def.variant(index).fields[FieldIdx::from_usize(field)].name)
PathElem::Field(
def.variant(index).fields()[FieldIdx::from_usize(field)].name,
)
}
Variants::Multiple { .. } => bug!("we handled variants above"),
}
}

// other ADTs
ty::Adt(def, _) => {
PathElem::Field(def.non_enum_variant().fields[FieldIdx::from_usize(field)].name)
PathElem::Field(def.non_enum_variant().fields()[FieldIdx::from_usize(field)].name)
}

// arrays/slices
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
// could be a problem for `ImmTy` (see layout_sanity_check):
// - variant.size == Size::ZERO: works fine because `ImmTy::offset` has a special case for
// zero-sized layouts.
// - variant.fields.count() == 0: works fine because `ImmTy::offset` has a special case for
// - variant.fields().count() == 0: works fine because `ImmTy::offset` has a special case for
// zero-field aggregates.
// - variant.abi.is_uninhabited(): triggers UB in `read_discriminant` so we never get here.
let inner = self.ecx().project_downcast(v, idx)?;
Expand Down
13 changes: 7 additions & 6 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ fn check_unnamed_fields(tcx: TyCtxt<'_>, def: ty::AdtDef<'_>) {
let adt_kind = def.descr();
let span = tcx.def_span(def.did());
let unnamed_fields = variant
.fields
.fields()
.iter()
.filter(|f| f.is_unnamed())
.map(|f| {
Expand All @@ -122,7 +122,7 @@ fn check_unnamed_fields(tcx: TyCtxt<'_>, def: ty::AdtDef<'_>) {
});
}
}
for field in variant.fields.iter().filter(|f| f.is_unnamed()) {
for field in variant.fields().iter().filter(|f| f.is_unnamed()) {
let field_ty = tcx.type_of(field.did).instantiate_identity();
if let Some(adt) = field_ty.ty_adt_def()
&& !adt.is_enum()
Expand Down Expand Up @@ -176,7 +176,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
}

let param_env = tcx.param_env(item_def_id);
for field in &def.non_enum_variant().fields {
for field in def.non_enum_variant().fields() {
let Ok(field_ty) = tcx.try_normalize_erasing_regions(param_env, field.ty(tcx, args))
else {
tcx.dcx().span_delayed_bug(span, "could not normalize field type");
Expand Down Expand Up @@ -647,7 +647,8 @@ fn is_enum_of_nonnullable_ptr<'tcx>(
let [var_one, var_two] = &adt_def.variants().raw[..] else {
return false;
};
let (([], [field]) | ([field], [])) = (&var_one.fields.raw[..], &var_two.fields.raw[..]) else {
let (([], [field]) | ([field], [])) = (&var_one.fields().raw[..], &var_two.fields().raw[..])
else {
return false;
};
matches!(field.ty(tcx, args).kind(), ty::FnPtr(..) | ty::Ref(..))
Expand Down Expand Up @@ -1059,7 +1060,7 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
if let ty::Adt(def, args) = t.kind()
&& def.is_struct()
{
let fields = &def.non_enum_variant().fields;
let fields = &def.non_enum_variant().fields();
if fields.is_empty() {
struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit();
return;
Expand Down Expand Up @@ -1201,7 +1202,7 @@ pub(super) fn check_packed_inner(
}

stack.push(def_id);
for field in &def.non_enum_variant().fields {
for field in def.non_enum_variant().fields() {
if let ty::Adt(def, _) = field.ty(tcx, args).kind()
&& !stack.contains(&def.did())
&& let Some(mut defs) = check_packed_inner(tcx, def.did(), stack)
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_analysis/src/check/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
ty::FnPtr(_) => Some(asm_ty_isize),
ty::RawPtr(ty, _) if self.is_thin_ptr_ty(ty) => Some(asm_ty_isize),
ty::Adt(adt, args) if adt.repr().simd() => {
let fields = &adt.non_enum_variant().fields;
let fields = &adt.non_enum_variant().fields();
let elem_ty = fields[FieldIdx::ZERO].ty(self.tcx, args);

let (size, ty) = match elem_ty.kind() {
Expand Down Expand Up @@ -139,7 +139,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
ty::Never if is_input => return None,
_ if ty.references_error() => return None,
ty::Adt(adt, args) if self.tcx.is_lang_item(adt.did(), LangItem::MaybeUninit) => {
let fields = &adt.non_enum_variant().fields;
let fields = &adt.non_enum_variant().fields();
let ty = fields[FieldIdx::from_u32(1)].ty(self.tcx, args);
// FIXME: Are we just trying to map to the `T` in `MaybeUninit<T>`?
// If so, just get it from the args.
Expand All @@ -150,7 +150,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
ty.is_manually_drop(),
"expected first field of `MaybeUninit` to be `ManuallyDrop`"
);
let fields = &ty.non_enum_variant().fields;
let fields = &ty.non_enum_variant().fields();
let ty = fields[FieldIdx::ZERO].ty(self.tcx, args);
self.get_asm_ty(ty)
}
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1077,7 +1077,7 @@ fn check_type_defn<'tcx>(

for variant in variants.iter() {
// All field types must be well-formed.
for field in &variant.fields {
for field in variant.fields_checked()? {
let field_id = field.did.expect_local();
let hir::FieldDef { ty: hir_ty, .. } =
tcx.hir_node_by_def_id(field_id).expect_field();
Expand All @@ -1104,12 +1104,12 @@ fn check_type_defn<'tcx>(
}
};
// All fields (except for possibly the last) should be sized.
let all_sized = all_sized || variant.fields.is_empty() || needs_drop_copy();
let all_sized = all_sized || variant.fields().is_empty() || needs_drop_copy();
let unsized_len = if all_sized { 0 } else { 1 };
for (idx, field) in
variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate()
variant.fields().raw[..variant.fields().len() - unsized_len].iter().enumerate()
{
let last = idx == variant.fields.len() - 1;
let last = idx == variant.fields().len() - 1;
let field_id = field.did.expect_local();
let hir::FieldDef { ty: hir_ty, .. } =
tcx.hir_node_by_def_id(field_id).expect_field();
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<()
res = Err(tcx.dcx().emit_err(errors::DispatchFromDynRepr { span }));
}

let fields = &def_a.non_enum_variant().fields;
let fields = &def_a.non_enum_variant().fields();

let coerced_fields = fields
.iter()
Expand Down Expand Up @@ -411,7 +411,7 @@ pub fn coerce_unsized_info<'tcx>(
// conversion). This will work out because `U:
// Unsize<V>`, and we have a builtin rule that `*mut
// U` can be coerced to `*mut V` if `U: Unsize<V>`.
let fields = &def_a.non_enum_variant().fields;
let fields = &def_a.non_enum_variant().fields();
let diff_fields = fields
.iter_enumerated()
.filter_map(|(i, f)| {
Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -867,7 +867,7 @@ fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
.unwrap_or(wrapped_discr),
);

for f in &variant.fields {
for f in variant.fields() {
tcx.ensure().generics_of(f.did);
tcx.ensure().type_of(f.did);
tcx.ensure().predicates_of(f.did);
Expand All @@ -886,7 +886,7 @@ fn find_field(tcx: TyCtxt<'_>, (def_id, ident): (DefId, Ident)) -> Option<FieldI
return None;
}

adt.non_enum_variant().fields.iter_enumerated().find_map(|(idx, field)| {
adt.non_enum_variant().fields().iter_enumerated().find_map(|(idx, field)| {
if field.is_unnamed() {
let field_ty = tcx.type_of(field.did).instantiate_identity();
let adt_def = field_ty.ty_adt_def().expect("expect Adt for unnamed field");
Expand Down Expand Up @@ -1091,7 +1091,11 @@ fn lower_variant(
vis: tcx.visibility(f.def_id),
})
.collect();
let recovered = matches!(def, hir::VariantData::Struct { recovered: Recovered::Yes(_), .. });
let recovered = match def {
hir::VariantData::Struct { recovered: Recovered::Yes(guard), .. } => Some(guard.clone()),
_ => None,
};

ty::VariantDef::new(
ident.name,
variant_did.map(LocalDefId::to_def_id),
Expand Down
Loading
Loading