Change:
Encountered an ICE when building  0.18.0 on edition 2021. I have roughly narrowed it down to the following (can probably be reduced further). Seems to be an issue with closure captures. <!-- If you're using the stable version of the compiler, you should also check if the bug also exists in the beta or nightly versions. --: <!-- Include a backtrace in the code block by setting in your environment. E.g. . --<details<summary<strongBacktrace</strong</summary<p</p</detailscc <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOT_END --
The code can be further simplified to: The issue seems to be around using type annotation. If a type annotation is included, the right hand side of the let statement should always be read.
Is there a runtime check/ is MIR generated for checking if is valid? Because if that's the case then we need props2 to be caputred.
claim I should have a fix later tonight
We found another instance of this ICE that still fails with included: Found trying to migrate . Let me know if you need any more information.

Discussion:
ascription: thir::Ascription { variance, user_ty, user_ty_span }, } => { // Apply the type ascription to the value at `match_pair.place`, which is the <del> candidate.ascriptions.push(Ascription { span: user_ty_span, user_ty, source: match_pair.place.clone().into_place(self.tcx, self.typeck_results), variance, }); </del> <ins> if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self.tcx, self.typeck_results) { candidate.ascriptions.push(Ascription { span: user_ty_span, user_ty, source: place_resolved.into_place(self.tcx, self.typeck_results), variance, }); } </ins> candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern));

} PatKind::Binding { name, mutability, mode, var, ty, ref subpattern, is_primary: _ } => { <del> candidate.bindings.push(Binding { name, mutability, span: match_pair.pattern.span, source: match_pair.place.clone().into_place(self.tcx, self.typeck_results), var_id: var, var_ty: ty, binding_mode: mode, }); </del> <ins> if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self.tcx, self.typeck_results) { candidate.bindings.push(Binding { name, mutability, span: match_pair.pattern.span, source: place_resolved.into_place(self.tcx, self.typeck_results), var_id: var, var_ty: ty, binding_mode: mode, }); } </ins> if let Some(subpattern) = subpattern.as_ref() { // this is the `x @ P` case; have to keep matching against `P` now

suffix: &'pat [Pat<'tcx>], ) { let tcx = self.tcx; <del> let (min_length, exact_size) = match place .clone() .into_place(tcx, self.typeck_results) .ty(&self.local_decls, tcx) .ty .kind() </del> <ins> let (min_length, exact_size) = if let Ok(place_resolved) = place.clone().try_upvars_resolved(tcx, self.typeck_results) </ins> { <del> ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true), _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false), </del> <ins> match place_resolved .into_place(tcx, self.typeck_results) .ty(&self.local_decls, tcx) .ty .kind() { ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true), _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false), } } else { ((prefix.len() + suffix.len()).try_into().unwrap(), false) </ins> }; match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| {

<ins> // run-pass // edition:2021 struct Props { field_1: u32, //~ WARNING: field is never read: `field_1` field_2: u32, //~ WARNING: field is never read: `field_2` } fn main() { // Test 1 let props_2 = Props { //~ WARNING: unused variable: `props_2` field_1: 1, field_2: 1, }; let _ = || { let _: Props = props_2; }; // Test 2 let mut arr = [1, 3, 4, 5]; let mref = &mut arr; let _c = || match arr { [_, _, _, _] => println!("A") }; println!("{:#?}", mref); } </ins>

<ins> warning: unused variable: `props_2` --> $DIR/issue-87987.rs:11:9 | LL |     let props_2 = Props { |         ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_props_2` | = note: `#[warn(unused_variables)]` on by default warning: field is never read: `field_1` --> $DIR/issue-87987.rs:5:5 | LL |     field_1: u32, |     ^^^^^^^^^^^^ | = note: `#[warn(dead_code)]` on by default warning: field is never read: `field_2` --> $DIR/issue-87987.rs:6:5 | LL |     field_2: u32, |     ^^^^^^^^^^^^ warning: 3 warnings emitted </ins>