diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 8b4a0840df583..cacc36b616a1e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -471,9 +471,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // two imports. for new_node_id in [id1, id2] { let new_id = self.resolver.local_def_id(new_node_id); - let res = if let Some(res) = resolutions.next() { - res - } else { + let Some(res) = resolutions.next() else { // Associate an HirId to both ids even if there is no resolution. let _old = self .node_id_to_hir_id diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a594339296f32..b1e601516ab97 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -32,6 +32,7 @@ #![feature(crate_visibility_modifier)] #![feature(box_patterns)] +#![feature(let_else)] #![feature(never_type)] #![recursion_limit = "256"] #![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))] diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index bab50df3dd543..8c5beb1025803 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -217,85 +217,81 @@ where let mut issue_num = None; let mut is_soft = false; for meta in metas { - if let Some(mi) = meta.meta_item() { - match mi.name_or_empty() { - sym::feature => { - if !get(mi, &mut feature) { - continue 'outer; - } + let Some(mi) = meta.meta_item() else { + handle_errors( + &sess.parse_sess, + meta.span(), + AttrError::UnsupportedLiteral("unsupported literal", false), + ); + continue 'outer; + }; + match mi.name_or_empty() { + sym::feature => { + if !get(mi, &mut feature) { + continue 'outer; } - sym::reason => { - if !get(mi, &mut reason) { - continue 'outer; - } + } + sym::reason => { + if !get(mi, &mut reason) { + continue 'outer; + } + } + sym::issue => { + if !get(mi, &mut issue) { + continue 'outer; } - sym::issue => { - if !get(mi, &mut issue) { - continue 'outer; - } - // These unwraps are safe because `get` ensures the meta item - // is a name/value pair string literal. - issue_num = match issue.unwrap().as_str() { - "none" => None, - issue => { - let emit_diag = |msg: &str| { - struct_span_err!( - diagnostic, - mi.span, - E0545, - "`issue` must be a non-zero numeric string \ - or \"none\"", - ) - .span_label( - mi.name_value_literal_span().unwrap(), - msg, - ) - .emit(); - }; - match issue.parse() { - Ok(0) => { - emit_diag( - "`issue` must not be \"0\", \ - use \"none\" instead", - ); - continue 'outer; - } - Ok(num) => NonZeroU32::new(num), - Err(err) => { - emit_diag(&err.to_string()); - continue 'outer; - } + // These unwraps are safe because `get` ensures the meta item + // is a name/value pair string literal. + issue_num = match issue.unwrap().as_str() { + "none" => None, + issue => { + let emit_diag = |msg: &str| { + struct_span_err!( + diagnostic, + mi.span, + E0545, + "`issue` must be a non-zero numeric string \ + or \"none\"", + ) + .span_label(mi.name_value_literal_span().unwrap(), msg) + .emit(); + }; + match issue.parse() { + Ok(0) => { + emit_diag( + "`issue` must not be \"0\", \ + use \"none\" instead", + ); + continue 'outer; + } + Ok(num) => NonZeroU32::new(num), + Err(err) => { + emit_diag(&err.to_string()); + continue 'outer; } } - }; - } - sym::soft => { - if !mi.is_word() { - let msg = "`soft` should not have any arguments"; - sess.parse_sess.span_diagnostic.span_err(mi.span, msg); } - is_soft = true; - } - _ => { - handle_errors( - &sess.parse_sess, - meta.span(), - AttrError::UnknownMetaItem( - pprust::path_to_string(&mi.path), - &["feature", "reason", "issue", "soft"], - ), - ); - continue 'outer; + }; + } + sym::soft => { + if !mi.is_word() { + let msg = "`soft` should not have any arguments"; + sess.parse_sess.span_diagnostic.span_err(mi.span, msg); } + is_soft = true; + } + _ => { + handle_errors( + &sess.parse_sess, + meta.span(), + AttrError::UnknownMetaItem( + pprust::path_to_string(&mi.path), + &["feature", "reason", "issue", "soft"], + ), + ); + continue 'outer; } - } else { - handle_errors( - &sess.parse_sess, - meta.span(), - AttrError::UnsupportedLiteral("unsupported literal", false), - ); - continue 'outer; } } diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs index 3fb11f77872be..c95c1c40a34c2 100644 --- a/compiler/rustc_attr/src/lib.rs +++ b/compiler/rustc_attr/src/lib.rs @@ -4,6 +4,8 @@ //! The goal is to move the definition of `MetaItem` and things that don't need to be in `syntax` //! to this crate. +#![feature(let_else)] + #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 01cc72121c7d4..3409f14c98b73 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -311,43 +311,39 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ty::BoundRegionKind::BrEnv => { let def_ty = self.regioncx.universal_regions().defining_ty; - if let DefiningTy::Closure(_, substs) = def_ty { - let args_span = if let hir::ExprKind::Closure(_, _, _, span, _) = - tcx.hir().expect_expr(self.mir_hir_id()).kind - { - span - } else { - bug!("Closure is not defined by a closure expr"); - }; - let region_name = self.synthesize_region_name(); - - let closure_kind_ty = substs.as_closure().kind_ty(); - let note = match closure_kind_ty.to_opt_closure_kind() { - Some(ty::ClosureKind::Fn) => { - "closure implements `Fn`, so references to captured variables \ - can't escape the closure" - } - Some(ty::ClosureKind::FnMut) => { - "closure implements `FnMut`, so references to captured variables \ - can't escape the closure" - } - Some(ty::ClosureKind::FnOnce) => { - bug!("BrEnv in a `FnOnce` closure"); - } - None => bug!("Closure kind not inferred in borrow check"), - }; - - Some(RegionName { - name: region_name, - source: RegionNameSource::SynthesizedFreeEnvRegion( - args_span, - note.to_string(), - ), - }) - } else { + let DefiningTy::Closure(_, substs) = def_ty else { // Can't have BrEnv in functions, constants or generators. bug!("BrEnv outside of closure."); - } + }; + let hir::ExprKind::Closure(_, _, _, args_span, _) = + tcx.hir().expect_expr(self.mir_hir_id()).kind else { + bug!("Closure is not defined by a closure expr"); + }; + let region_name = self.synthesize_region_name(); + + let closure_kind_ty = substs.as_closure().kind_ty(); + let note = match closure_kind_ty.to_opt_closure_kind() { + Some(ty::ClosureKind::Fn) => { + "closure implements `Fn`, so references to captured variables \ + can't escape the closure" + } + Some(ty::ClosureKind::FnMut) => { + "closure implements `FnMut`, so references to captured variables \ + can't escape the closure" + } + Some(ty::ClosureKind::FnOnce) => { + bug!("BrEnv in a `FnOnce` closure"); + } + None => bug!("Closure kind not inferred in borrow check"), + }; + + Some(RegionName { + name: region_name, + source: RegionNameSource::SynthesizedFreeEnvRegion( + args_span, + note.to_string(), + ), + }) } ty::BoundRegionKind::BrAnon(_) => None, @@ -765,48 +761,45 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> { let hir = self.infcx.tcx.hir(); - if let hir::TyKind::OpaqueDef(id, _) = hir_ty.kind { - let opaque_ty = hir.item(id); - if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { - bounds: - [ - hir::GenericBound::LangItemTrait( - hir::LangItem::Future, - _, - _, - hir::GenericArgs { - bindings: - [ - hir::TypeBinding { - ident: Ident { name: sym::Output, .. }, - kind: - hir::TypeBindingKind::Equality { - term: hir::Term::Ty(ty), - }, - .. - }, - ], - .. - }, - ), - ], - .. - }) = opaque_ty.kind - { - ty - } else { - span_bug!( - hir_ty.span, - "bounds from lowered return type of async fn did not match expected format: {:?}", - opaque_ty - ); - } - } else { + let hir::TyKind::OpaqueDef(id, _) = hir_ty.kind else { span_bug!( hir_ty.span, "lowered return type of async fn is not OpaqueDef: {:?}", hir_ty ); + }; + let opaque_ty = hir.item(id); + if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { + bounds: + [ + hir::GenericBound::LangItemTrait( + hir::LangItem::Future, + _, + _, + hir::GenericArgs { + bindings: + [ + hir::TypeBinding { + ident: Ident { name: sym::Output, .. }, + kind: + hir::TypeBindingKind::Equality { term: hir::Term::Ty(ty) }, + .. + }, + ], + .. + }, + ), + ], + .. + }) = opaque_ty.kind + { + ty + } else { + span_bug!( + hir_ty.span, + "bounds from lowered return type of async fn did not match expected format: {:?}", + opaque_ty + ); } } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index c288cc96990c2..5597a8b091554 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1427,9 +1427,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { bug!("temporary should be initialized exactly once") }; - let loc = match init.location { - InitLocation::Statement(stmt) => stmt, - _ => bug!("temporary initialized in arguments"), + let InitLocation::Statement(loc) = init.location else { + bug!("temporary initialized in arguments") }; let body = self.body; diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 3294f2cf64172..6329bcee4fa3f 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -602,33 +602,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { for binding in &candidate_ref.bindings { let local = self.var_local_id(binding.var_id, OutsideGuard); - if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( + let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. }, - )))) = self.local_decls[local].local_info - { - // `try_upvars_resolved` may fail if it is unable to resolve the given - // `PlaceBuilder` inside a closure. In this case, we don't want to include - // a scrutinee place. `scrutinee_place_builder` will fail for destructured - // assignments. This is because a closure only captures the precise places - // that it will read and as a result a closure may not capture the entire - // tuple/struct and rather have individual places that will be read in the - // final MIR. - // Example: - // ``` - // let foo = (0, 1); - // let c = || { - // let (v1, v2) = foo; - // }; - // ``` - if let Ok(match_pair_resolved) = - initializer.clone().try_upvars_resolved(self.tcx, self.typeck_results) - { - let place = - match_pair_resolved.into_place(self.tcx, self.typeck_results); - *match_place = Some(place); - } - } else { + )))) = self.local_decls[local].local_info else { bug!("Let binding to non-user variable.") + }; + // `try_upvars_resolved` may fail if it is unable to resolve the given + // `PlaceBuilder` inside a closure. In this case, we don't want to include + // a scrutinee place. `scrutinee_place_builder` will fail for destructured + // assignments. This is because a closure only captures the precise places + // that it will read and as a result a closure may not capture the entire + // tuple/struct and rather have individual places that will be read in the + // final MIR. + // Example: + // ``` + // let foo = (0, 1); + // let c = || { + // let (v1, v2) = foo; + // }; + // ``` + if let Ok(match_pair_resolved) = + initializer.clone().try_upvars_resolved(self.tcx, self.typeck_results) + { + let place = match_pair_resolved.into_place(self.tcx, self.typeck_results); + *match_place = Some(place); } } // All of the subcandidates should bind the same locals, so we diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index f4bf28bfa5ce2..49cd21c2137b7 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -227,16 +227,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let target_blocks = make_target_blocks(self); let terminator = if *switch_ty.kind() == ty::Bool { assert!(!options.is_empty() && options.len() <= 2); - if let [first_bb, second_bb] = *target_blocks { - let (true_bb, false_bb) = match options[0] { - 1 => (first_bb, second_bb), - 0 => (second_bb, first_bb), - v => span_bug!(test.span, "expected boolean value but got {:?}", v), - }; - TerminatorKind::if_(self.tcx, Operand::Copy(place), true_bb, false_bb) - } else { + let [first_bb, second_bb] = *target_blocks else { bug!("`TestKind::SwitchInt` on `bool` should have two targets") - } + }; + let (true_bb, false_bb) = match options[0] { + 1 => (first_bb, second_bb), + 0 => (second_bb, first_bb), + v => span_bug!(test.span, "expected boolean value but got {:?}", v), + }; + TerminatorKind::if_(self.tcx, Operand::Copy(place), true_bb, false_bb) } else { // The switch may be inexhaustive so we have a catch all block debug_assert_eq!(options.len() + 1, target_blocks.len()); @@ -285,24 +284,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let hi = self.literal_operand(test.span, hi); let val = Operand::Copy(place); - if let [success, fail] = *target_blocks { - self.compare( - block, - lower_bound_success, - fail, - source_info, - BinOp::Le, - lo, - val.clone(), - ); - let op = match *end { - RangeEnd::Included => BinOp::Le, - RangeEnd::Excluded => BinOp::Lt, - }; - self.compare(lower_bound_success, success, fail, source_info, op, val, hi); - } else { + let [success, fail] = *target_blocks else { bug!("`TestKind::Range` should have two target blocks"); - } + }; + self.compare( + block, + lower_bound_success, + fail, + source_info, + BinOp::Le, + lo, + val.clone(), + ); + let op = match *end { + RangeEnd::Included => BinOp::Le, + RangeEnd::Excluded => BinOp::Lt, + }; + self.compare(lower_bound_success, success, fail, source_info, op, val, hi); } TestKind::Len { len, op } => { @@ -317,21 +315,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // expected = let expected = self.push_usize(block, source_info, len); - if let [true_bb, false_bb] = *target_blocks { - // result = actual == expected OR result = actual < expected - // branch based on result - self.compare( - block, - true_bb, - false_bb, - source_info, - op, - Operand::Move(actual), - Operand::Move(expected), - ); - } else { + let [true_bb, false_bb] = *target_blocks else { bug!("`TestKind::Len` should have two target blocks"); - } + }; + // result = actual == expected OR result = actual < expected + // branch based on result + self.compare( + block, + true_bb, + false_bb, + source_info, + op, + Operand::Move(actual), + Operand::Move(expected), + ); } } } @@ -459,16 +456,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ); self.diverge_from(block); - if let [success_block, fail_block] = *make_target_blocks(self) { - // check the result - self.cfg.terminate( - eq_block, - source_info, - TerminatorKind::if_(self.tcx, Operand::Move(eq_result), success_block, fail_block), - ); - } else { + let [success_block, fail_block] = *make_target_blocks(self) else { bug!("`TestKind::Eq` should have two target blocks") - } + }; + // check the result + self.cfg.terminate( + eq_block, + source_info, + TerminatorKind::if_(self.tcx, Operand::Move(eq_result), success_block, fail_block), + ); } /// Given that we are performing `test` against `test_place`, this job diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 8b4ab77dffb5f..a3f7e84b1d524 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -47,11 +47,10 @@ use rls_data::{ use tracing::{debug, error}; +#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5213 macro_rules! down_cast_data { ($id:ident, $kind:ident, $sp:expr) => { - let $id = if let super::Data::$kind(data) = $id { - data - } else { + let super::Data::$kind($id) = $id else { span_bug!($sp, "unexpected data kind: {:?}", $id); }; }; diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index c14b459570f5e..2eebddb47df5c 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -1,6 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(if_let_guard)] #![feature(nll)] +#![feature(let_else)] #![recursion_limit = "256"] #![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]