From 08235b1603f77f39468e7b2e552945501c0cc048 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 22 Mar 2024 16:56:13 -0400 Subject: [PATCH] Validate that we're only matching on unit struct for path pattern --- compiler/rustc_hir_typeck/src/pat.rs | 21 ++++++++++- ...70549-resolve-after-recovered-self-ctor.rs | 4 +- ...9-resolve-after-recovered-self-ctor.stderr | 9 +++-- .../no-match-tuple-variant-self-ctor.rs | 37 +++++++++++++++++++ ...tch-tuple-variant-self-ctor.struct_.stderr | 19 ++++++++++ ...match-tuple-variant-self-ctor.tuple.stderr | 9 +++++ 6 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 tests/ui/pattern/no-match-tuple-variant-self-ctor.rs create mode 100644 tests/ui/pattern/no-match-tuple-variant-self-ctor.struct_.stderr create mode 100644 tests/ui/pattern/no-match-tuple-variant-self-ctor.tuple.stderr diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index dad43cb8abe..8cb3b4b8e47 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -919,8 +919,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, E0533, expected); return Ty::new_error(tcx, e); } - Res::SelfCtor(..) - | Res::Def( + Res::SelfCtor(def_id) => { + if let ty::Adt(adt_def, _) = *tcx.type_of(def_id).skip_binder().kind() + && adt_def.is_struct() + && let Some((CtorKind::Const, _)) = adt_def.non_enum_variant().ctor + { + // Ok, we allow unit struct ctors in patterns only. + } else { + let e = report_unexpected_variant_res( + tcx, + res, + qpath, + pat.span, + E0533, + "unit struct", + ); + return Ty::new_error(tcx, e); + } + } + Res::Def( DefKind::Ctor(_, CtorKind::Const) | DefKind::Const | DefKind::AssocConst diff --git a/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.rs b/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.rs index aeccd0d9f76..ada10fcda27 100644 --- a/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.rs +++ b/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.rs @@ -4,12 +4,12 @@ impl S { fn foo(&mur Self) {} //~^ ERROR expected identifier, found keyword `Self` //~| ERROR expected one of `:`, `@` - //~| ERROR the `Self` constructor can only be used with + //~| ERROR expected unit struct, found self constructor `Self` fn bar(&'static mur Self) {} //~^ ERROR unexpected lifetime //~| ERROR expected identifier, found keyword `Self` //~| ERROR expected one of `:`, `@` - //~| ERROR the `Self` constructor can only be used with + //~| ERROR expected unit struct, found self constructor `Self` fn baz(&mur Self @ _) {} //~^ ERROR expected one of `:`, `@` diff --git a/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr b/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr index 421f1454036..ec0af9a6caf 100644 --- a/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr +++ b/tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr @@ -40,17 +40,18 @@ error: expected one of `:`, `@`, or `|`, found keyword `Self` LL | fn baz(&mur Self @ _) {} | ^^^^ expected one of `:`, `@`, or `|` -error: the `Self` constructor can only be used with tuple or unit structs +error[E0533]: expected unit struct, found self constructor `Self` --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:4:17 | LL | fn foo(&mur Self) {} - | ^^^^ help: use curly brackets: `Self { /* fields */ }` + | ^^^^ not a unit struct -error: the `Self` constructor can only be used with tuple or unit structs +error[E0533]: expected unit struct, found self constructor `Self` --> $DIR/issue-70549-resolve-after-recovered-self-ctor.rs:8:25 | LL | fn bar(&'static mur Self) {} - | ^^^^ help: use curly brackets: `Self { /* fields */ }` + | ^^^^ not a unit struct error: aborting due to 8 previous errors +For more information about this error, try `rustc --explain E0533`. diff --git a/tests/ui/pattern/no-match-tuple-variant-self-ctor.rs b/tests/ui/pattern/no-match-tuple-variant-self-ctor.rs new file mode 100644 index 00000000000..7c2821e77ab --- /dev/null +++ b/tests/ui/pattern/no-match-tuple-variant-self-ctor.rs @@ -0,0 +1,37 @@ +//@ revisions: tuple unit struct_ +//@[unit] check-pass + +#[cfg(unit)] +mod unit { + struct S; + impl S { + fn foo() { + let Self = S; + } + } +} + +#[cfg(tuple)] +mod tuple { + struct S(()); + impl S { + fn foo() { + let Self = S; + //[tuple]~^ ERROR expected unit struct + } + } +} + +#[cfg(struct_)] +mod struct_ { + struct S {} + impl S { + fn foo() { + let Self = S; + //[struct_]~^ ERROR expected value, found struct `S` + //[struct_]~| ERROR expected unit struct, found self constructor `Self` + } + } +} + +fn main() {} diff --git a/tests/ui/pattern/no-match-tuple-variant-self-ctor.struct_.stderr b/tests/ui/pattern/no-match-tuple-variant-self-ctor.struct_.stderr new file mode 100644 index 00000000000..5ed3979feb8 --- /dev/null +++ b/tests/ui/pattern/no-match-tuple-variant-self-ctor.struct_.stderr @@ -0,0 +1,19 @@ +error[E0423]: expected value, found struct `S` + --> $DIR/no-match-tuple-variant-self-ctor.rs:30:24 + | +LL | struct S {} + | ----------- `S` defined here +... +LL | let Self = S; + | ^ help: use struct literal syntax instead: `S {}` + +error[E0533]: expected unit struct, found self constructor `Self` + --> $DIR/no-match-tuple-variant-self-ctor.rs:30:17 + | +LL | let Self = S; + | ^^^^ not a unit struct + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0423, E0533. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/pattern/no-match-tuple-variant-self-ctor.tuple.stderr b/tests/ui/pattern/no-match-tuple-variant-self-ctor.tuple.stderr new file mode 100644 index 00000000000..d31a4a79189 --- /dev/null +++ b/tests/ui/pattern/no-match-tuple-variant-self-ctor.tuple.stderr @@ -0,0 +1,9 @@ +error[E0533]: expected unit struct, found self constructor `Self` + --> $DIR/no-match-tuple-variant-self-ctor.rs:19:17 + | +LL | let Self = S; + | ^^^^ not a unit struct + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0533`.