about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs21
-rw-r--r--tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.rs4
-rw-r--r--tests/ui/parser/issues/issue-70549-resolve-after-recovered-self-ctor.stderr9
-rw-r--r--tests/ui/pattern/no-match-tuple-variant-self-ctor.rs37
-rw-r--r--tests/ui/pattern/no-match-tuple-variant-self-ctor.struct_.stderr19
-rw-r--r--tests/ui/pattern/no-match-tuple-variant-self-ctor.tuple.stderr9
6 files changed, 91 insertions, 8 deletions
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 7ecd380ebeb..4dc60f7c6da 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`.