Skip to content

Commit

Permalink
Rollup merge of rust-lang#122910 - compiler-errors:unit-struct-in-pat…
Browse files Browse the repository at this point in the history
…h-pat-only, r=petrochenkov

Validate that we're only matching on unit struct for path pattern

Resolution doesn't validate that we only really take `CtorKind::Unit` in path patterns, since all it sees is `Res::SelfCtor(def_id)`. Check this instead during pattern typeck.

r? petrochenkov

Fixes rust-lang#122809
  • Loading branch information
matthiaskrgr authored Mar 25, 2024
2 parents ccc5310 + 08235b1 commit e9ec442
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 8 deletions.
21 changes: 19 additions & 2 deletions compiler/rustc_hir_typeck/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 `:`, `@`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
37 changes: 37 additions & 0 deletions tests/ui/pattern/no-match-tuple-variant-self-ctor.rs
Original file line number Diff line number Diff line change
@@ -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() {}
19 changes: 19 additions & 0 deletions tests/ui/pattern/no-match-tuple-variant-self-ctor.struct_.stderr
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit e9ec442

Please sign in to comment.