about summary refs log tree commit diff
diff options
context:
space:
mode:
authorb-naber <b_naber@gmx.de>2023-07-05 20:43:37 +0000
committerb-naber <b_naber@gmx.de>2023-07-17 22:06:32 +0000
commit1c217b6d8a55865535d06752a65ba2ae24f7b349 (patch)
treed92375b182a260062b74c012660f66727496682d
parent843e2ee5d56907be94a68d3b3b6a2057f8abaaeb (diff)
downloadrust-1c217b6d8a55865535d06752a65ba2ae24f7b349.tar.gz
rust-1c217b6d8a55865535d06752a65ba2ae24f7b349.zip
move els into DeclOrigin
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/gather_locals.rs37
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs75
3 files changed, 58 insertions, 61 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index c70de7b8b72..2c1543ca1d5 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1,7 +1,7 @@
 use crate::coercion::CoerceMany;
 use crate::errors::SuggestPtrNullMut;
 use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
-use crate::gather_locals::{DeclContext, Declaration};
+use crate::gather_locals::Declaration;
 use crate::method::MethodCallee;
 use crate::TupleArgumentsFlag::*;
 use crate::{errors, Expectation::*};
@@ -1474,12 +1474,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // Type check the pattern. Override if necessary to avoid knock-on errors.
-        let decl_ctxt = DeclContext { has_else: decl.els.is_some(), origin: decl.origin };
-        self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr, Some(decl_ctxt));
+        self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin));
         let pat_ty = self.node_ty(decl.pat.hir_id);
         self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
 
-        if let Some(blk) = decl.els {
+        if let Some(blk) = decl.origin.try_get_els() {
             let previous_diverges = self.diverges.get();
             let else_ty = self.check_block_with_expected(blk, NoExpectation);
             let cause = self.cause(blk.span, ObligationCauseCode::LetElse);
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index 15562d57466..b2b6ad0d101 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -9,22 +9,24 @@ use rustc_span::def_id::LocalDefId;
 use rustc_span::Span;
 use rustc_trait_selection::traits;
 
+/// Provides context for checking patterns in declarations. More specifically this
+/// allows us to infer array types if the pattern is irrefutable and allows us to infer
+/// the size of the array. See issue #76342.
 #[derive(Debug, Copy, Clone)]
-pub(super) enum DeclOrigin {
+pub(super) enum DeclOrigin<'a> {
     // from an `if let` expression
     LetExpr,
     // from `let x = ..`
-    LocalDecl,
+    LocalDecl { els: Option<&'a hir::Block<'a>> },
 }
 
-/// Provides context for checking patterns in declarations. More specifically this
-/// allows us to infer array types if the pattern is irrefutable and allows us to infer
-/// the size of the array. See issue #76342.
-#[derive(Debug, Copy, Clone)]
-pub(crate) struct DeclContext {
-    // whether we're in a let-else context
-    pub(super) has_else: bool,
-    pub(super) origin: DeclOrigin,
+impl<'a> DeclOrigin<'a> {
+    pub(super) fn try_get_els(&self) -> Option<&'a hir::Block<'a>> {
+        match self {
+            Self::LocalDecl { els } => *els,
+            Self::LetExpr => None,
+        }
+    }
 }
 
 /// A declaration is an abstraction of [hir::Local] and [hir::Let].
@@ -36,29 +38,20 @@ pub(super) struct Declaration<'a> {
     pub ty: Option<&'a hir::Ty<'a>>,
     pub span: Span,
     pub init: Option<&'a hir::Expr<'a>>,
-    pub els: Option<&'a hir::Block<'a>>,
-    pub origin: DeclOrigin,
+    pub origin: DeclOrigin<'a>,
 }
 
 impl<'a> From<&'a hir::Local<'a>> for Declaration<'a> {
     fn from(local: &'a hir::Local<'a>) -> Self {
         let hir::Local { hir_id, pat, ty, span, init, els, source: _ } = *local;
-        Declaration { hir_id, pat, ty, span, init, els, origin: DeclOrigin::LocalDecl }
+        Declaration { hir_id, pat, ty, span, init, origin: DeclOrigin::LocalDecl { els } }
     }
 }
 
 impl<'a> From<&'a hir::Let<'a>> for Declaration<'a> {
     fn from(let_expr: &'a hir::Let<'a>) -> Self {
         let hir::Let { hir_id, pat, ty, span, init } = *let_expr;
-        Declaration {
-            hir_id,
-            pat,
-            ty,
-            span,
-            init: Some(init),
-            els: None,
-            origin: DeclOrigin::LetExpr,
-        }
+        Declaration { hir_id, pat, ty, span, init: Some(init), origin: DeclOrigin::LetExpr }
     }
 }
 
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index fbe50966419..659223a377c 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1,4 +1,4 @@
-use crate::gather_locals::{DeclContext, DeclOrigin};
+use crate::gather_locals::DeclOrigin;
 use crate::{errors, FnCtxt, RawTy};
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
@@ -79,10 +79,10 @@ struct TopInfo<'tcx> {
 }
 
 #[derive(Copy, Clone)]
-struct PatInfo<'tcx> {
+struct PatInfo<'tcx, 'a> {
     binding_mode: BindingMode,
     top_info: TopInfo<'tcx>,
-    decl_ctxt: Option<DeclContext>,
+    decl_origin: Option<DeclOrigin<'a>>,
 }
 
 impl<'tcx> FnCtxt<'_, 'tcx> {
@@ -149,10 +149,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         span: Option<Span>,
         origin_expr: Option<&'tcx hir::Expr<'tcx>>,
-        decl_ctxt: Option<DeclContext>,
+        decl_origin: Option<DeclOrigin<'tcx>>,
     ) {
         let info = TopInfo { expected, origin_expr, span };
-        let pat_info = PatInfo { binding_mode: INITIAL_BM, top_info: info, decl_ctxt };
+        let pat_info = PatInfo { binding_mode: INITIAL_BM, top_info: info, decl_origin };
         self.check_pat(pat, expected, pat_info);
     }
 
