diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-02-23 17:02:04 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-23 17:02:04 +0100 |
| commit | 4d5c4e5205cba3982951a78dc9ac2b249b73bd97 (patch) | |
| tree | 9c6116b82d2583ec8ded0e46f4b42d30bf25dd73 | |
| parent | 26cb6c728736ba9c582cbde761d9d9fd10ff74b9 (diff) | |
| parent | 35a9e7352138b059eaae2a9d0724dcd7f6d10ab5 (diff) | |
| download | rust-4d5c4e5205cba3982951a78dc9ac2b249b73bd97.tar.gz rust-4d5c4e5205cba3982951a78dc9ac2b249b73bd97.zip | |
Rollup merge of #121470 - clubby789:anon-struct-in-enum, r=fmease
Don't ICE on anonymous struct in enum variant Fixes #121446 Computing `adt_def` for the anon struct calls `adt_def` on the parent to find its repr. If the parent is a non-item (e.g. an enum variant) we should have already emitted at least one error, so we just use the repr of the anonymous struct to avoid an ICE. cc ``@frank-king``
4 files changed, 41 insertions, 1 deletions
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index fcb15925f6a..78e7c636a3e 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3004,6 +3004,11 @@ impl<'hir> Item<'hir> { matches!(self.kind, ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..)) } + /// Check if this is an [`ItemKind::Struct`] or [`ItemKind::Union`]. + pub fn is_struct_or_union(&self) -> bool { + matches!(self.kind, ItemKind::Struct(..) | ItemKind::Union(..)) + } + expect_methods_self_kind! { expect_extern_crate, Option<Symbol>, ItemKind::ExternCrate(s), *s; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 642009dfa48..e9c9ec6ba53 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1025,7 +1025,15 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { let is_anonymous = item.ident.name == kw::Empty; let repr = if is_anonymous { - tcx.adt_def(tcx.local_parent(def_id)).repr() + let parent = tcx.local_parent(def_id); + if let Node::Item(item) = tcx.hir_node_by_def_id(parent) + && item.is_struct_or_union() + { + tcx.adt_def(parent).repr() + } else { + tcx.dcx().span_delayed_bug(item.span, "anonymous field inside non struct/union"); + ty::ReprOptions::default() + } } else { tcx.repr_options_of_def(def_id) }; diff --git a/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.rs b/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.rs new file mode 100644 index 00000000000..00f9bfd5cdf --- /dev/null +++ b/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.rs @@ -0,0 +1,11 @@ +#![crate_type = "lib"] +#![feature(unnamed_fields)] +#![allow(unused, incomplete_features)] + +enum K { + M { + _ : struct { field: u8 }, + //~^ error: unnamed fields are not allowed outside of structs or unions + //~| error: anonymous structs are not allowed outside of unnamed struct or union fields + } +} diff --git a/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.stderr b/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.stderr new file mode 100644 index 00000000000..43843141e2e --- /dev/null +++ b/tests/ui/union/unnamed-fields/anon-struct-in-enum-issue-121446.stderr @@ -0,0 +1,16 @@ +error: unnamed fields are not allowed outside of structs or unions + --> $DIR/anon-struct-in-enum-issue-121446.rs:7:9 + | +LL | _ : struct { field: u8 }, + | -^^^^^^^^^^^^^^^^^^^^^^^ + | | + | unnamed field declared here + +error: anonymous structs are not allowed outside of unnamed struct or union fields + --> $DIR/anon-struct-in-enum-issue-121446.rs:7:13 + | +LL | _ : struct { field: u8 }, + | ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here + +error: aborting due to 2 previous errors + |
