]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_hir_typeck/src/pat.rs
Rollup merge of #104359 - Nilstrieb:plus-one, r=fee1-dead
[rust.git] / compiler / rustc_hir_typeck / src / pat.rs
index eb10f3e2c107f8f943b9d17c30cd8238b5fc9d8f..2fe1b1d8999bc6455e42bce4d988546e51a674f7 100644 (file)
@@ -401,6 +401,16 @@ fn check_pat_lit(
             }
         }
 
+        if self.tcx.features().string_deref_patterns && let hir::ExprKind::Lit(Spanned { node: ast::LitKind::Str(..), .. }) = lt.kind {
+            let tcx = self.tcx;
+            let expected = self.resolve_vars_if_possible(expected);
+            pat_ty = match expected.kind() {
+                ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().string() => expected,
+                ty::Str => tcx.mk_static_str(),
+                _ => pat_ty,
+            };
+        }
+
         // Somewhat surprising: in this case, the subtyping relation goes the
         // opposite way as the other cases. Actually what we really want is not
         // a subtyping relation at all but rather that there exists a LUB
@@ -839,12 +849,14 @@ fn check_pat_path(
         let (res, opt_ty, segments) = path_resolution;
         match res {
             Res::Err => {
-                self.set_tainted_by_errors();
-                return tcx.ty_error();
+                let e = tcx.sess.delay_span_bug(qpath.span(), "`Res::Err` but no error emitted");
+                self.set_tainted_by_errors(e);
+                return tcx.ty_error_with_guaranteed(e);
             }
-            Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fictive | CtorKind::Fn), _) => {
-                report_unexpected_variant_res(tcx, res, qpath, pat.span);
-                return tcx.ty_error();
+            Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => {
+                let expected = "unit struct, unit variant or constant";
+                let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0533", expected);
+                return tcx.ty_error_with_guaranteed(e);
             }
             Res::SelfCtor(..)
             | Res::Def(
@@ -985,65 +997,46 @@ fn check_pat_tuple_struct(
         ti: TopInfo<'tcx>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
-        let on_error = || {
+        let on_error = |e| {
             for pat in subpats {
-                self.check_pat(pat, tcx.ty_error(), def_bm, ti);
+                self.check_pat(pat, tcx.ty_error_with_guaranteed(e), def_bm, ti);
             }
         };
         let report_unexpected_res = |res: Res| {
-            let sm = tcx.sess.source_map();
-            let path_str = sm
-                .span_to_snippet(sm.span_until_char(pat.span, '('))
-                .map_or_else(|_| String::new(), |s| format!(" `{}`", s.trim_end()));
-            let msg = format!(
-                "expected tuple struct or tuple variant, found {}{}",
-                res.descr(),
-                path_str
-            );
-
-            let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{msg}");
-            match res {
-                Res::Def(DefKind::Fn | DefKind::AssocFn, _) => {
-                    err.span_label(pat.span, "`fn` calls are not allowed in patterns");
-                    err.help(
-                        "for more information, visit \
-                              https://doc.rust-lang.org/book/ch18-00-patterns.html",
-                    );
-                }
-                _ => {
-                    err.span_label(pat.span, "not a tuple variant or struct");
-                }
-            }
-            err.emit();
-            on_error();
+            let expected = "tuple struct or tuple variant";
+            let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0164", expected);
+            on_error(e);
+            e
         };
 
         // Resolve the path and check the definition for errors.
         let (res, opt_ty, segments) =
             self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span);
         if res == Res::Err {
-            self.set_tainted_by_errors();
-            on_error();
-            return self.tcx.ty_error();
+            let e = tcx.sess.delay_span_bug(pat.span, "`Res:Err` but no error emitted");
+            self.set_tainted_by_errors(e);
+            on_error(e);
+            return tcx.ty_error_with_guaranteed(e);
         }
 
         // Type-check the path.
         let (pat_ty, res) =
             self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id);
         if !pat_ty.is_fn() {
-            report_unexpected_res(res);
-            return tcx.ty_error();
+            let e = report_unexpected_res(res);
+            return tcx.ty_error_with_guaranteed(e);
         }
 
         let variant = match res {
             Res::Err => {
-                self.set_tainted_by_errors();
-                on_error();
-                return tcx.ty_error();
+                let e = tcx.sess.delay_span_bug(pat.span, "`Res::Err` but no error emitted");
+                self.set_tainted_by_errors(e);
+                on_error(e);
+                return tcx.ty_error_with_guaranteed(e);
             }
             Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) => {
-                report_unexpected_res(res);
-                return tcx.ty_error();
+                let e = report_unexpected_res(res);
+                return tcx.ty_error_with_guaranteed(e);
             }
             Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => tcx.expect_variant_res(res),
             _ => bug!("unexpected pattern resolution: {:?}", res),
@@ -1082,9 +1075,9 @@ fn check_pat_tuple_struct(
             }
         } else {
             // Pattern has wrong number of fields.
-            self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected, had_err);
-            on_error();
-            return tcx.ty_error();
+            let e = self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected, had_err);
+            on_error(e);
+            return tcx.ty_error_with_guaranteed(e);
         }
         pat_ty
     }
@@ -1098,7 +1091,7 @@ fn e0023(
         fields: &'tcx [ty::FieldDef],
         expected: Ty<'tcx>,
         had_err: bool,
-    ) {
+    ) -> ErrorGuaranteed {
         let subpats_ending = pluralize!(subpats.len());
         let fields_ending = pluralize!(fields.len());
 
@@ -1245,7 +1238,7 @@ fn e0023(
             }
         }
 
-        err.emit();
+        err.emit()
     }
 
     fn check_pat_tuple(
@@ -1467,8 +1460,8 @@ fn error_tuple_variant_index_shorthand(
         // if this is a tuple struct, then all field names will be numbers
         // so if any fields in a struct pattern use shorthand syntax, they will
         // be invalid identifiers (for example, Foo { 0, 1 }).
-        if let (CtorKind::Fn, PatKind::Struct(qpath, field_patterns, ..)) =
-            (variant.ctor_kind, &pat.kind)
+        if let (Some(CtorKind::Fn), PatKind::Struct(qpath, field_patterns, ..)) =
+            (variant.ctor_kind(), &pat.kind)
         {
             let has_shorthand_field_name = field_patterns.iter().any(|field| field.is_shorthand);
             if has_shorthand_field_name {
@@ -1645,7 +1638,7 @@ fn error_tuple_variant_as_struct_pat(
         fields: &'tcx [hir::PatField<'tcx>],
         variant: &ty::VariantDef,
     ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
-        if let (CtorKind::Fn, PatKind::Struct(qpath, ..)) = (variant.ctor_kind, &pat.kind) {
+        if let (Some(CtorKind::Fn), PatKind::Struct(qpath, ..)) = (variant.ctor_kind(), &pat.kind) {
             let path = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| {
                 s.print_qpath(qpath, false)
             });