@@ -162,8 +162,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Outside of this module, `check_pat_top` should always be used.
     /// Conversely, inside this module, `check_pat_top` should never be used.
     #[instrument(level = "debug", skip(self, pat_info))]
-    fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) {
-        let PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt } = pat_info;
+    fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) {
+        let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin } = pat_info;
         let path_res = match &pat.kind {
             PatKind::Path(qpath) => {
                 Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span))
@@ -183,7 +183,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 var_id,
                 sub,
                 expected,
-                PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
+                PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
             ),
             PatKind::TupleStruct(ref qpath, subpats, ddpos) => self.check_pat_tuple_struct(
                 pat,
@@ -191,7 +191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 subpats,
                 ddpos,
                 expected,
-                PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
+                PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
             ),
             PatKind::Path(ref qpath) => {
                 self.check_pat_path(pat, qpath, path_res.unwrap(), expected, ti)
@@ -202,14 +202,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 fields,
                 has_rest_pat,
                 expected,
-                PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
+                PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
             ),
             PatKind::Or(pats) => {
                 for pat in pats {
                     self.check_pat(
                         pat,
                         expected,
-                        PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
+                        PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
                     );
                 }
                 expected
@@ -219,20 +219,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 elements,
                 ddpos,
                 expected,
-                PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
+                PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
             ),
             PatKind::Box(inner) => self.check_pat_box(
                 pat.span,
                 inner,
                 expected,
-                PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
+                PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
             ),
             PatKind::Ref(inner, mutbl) => self.check_pat_ref(
                 pat,
                 inner,
                 mutbl,
                 expected,
-                PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
+                PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
             ),
             PatKind::Slice(before, slice, after) => self.check_pat_slice(
                 pat.span,
@@ -240,7 +240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 slice,
                 after,
                 expected,
-                PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
+                PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
             ),
         };
 
@@ -622,9 +622,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         var_id: HirId,
         sub: Option<&'tcx Pat<'tcx>>,
         expected: Ty<'tcx>,
-        pat_info: PatInfo<'tcx>,
+        pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
-        let PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt } = pat_info;
+        let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin } = pat_info;
 
         // Determine the binding mode...
         let bm = match ba {
@@ -663,7 +663,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         if let Some(p) = sub {
-            self.check_pat(p, expected, PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt });
+            self.check_pat(
+                p,
+                expected,
+                PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
+            );
         }
 
         local_ty
