Skip to content

Commit b3413c6

Browse files
committed
only infer array type on irrefutable patterns
1 parent e18e376 commit b3413c6

File tree

5 files changed

+138
-40
lines changed

5 files changed

+138
-40
lines changed

compiler/rustc_hir_typeck/src/_match.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4141
// #55810: Type check patterns first so we get types for all bindings.
4242
let scrut_span = scrut.span.find_ancestor_inside(expr.span).unwrap_or(scrut.span);
4343
for arm in arms {
44-
self.check_pat_top(&arm.pat, scrutinee_ty, Some(scrut_span), Some(scrut));
44+
self.check_pat_top(&arm.pat, scrutinee_ty, Some(scrut_span), Some(scrut), None);
4545
}
4646

4747
// Now typecheck the blocks.

compiler/rustc_hir_typeck/src/check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ pub(super) fn check_fn<'a, 'tcx>(
8989
for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() {
9090
// Check the pattern.
9191
let ty_span = try { inputs_hir?.get(idx)?.span };
92-
fcx.check_pat_top(&param.pat, param_ty, ty_span, None);
92+
fcx.check_pat_top(&param.pat, param_ty, ty_span, None, None);
9393

9494
// Check that argument is Sized.
9595
if !params_can_be_unsized {

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

Lines changed: 3 additions & 2 deletions
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::Declaration;
4+
use crate::gather_locals::{DeclContext, Declaration};
55
use crate::method::MethodCallee;
66
use crate::TupleArgumentsFlag::*;
77
use crate::{errors, Expectation::*};
@@ -1474,7 +1474,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14741474
};
14751475

14761476
// Type check the pattern. Override if necessary to avoid knock-on errors.
1477-
self.check_pat_top(&decl.pat, decl_ty, ty_span, origin_expr);
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));
14781479
let pat_ty = self.node_ty(decl.pat.hir_id);
14791480
self.overwrite_local_ty_if_err(decl.hir_id, decl.pat, pat_ty);
14801481

compiler/rustc_hir_typeck/src/gather_locals.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,24 @@ use rustc_span::def_id::LocalDefId;
99
use rustc_span::Span;
1010
use rustc_trait_selection::traits;
1111

12+
#[derive(Debug, Copy, Clone)]
13+
pub(super) enum DeclOrigin {
14+
// from an `if let` expression
15+
LetExpr,
16+
// from `let x = ..`
17+
LocalDecl,
18+
}
19+
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,
28+
}
29+
1230
/// A declaration is an abstraction of [hir::Local] and [hir::Let].
1331
///
1432
/// It must have a hir_id, as this is how we connect gather_locals to the check functions.
@@ -19,19 +37,28 @@ pub(super) struct Declaration<'a> {
1937
pub span: Span,
2038
pub init: Option<&'a hir::Expr<'a>>,
2139
pub els: Option<&'a hir::Block<'a>>,
40+
pub origin: DeclOrigin,
2241
}
2342

2443
impl<'a> From<&'a hir::Local<'a>> for Declaration<'a> {
2544
fn from(local: &'a hir::Local<'a>) -> Self {
2645
let hir::Local { hir_id, pat, ty, span, init, els, source: _ } = *local;
27-
Declaration { hir_id, pat, ty, span, init, els }
46+
Declaration { hir_id, pat, ty, span, init, els, origin: DeclOrigin::LocalDecl }
2847
}
2948
}
3049

3150
impl<'a> From<&'a hir::Let<'a>> for Declaration<'a> {
3251
fn from(let_expr: &'a hir::Let<'a>) -> Self {
3352
let hir::Let { hir_id, pat, ty, span, init } = *let_expr;
34-
Declaration { hir_id, pat, ty, span, init: Some(init), els: None }
53+
Declaration {
54+
hir_id,
55+
pat,
56+
ty,
57+
span,
58+
init: Some(init),
59+
els: None,
60+
origin: DeclOrigin::LetExpr,
61+
}
3562
}
3663
}
3764

0 commit comments

Comments
 (0)