Skip to content

Commit 1c217b6

Browse files
committed
move els into DeclOrigin
1 parent 843e2ee commit 1c217b6

File tree

3 files changed

+58
-61
lines changed

3 files changed

+58
-61
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::coercion::CoerceMany;
22
use crate::errors::SuggestPtrNullMut;
33
use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
4-
use crate::gather_locals::{DeclContext, Declaration};
4+
use crate::gather_locals::Declaration;
55
use crate::method::MethodCallee;
66
use crate::TupleArgumentsFlag::*;
77
use crate::{errors, Expectation::*};
@@ -1474,12 +1474,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14741474
};
14751475

14761476
// Type check the pattern. Override if necessary to avoid knock-on errors.
1477-
let decl_ctxt = DeclContext { has_else: decl.els.is_some(), origin: decl.origin };
1478-
self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr, Some(decl_ctxt));
1477+
self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr, Some(decl.origin));
14791478
let pat_ty = self.node_ty(decl.pat.hir_id);
14801479
self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
14811480

1482-
if let Some(blk) = decl.els {
1481+
if let Some(blk) = decl.origin.try_get_els() {
14831482
let previous_diverges = self.diverges.get();
14841483
let else_ty = self.check_block_with_expected(blk, NoExpectation);
14851484
let cause = self.cause(blk.span, ObligationCauseCode::LetElse);

compiler/rustc_hir_typeck/src/gather_locals.rs

+15-22
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,24 @@ use rustc_span::def_id::LocalDefId;
99
use rustc_span::Span;
1010
use rustc_trait_selection::traits;
1111

12+
/// Provides context for checking patterns in declarations. More specifically this
13+
/// allows us to infer array types if the pattern is irrefutable and allows us to infer
14+
/// the size of the array. See issue #76342.
1215
#[derive(Debug, Copy, Clone)]
13-
pub(super) enum DeclOrigin {
16+
pub(super) enum DeclOrigin<'a> {
1417
// from an `if let` expression
1518
LetExpr,
1619
// from `let x = ..`
17-
LocalDecl,
20+
LocalDecl { els: Option<&'a hir::Block<'a>> },
1821
}
1922

20-
/// Provides context for checking patterns in declarations. More specifically this
21-
/// allows us to infer array types if the pattern is irrefutable and allows us to infer
22-
/// the size of the array. See issue #76342.
23-
#[derive(Debug, Copy, Clone)]
24-
pub(crate) struct DeclContext {
25-
// whether we're in a let-else context
26-
pub(super) has_else: bool,
27-
pub(super) origin: DeclOrigin,
23+
impl<'a> DeclOrigin<'a> {
24+
pub(super) fn try_get_els(&self) -> Option<&'a hir::Block<'a>> {
25+
match self {
26+
Self::LocalDecl { els } => *els,
27+
Self::LetExpr => None,
28+
}
29+
}
2830
}
2931

3032
/// A declaration is an abstraction of [hir::Local] and [hir::Let].
@@ -36,29 +38,20 @@ pub(super) struct Declaration<'a> {
3638
pub ty: Option<&'a hir::Ty<'a>>,
3739
pub span: Span,
3840
pub init: Option<&'a hir::Expr<'a>>,
39-
pub els: Option<&'a hir::Block<'a>>,
40-
pub origin: DeclOrigin,
41+
pub origin: DeclOrigin<'a>,
4142
}
4243

4344
impl<'a> From<&'a hir::Local<'a>> for Declaration<'a> {
4445
fn from(local: &'a hir::Local<'a>) -> Self {
4546
let hir::Local { hir_id, pat, ty, span, init, els, source: _ } = *local;
46-
Declaration { hir_id, pat, ty, span, init, els, origin: DeclOrigin::LocalDecl }
47+
Declaration { hir_id, pat, ty, span, init, origin: DeclOrigin::LocalDecl { els } }
4748
}
4849
}
4950

5051
impl<'a> From<&'a hir::Let<'a>> for Declaration<'a> {
5152
fn from(let_expr: &'a hir::Let<'a>) -> Self {
5253
let hir::Let { hir_id, pat, ty, span, init } = *let_expr;
53-
Declaration {
54-
hir_id,
55-
pat,
56-
ty,
57-
span,
58-
init: Some(init),
59-
els: None,
60-
origin: DeclOrigin::LetExpr,
61-
}
54+
Declaration { hir_id, pat, ty, span, init: Some(init), origin: DeclOrigin::LetExpr }
6255
}
6356
}
6457

compiler/rustc_hir_typeck/src/pat.rs

+40-35
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::gather_locals::{DeclContext, DeclOrigin};
1+
use crate::gather_locals::DeclOrigin;
22
use crate::{errors, FnCtxt, RawTy};
33
use rustc_ast as ast;
44
use rustc_data_structures::fx::FxHashMap;
@@ -79,10 +79,10 @@ struct TopInfo<'tcx> {
7979
}
8080

8181
#[derive(Copy, Clone)]
82-
struct PatInfo<'tcx> {
82+
struct PatInfo<'tcx, 'a> {
8383
binding_mode: BindingMode,
8484
top_info: TopInfo<'tcx>,
85-
decl_ctxt: Option<DeclContext>,
85+
decl_origin: Option<DeclOrigin<'a>>,
8686
}
8787

8888
impl<'tcx> FnCtxt<'_, 'tcx> {
@@ -149,10 +149,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
149149
expected: Ty<'tcx>,
150150
span: Option<Span>,
151151
origin_expr: Option<&'tcx hir::Expr<'tcx>>,
152-
decl_ctxt: Option<DeclContext>,
152+
decl_origin: Option<DeclOrigin<'tcx>>,
153153
) {
154154
let info = TopInfo { expected, origin_expr, span };
155-
let pat_info = PatInfo { binding_mode: INITIAL_BM, top_info: info, decl_ctxt };
155+
let pat_info = PatInfo { binding_mode: INITIAL_BM, top_info: info, decl_origin };
156156
self.check_pat(pat, expected, pat_info);
157157
}
158158