@@ -886,9 +890,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         fields: &'tcx [hir::PatField<'tcx>],
         has_rest_pat: bool,
         expected: Ty<'tcx>,
-        pat_info: PatInfo<'tcx>,
+        pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
-        let PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt } = pat_info;
+        let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin } = pat_info;
 
         // Resolve the path and check the definition for errors.
         let (variant, pat_ty) = match self.check_struct_path(qpath, pat.hir_id) {
@@ -900,7 +904,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.check_pat(
                         field.pat,
                         err,
-                        PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
+                        PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
                     );
                 }
                 return err;
@@ -917,7 +921,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             variant,
             fields,
             has_rest_pat,
-            PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
+            PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
         ) {
             pat_ty
         } else {
@@ -1083,16 +1087,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         subpats: &'tcx [Pat<'tcx>],
         ddpos: hir::DotDotPos,
         expected: Ty<'tcx>,
-        pat_info: PatInfo<'tcx>,
+        pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
-        let PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt } = pat_info;
+        let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin } = pat_info;
         let tcx = self.tcx;
         let on_error = |e| {
             for pat in subpats {
                 self.check_pat(
                     pat,
                     Ty::new_error(tcx, e),
-                    PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
+                    PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
                 );
             }
         };
@@ -1162,7 +1166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.check_pat(
                     subpat,
                     field_ty,
-                    PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
+                    PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
                 );
 
                 self.tcx.check_stability(
@@ -1347,7 +1351,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         elements: &'tcx [Pat<'tcx>],
         ddpos: hir::DotDotPos,
         expected: Ty<'tcx>,
-        pat_info: PatInfo<'tcx>,
+        pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let mut expected_len = elements.len();
@@ -1394,7 +1398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         variant: &'tcx ty::VariantDef,
         fields: &'tcx [hir::PatField<'tcx>],
         has_rest_pat: bool,
-        pat_info: PatInfo<'tcx>,
+        pat_info: PatInfo<'tcx, '_>,
     ) -> bool {
         let tcx = self.tcx;
 
@@ -2004,7 +2008,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         inner: &'tcx Pat<'tcx>,
         expected: Ty<'tcx>,
-        pat_info: PatInfo<'tcx>,
+        pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let (box_ty, inner_ty) = match self.check_dereferenceable(span, expected, inner) {
@@ -2035,7 +2039,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         inner: &'tcx Pat<'tcx>,
         mutbl: hir::Mutability,
         expected: Ty<'tcx>,
-        pat_info: PatInfo<'tcx>,
+        pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let expected = self.shallow_resolve(expected);
@@ -2139,9 +2143,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ///
     /// If we're in an irrefutable pattern we prefer the array impl candidate given that
     /// the slice impl candidate would be be rejected anyway (if no ambiguity existed).
-    fn pat_is_irrefutable(&self, decl_ctxt: Option<DeclContext>) -> bool {
-        if let Some(decl_ctxt) = decl_ctxt {
-            !decl_ctxt.has_else && matches!(decl_ctxt.origin, DeclOrigin::LocalDecl)
+    fn pat_is_irrefutable(&self, decl_origin: Option<DeclOrigin<'_>>) -> bool {
+        if let Some(decl_origin) = decl_origin {
+            decl_origin.try_get_els().is_none()
+                && matches!(decl_origin, DeclOrigin::LocalDecl { .. })
         } else {
             false
         }
@@ -2164,11 +2169,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         slice: Option<&'tcx Pat<'tcx>>,
         after: &'tcx [Pat<'tcx>],
         expected: Ty<'tcx>,
-        pat_info: PatInfo<'tcx>,
+        pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
         // If the pattern is irrefutable and `expected` is an infer ty, we try to equate it
         // to an array if the given pattern allows it. See issue #76342
-        if self.pat_is_irrefutable(pat_info.decl_ctxt) && expected.is_ty_var() {
+        if self.pat_is_irrefutable(pat_info.decl_origin) && expected.is_ty_var() {
             if let Some(resolved_arr_ty) =
                 self.try_resolve_slice_ty_to_array_ty(before, slice, span)
             {