From 743c41757c3211d989334b50b71df34279add5bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olaf=20Siwi=C5=84ski?= Date: Wed, 5 Jun 2024 21:54:22 +0200 Subject: [PATCH] check_expr_struct_fields: taint context with errors if struct definition is malformed --- compiler/rustc_hir_typeck/src/expr.rs | 9 ++++++++ tests/crashes/124552.rs | 12 ---------- .../static/duplicated-fields-issue-124464.rs} | 6 ++++- .../duplicated-fields-issue-124464.stderr | 22 +++++++++++++++++++ .../static/duplicated-fields-issue-125842.rs | 21 ++++++++++++++++++ .../duplicated-fields-issue-125842.stderr | 11 ++++++++++ 6 files changed, 68 insertions(+), 13 deletions(-) delete mode 100644 tests/crashes/124552.rs rename tests/{crashes/124464.rs => ui/static/duplicated-fields-issue-124464.rs} (57%) create mode 100644 tests/ui/static/duplicated-fields-issue-124464.stderr create mode 100644 tests/ui/static/duplicated-fields-issue-125842.rs create mode 100644 tests/ui/static/duplicated-fields-issue-125842.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 4cc936eed08c5..7dd7b3ff055e5 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1671,6 +1671,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut error_happened = false; + if variant.fields.len() != remaining_fields.len() { + // Some field is defined more than once. Make sure we don't try to + // instantiate this struct in static/const context. + let guar = + self.dcx().span_delayed_bug(expr.span, "struct fields have non-unique names"); + self.set_tainted_by_errors(guar); + error_happened = true; + } + // Type-check each field. for (idx, field) in hir_fields.iter().enumerate() { let ident = tcx.adjust_ident(field.ident, variant.def_id); diff --git a/tests/crashes/124552.rs b/tests/crashes/124552.rs deleted file mode 100644 index 5320ce2784305..0000000000000 --- a/tests/crashes/124552.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: rust-lang/rust#124552 - -struct B; - -struct Foo { - b: u32, - b: B, -} - -static BAR: Foo = Foo { b: B }; - -fn main() {} diff --git a/tests/crashes/124464.rs b/tests/ui/static/duplicated-fields-issue-124464.rs similarity index 57% rename from tests/crashes/124464.rs rename to tests/ui/static/duplicated-fields-issue-124464.rs index 471479f5cf1b6..60609edbfebb6 100644 --- a/tests/crashes/124464.rs +++ b/tests/ui/static/duplicated-fields-issue-124464.rs @@ -1,12 +1,16 @@ -//@ known-bug: rust-lang/rust #124464 +// Don't const eval fields with ambiguous layout. +// See issues #125842 and #124464. + enum TestOption { TestSome(T), TestSome(T), +//~^ ERROR the name `TestSome` is defined multiple times } pub struct Request { bar: TestOption, bar: u8, +//~^ ERROR field `bar` is already declared } fn default_instance() -> &'static Request { diff --git a/tests/ui/static/duplicated-fields-issue-124464.stderr b/tests/ui/static/duplicated-fields-issue-124464.stderr new file mode 100644 index 0000000000000..a36192ae8d69d --- /dev/null +++ b/tests/ui/static/duplicated-fields-issue-124464.stderr @@ -0,0 +1,22 @@ +error[E0428]: the name `TestSome` is defined multiple times + --> $DIR/duplicated-fields-issue-124464.rs:6:5 + | +LL | TestSome(T), + | ----------- previous definition of the type `TestSome` here +LL | TestSome(T), + | ^^^^^^^^^^^ `TestSome` redefined here + | + = note: `TestSome` must be defined only once in the type namespace of this enum + +error[E0124]: field `bar` is already declared + --> $DIR/duplicated-fields-issue-124464.rs:12:5 + | +LL | bar: TestOption, + | -------------------- `bar` first declared here +LL | bar: u8, + | ^^^^^^^ field already declared + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0124, E0428. +For more information about an error, try `rustc --explain E0124`. diff --git a/tests/ui/static/duplicated-fields-issue-125842.rs b/tests/ui/static/duplicated-fields-issue-125842.rs new file mode 100644 index 0000000000000..580b810232e04 --- /dev/null +++ b/tests/ui/static/duplicated-fields-issue-125842.rs @@ -0,0 +1,21 @@ +// Do not try to evaluate static initalizers that reference +// ill-defined types. This used to be an ICE. +// See issues #125842 and #124464. +struct Struct { + field: Option, + field: u8, +//~^ ERROR field `field` is already declared +} + +static STATIC_A: Struct = Struct { + field: 1 +}; + +static STATIC_B: Struct = { + let field = 1; + Struct { + field, + } +}; + +fn main() {} diff --git a/tests/ui/static/duplicated-fields-issue-125842.stderr b/tests/ui/static/duplicated-fields-issue-125842.stderr new file mode 100644 index 0000000000000..c80bb99005ee5 --- /dev/null +++ b/tests/ui/static/duplicated-fields-issue-125842.stderr @@ -0,0 +1,11 @@ +error[E0124]: field `field` is already declared + --> $DIR/duplicated-fields-issue-125842.rs:6:5 + | +LL | field: Option, + | ----------------- `field` first declared here +LL | field: u8, + | ^^^^^^^^^ field already declared + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0124`.