@@ -162,8 +162,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
162162
/// Outside of this module, `check_pat_top` should always be used.
163163
/// Conversely, inside this module, `check_pat_top` should never be used.
164164
#[instrument(level = "debug", skip(self, pat_info))]
165-
fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) {
166-
let PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt } = pat_info;
165+
fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>) {
166+
let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin } = pat_info;
167167
let path_res = match &pat.kind {
168168
PatKind::Path(qpath) => {
169169
Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span))
@@ -183,15 +183,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
183183
var_id,
184184
sub,
185185
expected,
186-
PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
186+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
187187
),
188188
PatKind::TupleStruct(ref qpath, subpats, ddpos) => self.check_pat_tuple_struct(
189189
pat,
190190
qpath,
191191
subpats,
192192
ddpos,
193193
expected,
194-
PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
194+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
195195
),
196196
PatKind::Path(ref qpath) => {
197197
self.check_pat_path(pat, qpath, path_res.unwrap(), expected, ti)
@@ -202,14 +202,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
202202
fields,
203203
has_rest_pat,
204204
expected,
205-
PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
205+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
206206
),
207207
PatKind::Or(pats) => {
208208
for pat in pats {
209209
self.check_pat(
210210
pat,
211211
expected,
212-
PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
212+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
213213
);
214214
}
215215
expected
@@ -219,28 +219,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
219219
elements,
220220
ddpos,
221221
expected,
222-
PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
222+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
223223
),
224224
PatKind::Box(inner) => self.check_pat_box(
225225
pat.span,
226226
inner,
227227
expected,
228-
PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
228+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
229229
),
230230
PatKind::Ref(inner, mutbl) => self.check_pat_ref(
231231
pat,
232232
inner,
233233
mutbl,
234234
expected,
235-
PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
235+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
236236
),
237237
PatKind::Slice(before, slice, after) => self.check_pat_slice(
238238
pat.span,
239239
before,
240240
slice,
241241
after,
242242
expected,
243-
PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
243+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
244244
),
245245
};
246246

@@ -622,9 +622,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
622622
var_id: HirId,
623623
sub: Option<&'tcx Pat<'tcx>>,
624624
expected: Ty<'tcx>,
625-
pat_info: PatInfo<'tcx>,
625+
pat_info: PatInfo<'tcx, '_>,
626626
) -> Ty<'tcx> {
627-
let PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt } = pat_info;
627+
let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin } = pat_info;
628628

629629
// Determine the binding mode...
630630
let bm = match ba {
@@ -663,7 +663,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
663663
}
664664

665665
if let Some(p) = sub {
666-
self.check_pat(p, expected, PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt });
666+
self.check_pat(
667+
p,
668+
expected,
669+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
670+
);
667671
}
668672

669673
local_ty
@@ -886,9 +890,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
886890
fields: &'tcx [hir::PatField<'tcx>],
887891
has_rest_pat: bool,
888892
expected: Ty<'tcx>,
889-
pat_info: PatInfo<'tcx>,
893+
pat_info: PatInfo<'tcx, '_>,
890894
) -> Ty<'tcx> {
891-
let PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt } = pat_info;
895+
let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin } = pat_info;
892896

