diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 2c1543ca1d5..70ae21d9b98 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1478,7 +1478,7 @@ pub(in super::super) fn check_decl(&self, decl: Declaration<'tcx>) { 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.origin.try_get_els() { + if let Some(blk) = decl.origin.try_get_else() { 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 b2b6ad0d101..ed4c63f171c 100644 --- a/compiler/rustc_hir_typeck/src/gather_locals.rs +++ b/compiler/rustc_hir_typeck/src/gather_locals.rs @@ -21,7 +21,7 @@ pub(super) enum DeclOrigin<'a> { } impl<'a> DeclOrigin<'a> { - pub(super) fn try_get_els(&self) -> Option<&'a hir::Block<'a>> { + pub(super) fn try_get_else(&self) -> Option<&'a hir::Block<'a>> { match self { Self::LocalDecl { els } => *els, Self::LetExpr => None, diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 659223a377c..8e14212fd56 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -163,7 +163,7 @@ pub(crate) fn check_pat_top( /// 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_origin } = pat_info; + let PatInfo { binding_mode: def_bm, top_info: ti, .. } = 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)) @@ -172,76 +172,39 @@ fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo< }; let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res)); let (expected, def_bm) = self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode); + let pat_info = + PatInfo { binding_mode: def_bm, top_info: ti, decl_origin: pat_info.decl_origin }; let ty = match pat.kind { PatKind::Wild => expected, PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti), PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti), - PatKind::Binding(ba, var_id, _, sub) => self.check_pat_ident( - pat, - ba, - var_id, - sub, - expected, - PatInfo { binding_mode: def_bm, top_info: ti, decl_origin }, - ), - PatKind::TupleStruct(ref qpath, subpats, ddpos) => self.check_pat_tuple_struct( - pat, - qpath, - subpats, - ddpos, - expected, - PatInfo { binding_mode: def_bm, top_info: ti, decl_origin }, - ), + PatKind::Binding(ba, var_id, _, sub) => { + self.check_pat_ident(pat, ba, var_id, sub, expected, pat_info) + } + PatKind::TupleStruct(ref qpath, subpats, ddpos) => { + self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info) + } PatKind::Path(ref qpath) => { self.check_pat_path(pat, qpath, path_res.unwrap(), expected, ti) } - PatKind::Struct(ref qpath, fields, has_rest_pat) => self.check_pat_struct( - pat, - qpath, - fields, - has_rest_pat, - expected, - PatInfo { binding_mode: def_bm, top_info: ti, decl_origin }, - ), + PatKind::Struct(ref qpath, fields, has_rest_pat) => { + self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info) + } PatKind::Or(pats) => { for pat in pats { - self.check_pat( - pat, - expected, - PatInfo { binding_mode: def_bm, top_info: ti, decl_origin }, - ); + self.check_pat(pat, expected, pat_info); } expected } - PatKind::Tuple(elements, ddpos) => self.check_pat_tuple( - pat.span, - elements, - ddpos, - expected, - 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_origin }, - ), - PatKind::Ref(inner, mutbl) => self.check_pat_ref( - pat, - inner, - mutbl, - expected, - PatInfo { binding_mode: def_bm, top_info: ti, decl_origin }, - ), - PatKind::Slice(before, slice, after) => self.check_pat_slice( - pat.span, - before, - slice, - after, - expected, - PatInfo { binding_mode: def_bm, top_info: ti, decl_origin }, - ), + PatKind::Tuple(elements, ddpos) => { + self.check_pat_tuple(pat.span, elements, ddpos, expected, pat_info) + } + PatKind::Box(inner) => self.check_pat_box(pat.span, inner, expected, pat_info), + PatKind::Ref(inner, mutbl) => self.check_pat_ref(pat, inner, mutbl, expected, pat_info), + PatKind::Slice(before, slice, after) => { + self.check_pat_slice(pat.span, before, slice, after, expected, pat_info) + } }; self.write_ty(pat.hir_id, ty); @@ -624,7 +587,7 @@ fn check_pat_ident( expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx> { - let PatInfo { binding_mode: def_bm, top_info: ti, decl_origin } = pat_info; + let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info; // Determine the binding mode... let bm = match ba { @@ -663,11 +626,7 @@ fn check_pat_ident( } if let Some(p) = sub { - self.check_pat( - p, - expected, - PatInfo { binding_mode: def_bm, top_info: ti, decl_origin }, - ); + self.check_pat(p, expected, pat_info); } local_ty @@ -892,37 +851,23 @@ fn check_pat_struct( expected: Ty<'tcx>, pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx> { - 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) { Ok(data) => data, Err(guar) => { let err = Ty::new_error(self.tcx, guar); for field in fields { - let ti = ti; - self.check_pat( - field.pat, - err, - PatInfo { binding_mode: def_bm, top_info: ti, decl_origin }, - ); + self.check_pat(field.pat, err, pat_info); } return err; } }; // Type-check the path. - self.demand_eqtype_pat(pat.span, expected, pat_ty, ti); + self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info); // Type-check subpatterns. - if self.check_struct_pat_fields( - pat_ty, - &pat, - variant, - fields, - has_rest_pat, - PatInfo { binding_mode: def_bm, top_info: ti, decl_origin }, - ) { + if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, has_rest_pat, pat_info) { pat_ty } else { Ty::new_misc_error(self.tcx) @@ -2144,11 +2089,9 @@ fn try_resolve_slice_ty_to_array_ty( /// 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_origin: Option>) -> bool { - if let Some(decl_origin) = decl_origin { - decl_origin.try_get_els().is_none() - && matches!(decl_origin, DeclOrigin::LocalDecl { .. }) - } else { - false + match decl_origin { + Some(DeclOrigin::LocalDecl { els: None }) => true, + Some(DeclOrigin::LocalDecl { els: Some(_) } | DeclOrigin::LetExpr) | None => false, } } @@ -2183,6 +2126,8 @@ fn check_pat_slice( } let expected = self.structurally_resolve_type(span, expected); + debug!(?expected); + let (element_ty, opt_slice_ty, inferred) = match *expected.kind() { // An array, so we might have something like `let [a, b, c] = [0, 1, 2];`. ty::Array(element_ty, len) => { diff --git a/tests/ui/array-slice-vec/slice-pat-type-mismatches.rs b/tests/ui/array-slice-vec/slice-pat-type-mismatches.rs index 310c49701ed..03a1876fdc5 100644 --- a/tests/ui/array-slice-vec/slice-pat-type-mismatches.rs +++ b/tests/ui/array-slice-vec/slice-pat-type-mismatches.rs @@ -30,9 +30,8 @@ fn main() { } fn another_fn_to_avoid_suppression() { - match Default - //~^ ERROR expected value, found trait - { + match Default::default() { [] => {} + //~^ ERROR type annotations needed }; } diff --git a/tests/ui/array-slice-vec/slice-pat-type-mismatches.stderr b/tests/ui/array-slice-vec/slice-pat-type-mismatches.stderr index 6218bffd503..d1d042c4776 100644 --- a/tests/ui/array-slice-vec/slice-pat-type-mismatches.stderr +++ b/tests/ui/array-slice-vec/slice-pat-type-mismatches.stderr @@ -4,12 +4,6 @@ error[E0425]: cannot find value `does_not_exist` in this scope LL | match does_not_exist { | ^^^^^^^^^^^^^^ not found in this scope -error[E0423]: expected value, found trait `Default` - --> $DIR/slice-pat-type-mismatches.rs:33:11 - | -LL | match Default - | ^^^^^^^ not a value - error[E0529]: expected an array or slice, found `String` --> $DIR/slice-pat-type-mismatches.rs:3:9 | @@ -28,7 +22,13 @@ error[E0528]: pattern requires at least 4 elements but array has 3 LL | [0, 1, 2, 3, x @ ..] => {} | ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements +error[E0282]: type annotations needed + --> $DIR/slice-pat-type-mismatches.rs:34:9 + | +LL | [] => {} + | ^^ cannot infer type + error: aborting due to 5 previous errors -Some errors have detailed explanations: E0423, E0425, E0527, E0528, E0529. -For more information about an error, try `rustc --explain E0423`. +Some errors have detailed explanations: E0282, E0425, E0527, E0528, E0529. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/pattern/issue-76342.rs b/tests/ui/pattern/issue-76342.rs index 0d066a12179..e4d3218104e 100644 --- a/tests/ui/pattern/issue-76342.rs +++ b/tests/ui/pattern/issue-76342.rs @@ -1,4 +1,7 @@ // check-pass + +// Test that we infer the expected type of a pattern to an array of the given length. + #![allow(unused_variables)] struct Zeroes; impl Into<[usize; 2]> for Zeroes { diff --git a/tests/ui/pattern/slice-pattern-refutable.rs b/tests/ui/pattern/slice-pattern-refutable.rs index 3961da3bf53..1be3c6ef82d 100644 --- a/tests/ui/pattern/slice-pattern-refutable.rs +++ b/tests/ui/pattern/slice-pattern-refutable.rs @@ -1,3 +1,5 @@ +// Test that we do not infer the expected types of patterns to an array +// if we're in a refutable pattern. #![allow(unused_variables)] struct Zeroes; diff --git a/tests/ui/pattern/slice-pattern-refutable.stderr b/tests/ui/pattern/slice-pattern-refutable.stderr index cb5503bac39..df5b58d3e9c 100644 --- a/tests/ui/pattern/slice-pattern-refutable.stderr +++ b/tests/ui/pattern/slice-pattern-refutable.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/slice-pattern-refutable.rs:12:9 + --> $DIR/slice-pattern-refutable.rs:14:9 | LL | let [a, b, c] = Zeroes.into() else { | ^^^^^^^^^ @@ -10,7 +10,7 @@ LL | let [a, b, c]: /* Type */ = Zeroes.into() else { | ++++++++++++ error[E0282]: type annotations needed - --> $DIR/slice-pattern-refutable.rs:19:31 + --> $DIR/slice-pattern-refutable.rs:21:31 | LL | if let [a, b, c] = Zeroes.into() { | --------- ^^^^ @@ -23,7 +23,7 @@ LL | if let [a, b, c] = >::into(Zeroes) { | ++++++++++++++++++++++++++ ~ error[E0282]: type annotations needed - --> $DIR/slice-pattern-refutable.rs:26:31 + --> $DIR/slice-pattern-refutable.rs:28:31 | LL | if let [a, b, c] = Zeroes.into() { | --------- ^^^^