Auto merge of #89933 - est31:let_else, r=michaelwoerister

Adopt let_else across the compiler

This performs a substitution of code following the pattern:

```
let <id> = if let <pat> = ... { identity } else { ... : ! };
```

To simplify it to:

```
let <pat> = ... { identity } else { ... : ! };
```

By adopting the `let_else` feature (cc #87335).

The PR also updates the syn crate because the currently used version of the crate doesn't support `let_else` syntax yet.

Note: Generally I'm the person who *removes* usages of unstable features from the compiler, not adds more usages of them, but in this instance I think it hopefully helps the feature get stabilized sooner and in a better state. I have written a [comment](https://github.com/rust-lang/rust/issues/87335#issuecomment-944846205) on the tracking issue about my experience and what I feel could be improved before stabilization of `let_else`.
This commit is contained in:
bors 2021-10-19 14:41:39 +00:00
commit 1af55d19c7
54 changed files with 76 additions and 150 deletions

View File

@ -2728,9 +2728,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
[[package]]
name = "proc-macro2"
version = "1.0.24"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70"
dependencies = [
"unicode-xid",
]
@ -5093,9 +5093,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.65"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663"
checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194"
dependencies = [
"proc-macro2",
"quote",

View File

@ -315,9 +315,7 @@ impl<'a, 'tcx> GatherBorrows<'a, 'tcx> {
// TEMP = &foo
//
// so extract `temp`.
let temp = if let Some(temp) = assigned_place.as_local() {
temp
} else {
let Some(temp) = assigned_place.as_local() else {
span_bug!(
self.body.source_info(start_location).span,
"expected 2-phase borrow to assign to a local, not `{:?}`",

View File

@ -90,9 +90,7 @@ impl OutlivesSuggestionBuilder {
let mut unified_already = FxHashSet::default();
for (fr, outlived) in &self.constraints_to_add {
let fr_name = if let Some(fr_name) = self.region_vid_to_name(mbcx, *fr) {
fr_name
} else {
let Some(fr_name) = self.region_vid_to_name(mbcx, *fr) else {
continue;
};

View File

@ -7,6 +7,7 @@
#![feature(format_args_capture)]
#![feature(in_band_lifetimes)]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(min_specialization)]
#![feature(stmt_expr_attributes)]
#![feature(trusted_step)]

View File

@ -174,9 +174,8 @@ pub fn each_linked_rlib(
_ => {}
}
}
let fmts = match fmts {
Some(f) => f,
None => return Err("could not find formats for rlibs".to_string()),
let Some(fmts) = fmts else {
return Err("could not find formats for rlibs".to_string());
};
for &cnum in crates {
match fmts.get(cnum.as_usize() - 1) {

View File

@ -3,6 +3,7 @@
#![feature(box_patterns)]
#![feature(try_blocks)]
#![feature(in_band_lifetimes)]
#![feature(let_else)]
#![feature(once_cell)]
#![feature(nll)]
#![feature(associated_type_bounds)]

View File

@ -343,9 +343,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
.unwrap_or_else(|| bug!("indirect_dest has non-pointer type: {:?}", indirect_dest))
.ty;
let (llptr, llextra) = if let OperandValue::Ref(llptr, Some(llextra), _) = self {
(llptr, llextra)
} else {
let OperandValue::Ref(llptr, Some(llextra), _) = self else {
bug!("store_unsized called with a sized value")
};

View File

@ -13,6 +13,7 @@ Rust MIR: a lowered representation of Rust.
#![feature(exact_size_is_empty)]
#![feature(in_band_lifetimes)]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(map_try_insert)]
#![feature(min_specialization)]
#![feature(slice_ptr_get)]

View File

@ -145,9 +145,7 @@ impl Qualif for NeedsNonConstDrop {
Ok([..]) => {}
}
let drop_trait = if let Some(did) = cx.tcx.lang_items().drop_trait() {
did
} else {
let Some(drop_trait) = cx.tcx.lang_items().drop_trait() else {
// there is no way to define a type that needs non-const drop
// without having the lang item present.
return false;

View File

@ -449,11 +449,7 @@ pub trait Emitter {
span: &mut MultiSpan,
children: &mut Vec<SubDiagnostic>,
) {
let source_map = if let Some(ref sm) = source_map {
sm
} else {
return;
};
let Some(source_map) = source_map else { return };
debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children);
self.fix_multispan_in_extern_macros(source_map, span);
for child in children.iter_mut() {

View File

@ -8,6 +8,7 @@
#![feature(if_let_guard)]
#![feature(format_args_capture)]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(nll)]
#[macro_use]

View File

@ -447,9 +447,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
let mut undetermined_invocations = Vec::new();
let (mut progress, mut force) = (false, !self.monotonic);
loop {
let (invoc, ext) = if let Some(invoc) = invocations.pop() {
invoc
} else {
let Some((invoc, ext)) = invocations.pop() else {
self.resolve_imports();
if undetermined_invocations.is_empty() {
break;

View File

@ -4,6 +4,7 @@
#![feature(format_args_capture)]
#![feature(if_let_guard)]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(proc_macro_diagnostic)]
#![feature(proc_macro_internals)]
#![feature(proc_macro_span)]

View File

@ -116,10 +116,8 @@ pub(super) fn transcribe<'a>(
loop {
// Look at the last frame on the stack.
let tree = if let Some(tree) = stack.last_mut().unwrap().next() {
// If it still has a TokenTree we have not looked at yet, use that tree.
tree
} else {
// If it still has a TokenTree we have not looked at yet, use that tree.
let Some(tree) = stack.last_mut().unwrap().next() else {
// This else-case never produces a value for `tree` (it `continue`s or `return`s).
// Otherwise, if we have just reached the end of a sequence and we can keep repeating,
@ -190,9 +188,7 @@ pub(super) fn transcribe<'a>(
LockstepIterSize::Constraint(len, _) => {
// We do this to avoid an extra clone above. We know that this is a
// sequence already.
let (sp, seq) = if let mbe::TokenTree::Sequence(sp, seq) = seq {
(sp, seq)
} else {
let mbe::TokenTree::Sequence(sp, seq) = seq else {
unreachable!()
};

View File

@ -2,6 +2,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(in_band_lifetimes)]
#![feature(let_else)]
#![feature(nll)]
#![recursion_limit = "256"]

View File

@ -241,9 +241,7 @@ pub fn prepare_session_directory(
// have already tried before.
let source_directory = find_source_directory(&crate_dir, &source_directories_already_tried);
let source_directory = if let Some(dir) = source_directory {
dir
} else {
let Some(source_directory) = source_directory else {
// There's nowhere to copy from, we're done
debug!(
"no source directory found. Continuing with empty session \
@ -397,15 +395,14 @@ fn copy_files(sess: &Session, target_dir: &Path, source_dir: &Path) -> Result<bo
// We acquire a shared lock on the lock file of the directory, so that
// nobody deletes it out from under us while we are reading from it.
let lock_file_path = lock_file_path(source_dir);
let _lock = if let Ok(lock) = flock::Lock::new(
// not exclusive
let Ok(_lock) = flock::Lock::new(
&lock_file_path,
false, // don't wait,
false, // don't create
false,
) {
// not exclusive
lock
} else {
) else {
// Could not acquire the lock, don't try to copy from here
return Err(());
};

View File

@ -263,9 +263,7 @@ pub fn suggest_new_region_bound(
match fn_return.kind {
TyKind::OpaqueDef(item_id, _) => {
let item = tcx.hir().item(item_id);
let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind {
opaque
} else {
let ItemKind::OpaqueTy(opaque) = &item.kind else {
return;
};

View File

@ -17,6 +17,7 @@
#![feature(box_patterns)]
#![feature(extend_one)]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(never_type)]
#![feature(in_band_lifetimes)]
#![feature(control_flow_enum)]

View File

@ -2,6 +2,7 @@
#![feature(crate_visibility_modifier)]
#![feature(drain_filter)]
#![feature(in_band_lifetimes)]
#![feature(let_else)]
#![feature(nll)]
#![feature(once_cell)]
#![feature(proc_macro_internals)]

View File

@ -472,9 +472,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
let len = BytePos::decode(decoder)?;
let hi = lo + len;
let sess = if let Some(sess) = decoder.sess {
sess
} else {
let Some(sess) = decoder.sess else {
bug!("Cannot decode Span without Session.")
};

View File

@ -39,6 +39,7 @@
#![feature(new_uninit)]
#![feature(nll)]
#![feature(once_cell)]
#![feature(let_else)]
#![feature(min_specialization)]
#![feature(trusted_len)]
#![feature(in_band_lifetimes)]

View File

@ -221,9 +221,7 @@ pub fn suggest_constraining_type_param(
) -> bool {
let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
let param = if let Some(param) = param {
param
} else {
let Some(param) = param else {
return false;
};

View File

@ -755,17 +755,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
}
// Extract the number of elements from the layout of the array field:
let len = if let Ok(TyAndLayout {
let Ok(TyAndLayout {
layout: Layout { fields: FieldsShape::Array { count, .. }, .. },
..
}) = self.layout_of(f0_ty)
{
count
} else {
}) = self.layout_of(f0_ty) else {
return Err(LayoutError::Unknown(ty));
};
(*e_ty, *len, true)
(*e_ty, *count, true)
} else {
// First ADT field is not an array:
(f0_ty, def.non_enum_variant().fields.len() as _, false)
@ -787,9 +784,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
// Compute the ABI of the element type:
let e_ly = self.layout_of(e_ty)?;
let e_abi = if let Abi::Scalar(scalar) = e_ly.abi {
scalar
} else {
let Abi::Scalar(e_abi) = e_ly.abi else {
// This error isn't caught in typeck, e.g., if
// the element type of the vector is generic.
tcx.sess.fatal(&format!(

View File

@ -221,15 +221,13 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>(
let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_def_id.expect_local());
let closure_span = tcx.hir().span(closure_hir_id);
let (capture_index, capture) = if let Some(capture_details) =
let Some((capture_index, capture)) =
find_capture_matching_projections(
typeck_results,
var_hir_id,
closure_def_id,
&from_builder.projection,
) {
capture_details
} else {
) else {
if !enable_precise_capture(tcx, closure_span) {
bug!(
"No associated capture found for {:?}[{:#?}] even though \

View File

@ -362,11 +362,7 @@ impl DropTree {
blocks: &IndexVec<DropIdx, Option<BasicBlock>>,
) {
for (drop_idx, drop_data) in self.drops.iter_enumerated().rev() {
let block = if let Some(block) = blocks[drop_idx] {
block
} else {
continue;
};
let Some(block) = blocks[drop_idx] else { continue };
match drop_data.0.kind {
DropKind::Value => {
let terminator = TerminatorKind::Drop {

View File

@ -6,6 +6,7 @@
#![feature(crate_visibility_modifier)]
#![feature(bool_to_option)]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(once_cell)]
#![feature(min_specialization)]
#![recursion_limit = "256"]

View File

@ -6,6 +6,7 @@
#![feature(exact_size_is_empty)]
#![feature(in_band_lifetimes)]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(min_specialization)]
#![feature(once_cell)]
#![feature(stmt_expr_attributes)]

View File

@ -290,9 +290,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeMutBorrowedLocals<'_, 'tcx> {
call: PeekCall,
) {
info!(?place, "peek_at");
let local = if let Some(l) = place.as_local() {
l
} else {
let Some(local) = place.as_local() else {
tcx.sess.span_err(call.span, "rustc_peek: argument was not a local");
return;
};
@ -312,9 +310,7 @@ impl<'tcx> RustcPeekAt<'tcx> for MaybeLiveLocals {
call: PeekCall,
) {
info!(?place, "peek_at");
let local = if let Some(l) = place.as_local() {
l
} else {
let Some(local) = place.as_local() else {
tcx.sess.span_err(call.span, "rustc_peek: argument was not a local");
return;
};

View File

@ -673,9 +673,7 @@ impl Inliner<'tcx> {
assert!(args.next().is_none());
let tuple = Place::from(tuple);
let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_body, tcx).ty.kind() {
s
} else {
let ty::Tuple(tuple_tys) = tuple.ty(caller_body, tcx).ty.kind() else {
bug!("Closure arguments are not passed as a tuple");
};

View File

@ -4,6 +4,7 @@
#![cfg_attr(bootstrap, feature(const_panic))]
#![feature(in_band_lifetimes)]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(map_try_insert)]
#![feature(min_specialization)]
#![feature(option_get_or_insert_default)]

View File

@ -17,9 +17,7 @@ impl<'tcx> MirPass<'tcx> for LowerSliceLenCalls {
pub fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let language_items = tcx.lang_items();
let slice_len_fn_item_def_id = if let Some(slice_len_fn_item) = language_items.slice_len_fn() {
slice_len_fn_item
} else {
let Some(slice_len_fn_item_def_id) = language_items.slice_len_fn() else {
// there is no language item to compare to :)
return;
};

View File

@ -208,7 +208,7 @@ fn normalize_array_len_call<'tcx>(
operand,
cast_ty,
) => {
let local = if let Some(local) = place.as_local() { local } else { return };
let Some(local) = place.as_local() else { return };
match operand {
Operand::Copy(place) | Operand::Move(place) => {
let operand_local =
@ -255,9 +255,7 @@ fn normalize_array_len_call<'tcx>(
}
}
Rvalue::Len(place) => {
let local = if let Some(local) = place.local_or_deref_local() {
local
} else {
let Some(local) = place.local_or_deref_local() else {
return;
};
if let Some(cast_statement_idx) = state.get(&local).copied() {

View File

@ -83,12 +83,9 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
let bb = BasicBlock::from_usize(bb);
trace!("processing block {:?}", bb);
let discriminant_ty =
if let Some(ty) = get_switched_on_type(&body.basic_blocks()[bb], tcx, body) {
ty
} else {
continue;
};
let Some(discriminant_ty) = get_switched_on_type(&body.basic_blocks()[bb], tcx, body) else {
continue;
};
let layout = tcx.layout_of(tcx.param_env(body.source.def_id()).and(discriminant_ty));

View File

@ -2,6 +2,7 @@
#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
#![feature(control_flow_enum)]
#![feature(let_else)]
#![feature(in_band_lifetimes)]
#![recursion_limit = "256"]

View File

@ -458,9 +458,7 @@ fn mono_item_visibility(
let is_generic = instance.substs.non_erasable_generics().next().is_some();
// Upstream `DefId` instances get different handling than local ones.
let def_id = if let Some(def_id) = def_id.as_local() {
def_id
} else {
let Some(def_id) = def_id.as_local() else {
return if export_generics && is_generic {
// If it is an upstream monomorphization and we export generics, we must make
// it available to downstream crates.

View File

@ -3,6 +3,7 @@
#![feature(core_intrinsics)]
#![feature(hash_raw_entry)]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(min_specialization)]
#![feature(thread_local_const_init)]

View File

@ -644,9 +644,7 @@ pub fn print_query_stack<CTX: QueryContext>(
if Some(i) == num_frames {
break;
}
let query_info = if let Some(info) = query_map.as_ref().and_then(|map| map.get(&query)) {
info
} else {
let Some(query_info) = query_map.as_ref().and_then(|map| map.get(&query)) else {
break;
};
let mut diag = Diagnostic::new(

View File

@ -761,11 +761,9 @@ where
return false;
}
let key = if let Some(key) =
let Some(key) =
<Q::Key as DepNodeParams<CTX::DepContext>>::recover(*tcx.dep_context(), &dep_node)
{
key
} else {
else {
return false;
};

View File

@ -1471,9 +1471,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
module: ModuleOrUniformRoot<'b>,
ident: Ident,
) -> Option<(Option<Suggestion>, Vec<String>)> {
let mut crate_module = if let ModuleOrUniformRoot::Module(module) = module {
module
} else {
let ModuleOrUniformRoot::Module(mut crate_module) = module else {
return None;
};

View File

@ -1057,9 +1057,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
match param.kind {
GenericParamKind::Lifetime { .. } => {
let (name, reg) = Region::early(&self.tcx.hir(), &mut index, &param);
let def_id = if let Region::EarlyBound(_, def_id, _) = reg {
def_id
} else {
let Region::EarlyBound(_, def_id, _) = reg else {
bug!();
};
// We cannot predict what lifetimes are unused in opaque type.

View File

@ -15,6 +15,7 @@
#![feature(crate_visibility_modifier)]
#![feature(format_args_capture)]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(never_type)]
#![feature(nll)]
#![recursion_limit = "256"]

View File

@ -17,6 +17,7 @@
#![feature(hash_drain_filter)]
#![feature(in_band_lifetimes)]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(never_type)]
#![feature(crate_visibility_modifier)]
#![feature(control_flow_enum)]

View File

@ -1038,13 +1038,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let hir = self.tcx.hir();
let parent_node = hir.get_parent_node(obligation.cause.body_id);
let node = hir.find(parent_node);
let (sig, body_id) = if let Some(hir::Node::Item(hir::Item {
let Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Fn(sig, _, body_id),
..
})) = node
{
(sig, body_id)
} else {
else {
return false;
};
let body = hir.body(*body_id);

View File

@ -647,9 +647,7 @@ fn receiver_is_dispatchable<'tcx>(
debug!("receiver_is_dispatchable: method = {:?}, receiver_ty = {:?}", method, receiver_ty);
let traits = (tcx.lang_items().unsize_trait(), tcx.lang_items().dispatch_from_dyn_trait());
let (unsize_did, dispatch_from_dyn_did) = if let (Some(u), Some(cu)) = traits {
(u, cu)
} else {
let (Some(unsize_did), Some(dispatch_from_dyn_did)) = traits else {
debug!("receiver_is_dispatchable: Missing Unsize or DispatchFromDyn traits");
return false;
};

View File

@ -164,9 +164,7 @@ impl<'tcx> OnUnimplementedDirective {
) -> Result<Option<Self>, ErrorReported> {
let attrs = tcx.get_attrs(impl_def_id);
let attr = if let Some(item) = tcx.sess.find_by_name(&attrs, sym::rustc_on_unimplemented) {
item
} else {
let Some(attr) = tcx.sess.find_by_name(&attrs, sym::rustc_on_unimplemented) else {
return Ok(None);
};

View File

@ -716,9 +716,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
cause.clone(),
);
let data = if let ty::Dynamic(ref data, ..) = normalized_ty.kind() {
data
} else {
let ty::Dynamic(data, ..) = normalized_ty.kind() else {
return None;
};

View File

@ -1916,9 +1916,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!("qpath_to_ty: trait_def_id={:?}", trait_def_id);
let self_ty = if let Some(ty) = opt_self_ty {
ty
} else {
let Some(self_ty) = opt_self_ty else {
let path_str = tcx.def_path_str(trait_def_id);
let def_id = self.item_def_id();

View File

@ -521,9 +521,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let traits =
(self.tcx.lang_items().unsize_trait(), self.tcx.lang_items().coerce_unsized_trait());
let (unsize_did, coerce_unsized_did) = if let (Some(u), Some(cu)) = traits {
(u, cu)
} else {
let (Some(unsize_did), Some(coerce_unsized_did)) = traits else {
debug!("missing Unsize or CoerceUnsized traits");
return Err(TypeError::Mismatch);
};

View File

@ -743,9 +743,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return false;
}
let src = if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
src
} else {
let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) else {
return false;
};

View File

@ -502,9 +502,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// FIXME: Instead of exiting early when encountering bound vars in
// the function signature, consider keeping the binder here and
// propagating it downwards.
let fn_sig = if let Some(fn_sig) = self.tcx.fn_sig(def_id).no_bound_vars() {
fn_sig
} else {
let Some(fn_sig) = self.tcx.fn_sig(def_id).no_bound_vars() else {
return false;
};

View File

@ -718,10 +718,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ti: TopInfo<'tcx>,
) -> Ty<'tcx> {
// Resolve the path and check the definition for errors.
let (variant, pat_ty) = if let Some(variant_ty) = self.check_struct_path(qpath, pat.hir_id)
{
variant_ty
} else {
let Some((variant, pat_ty)) = self.check_struct_path(qpath, pat.hir_id) else {
let err = self.tcx.ty_error();
for field in fields {
let ti = TopInfo { parent_pat: Some(pat), ..ti };

View File

@ -411,9 +411,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("convert_place_op_to_mutable: method={:?}", method);
self.write_method_call(expr.hir_id, method);
let region = if let ty::Ref(r, _, hir::Mutability::Mut) = method.sig.inputs()[0].kind() {
r
} else {
let ty::Ref(region, _, hir::Mutability::Mut) = method.sig.inputs()[0].kind() else {
span_bug!(expr.span, "input to mutable place op is not a mut ref?");
};

View File

@ -1000,11 +1000,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return None;
}
let root_var_min_capture_list = if let Some(root_var_min_capture_list) =
min_captures.and_then(|m| m.get(&var_hir_id))
{
root_var_min_capture_list
} else {
let Some(root_var_min_capture_list) = min_captures.and_then(|m| m.get(&var_hir_id)) else {
// The upvar is mentioned within the closure but no path starting from it is
// used.
@ -1077,9 +1073,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
closure_clause: hir::CaptureBy,
min_captures: Option<&ty::RootVariableMinCaptureList<'tcx>>,
) -> (Vec<MigrationDiagnosticInfo>, String) {
let upvars = if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
upvars
} else {
let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) else {
return (Vec::new(), format!(""));
};
@ -1684,9 +1678,7 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
diag_expr_id: hir::HirId,
) {
let tcx = self.fcx.tcx;
let upvar_id = if let PlaceBase::Upvar(upvar_id) = place_with_id.place.base {
upvar_id
} else {
let PlaceBase::Upvar(upvar_id) = place_with_id.place.base else {
return;
};

View File

@ -63,6 +63,7 @@ This API is completely unstable and subject to change.
#![feature(in_band_lifetimes)]
#![feature(is_sorted)]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(min_specialization)]
#![feature(nll)]
#![feature(try_blocks)]