893897
// Resolve the path and check the definition for errors.
894898
let (variant, pat_ty) = match self.check_struct_path(qpath, pat.hir_id) {
@@ -900,7 +904,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
900904
self.check_pat(
901905
field.pat,
902906
err,
903-
PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
907+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
904908
);
905909
}
906910
return err;
@@ -917,7 +921,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
917921
variant,
918922
fields,
919923
has_rest_pat,
920-
PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
924+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
921925
) {
922926
pat_ty
923927
} else {
@@ -1083,16 +1087,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10831087
subpats: &'tcx [Pat<'tcx>],
10841088
ddpos: hir::DotDotPos,
10851089
expected: Ty<'tcx>,
1086-
pat_info: PatInfo<'tcx>,
1090+
pat_info: PatInfo<'tcx, '_>,
10871091
) -> Ty<'tcx> {
1088-
let PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt } = pat_info;
1092+
let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin } = pat_info;
10891093
let tcx = self.tcx;
10901094
let on_error = |e| {
10911095
for pat in subpats {
10921096
self.check_pat(
10931097
pat,
10941098
Ty::new_error(tcx, e),
1095-
PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
1099+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
10961100
);
10971101
}
10981102
};
@@ -1162,7 +1166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11621166
self.check_pat(
11631167
subpat,
11641168
field_ty,
1165-
PatInfo { binding_mode: def_bm, top_info: ti, decl_ctxt },
1169+
PatInfo { binding_mode: def_bm, top_info: ti, decl_origin },
11661170
);
11671171

11681172
self.tcx.check_stability(
@@ -1347,7 +1351,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13471351
elements: &'tcx [Pat<'tcx>],
13481352
ddpos: hir::DotDotPos,
13491353
expected: Ty<'tcx>,
1350-
pat_info: PatInfo<'tcx>,
1354+
pat_info: PatInfo<'tcx, '_>,
13511355
) -> Ty<'tcx> {
13521356
let tcx = self.tcx;
13531357
let mut expected_len = elements.len();
@@ -1394,7 +1398,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13941398
variant: &'tcx ty::VariantDef,
13951399
fields: &'tcx [hir::PatField<'tcx>],
13961400
has_rest_pat: bool,
1397-
pat_info: PatInfo<'tcx>,
1401+
pat_info: PatInfo<'tcx, '_>,
13981402
) -> bool {
13991403
let tcx = self.tcx;
14001404

@@ -2004,7 +2008,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20042008
span: Span,
20052009
inner: &'tcx Pat<'tcx>,
20062010
expected: Ty<'tcx>,
2007-
pat_info: PatInfo<'tcx>,
2011+
pat_info: PatInfo<'tcx, '_>,
20082012
) -> Ty<'tcx> {
20092013
let tcx = self.tcx;
20102014
let (box_ty, inner_ty) = match self.check_dereferenceable(span, expected, inner) {
@@ -2035,7 +2039,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20352039
inner: &'tcx Pat<'tcx>,
20362040
mutbl: hir::Mutability,
20372041
expected: Ty<'tcx>,
2038-
pat_info: PatInfo<'tcx>,
2042+
pat_info: PatInfo<'tcx, '_>,
20392043
) -> Ty<'tcx> {
20402044
let tcx = self.tcx;
20412045
let expected = self.shallow_resolve(expected);
@@ -2139,9 +2143,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21392143
///
21402144
/// If we're in an irrefutable pattern we prefer the array impl candidate given that
21412145
/// the slice impl candidate would be be rejected anyway (if no ambiguity existed).
2142-
fn pat_is_irrefutable(&self, decl_ctxt: Option<DeclContext>) -> bool {
2143-
if let Some(decl_ctxt) = decl_ctxt {
2144-
!decl_ctxt.has_else && matches!(decl_ctxt.origin, DeclOrigin::LocalDecl)
2146+
fn pat_is_irrefutable(&self, decl_origin: Option<DeclOrigin<'_>>) -> bool {
2147+
if let Some(decl_origin) = decl_origin {
2148+
decl_origin.try_get_els().is_none()
2149+
&& matches!(decl_origin, DeclOrigin::LocalDecl { .. })
21452150
} else {
21462151
false
21472152
}
@@ -2164,11 +2169,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21642169
slice: Option<&'tcx Pat<'tcx>>,
21652170
after: &'tcx [Pat<'tcx>],
21662171
expected: Ty<'tcx>,
2167-
pat_info: PatInfo<'tcx>,
2172+
pat_info: PatInfo<'tcx, '_>,
21682173
) -> Ty<'tcx> {
21692174
// If the pattern is irrefutable and `expected` is an infer ty, we try to equate it
21702175
// to an array if the given pattern allows it. See issue #76342
2171-
if self.pat_is_irrefutable(pat_info.decl_ctxt) && expected.is_ty_var() {
2176+
if self.pat_is_irrefutable(pat_info.decl_origin) && expected.is_ty_var() {
21722177
if let Some(resolved_arr_ty) =
21732178
self.try_resolve_slice_ty_to_array_ty(before, slice, span)
21742179
{

0 commit comments

Comments
 (0)