mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 10:13:54 +00:00
More let_else adoptions
This commit is contained in:
parent
d5f9c40e6a
commit
670f5c6ef3
@ -471,9 +471,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
// two imports.
|
// two imports.
|
||||||
for new_node_id in [id1, id2] {
|
for new_node_id in [id1, id2] {
|
||||||
let new_id = self.resolver.local_def_id(new_node_id);
|
let new_id = self.resolver.local_def_id(new_node_id);
|
||||||
let res = if let Some(res) = resolutions.next() {
|
let Some(res) = resolutions.next() else {
|
||||||
res
|
|
||||||
} else {
|
|
||||||
// Associate an HirId to both ids even if there is no resolution.
|
// Associate an HirId to both ids even if there is no resolution.
|
||||||
let _old = self
|
let _old = self
|
||||||
.node_id_to_hir_id
|
.node_id_to_hir_id
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#![feature(crate_visibility_modifier)]
|
#![feature(crate_visibility_modifier)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
|
#![feature(let_else)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
|
#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
|
||||||
|
@ -217,85 +217,81 @@ where
|
|||||||
let mut issue_num = None;
|
let mut issue_num = None;
|
||||||
let mut is_soft = false;
|
let mut is_soft = false;
|
||||||
for meta in metas {
|
for meta in metas {
|
||||||
if let Some(mi) = meta.meta_item() {
|
let Some(mi) = meta.meta_item() else {
|
||||||
match mi.name_or_empty() {
|
|
||||||
sym::feature => {
|
|
||||||
if !get(mi, &mut feature) {
|
|
||||||
continue 'outer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sym::reason => {
|
|
||||||
if !get(mi, &mut reason) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
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(
|
handle_errors(
|
||||||
&sess.parse_sess,
|
&sess.parse_sess,
|
||||||
meta.span(),
|
meta.span(),
|
||||||
AttrError::UnsupportedLiteral("unsupported literal", false),
|
AttrError::UnsupportedLiteral("unsupported literal", false),
|
||||||
);
|
);
|
||||||
continue 'outer;
|
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::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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
//! The goal is to move the definition of `MetaItem` and things that don't need to be in `syntax`
|
//! The goal is to move the definition of `MetaItem` and things that don't need to be in `syntax`
|
||||||
//! to this crate.
|
//! to this crate.
|
||||||
|
|
||||||
|
#![feature(let_else)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rustc_macros;
|
extern crate rustc_macros;
|
||||||
|
|
||||||
|
@ -311,43 +311,39 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
|||||||
ty::BoundRegionKind::BrEnv => {
|
ty::BoundRegionKind::BrEnv => {
|
||||||
let def_ty = self.regioncx.universal_regions().defining_ty;
|
let def_ty = self.regioncx.universal_regions().defining_ty;
|
||||||
|
|
||||||
if let DefiningTy::Closure(_, substs) = def_ty {
|
let DefiningTy::Closure(_, substs) = def_ty else {
|
||||||
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 {
|
|
||||||
// Can't have BrEnv in functions, constants or generators.
|
// Can't have BrEnv in functions, constants or generators.
|
||||||
bug!("BrEnv outside of closure.");
|
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,
|
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> {
|
fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
|
||||||
let hir = self.infcx.tcx.hir();
|
let hir = self.infcx.tcx.hir();
|
||||||
|
|
||||||
if let hir::TyKind::OpaqueDef(id, _) = hir_ty.kind {
|
let hir::TyKind::OpaqueDef(id, _) = hir_ty.kind else {
|
||||||
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 {
|
|
||||||
span_bug!(
|
span_bug!(
|
||||||
hir_ty.span,
|
hir_ty.span,
|
||||||
"lowered return type of async fn is not OpaqueDef: {:?}",
|
"lowered return type of async fn is not OpaqueDef: {:?}",
|
||||||
hir_ty
|
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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1427,9 +1427,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
bug!("temporary should be initialized exactly once")
|
bug!("temporary should be initialized exactly once")
|
||||||
};
|
};
|
||||||
|
|
||||||
let loc = match init.location {
|
let InitLocation::Statement(loc) = init.location else {
|
||||||
InitLocation::Statement(stmt) => stmt,
|
bug!("temporary initialized in arguments")
|
||||||
_ => bug!("temporary initialized in arguments"),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let body = self.body;
|
let body = self.body;
|
||||||
|
@ -602,33 +602,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
for binding in &candidate_ref.bindings {
|
for binding in &candidate_ref.bindings {
|
||||||
let local = self.var_local_id(binding.var_id, OutsideGuard);
|
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, _)), .. },
|
VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
|
||||||
)))) = self.local_decls[local].local_info
|
)))) = self.local_decls[local].local_info else {
|
||||||
{
|
|
||||||
// `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 {
|
|
||||||
bug!("Let binding to non-user variable.")
|
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
|
// All of the subcandidates should bind the same locals, so we
|
||||||
|
@ -227,16 +227,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
let target_blocks = make_target_blocks(self);
|
let target_blocks = make_target_blocks(self);
|
||||||
let terminator = if *switch_ty.kind() == ty::Bool {
|
let terminator = if *switch_ty.kind() == ty::Bool {
|
||||||
assert!(!options.is_empty() && options.len() <= 2);
|
assert!(!options.is_empty() && options.len() <= 2);
|
||||||
if let [first_bb, second_bb] = *target_blocks {
|
let [first_bb, second_bb] = *target_blocks else {
|
||||||
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 {
|
|
||||||
bug!("`TestKind::SwitchInt` on `bool` should have two targets")
|
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 {
|
} else {
|
||||||
// The switch may be inexhaustive so we have a catch all block
|
// The switch may be inexhaustive so we have a catch all block
|
||||||
debug_assert_eq!(options.len() + 1, target_blocks.len());
|
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 hi = self.literal_operand(test.span, hi);
|
||||||
let val = Operand::Copy(place);
|
let val = Operand::Copy(place);
|
||||||
|
|
||||||
if let [success, fail] = *target_blocks {
|
let [success, fail] = *target_blocks else {
|
||||||
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 {
|
|
||||||
bug!("`TestKind::Range` should have two target blocks");
|
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 } => {
|
TestKind::Len { len, op } => {
|
||||||
@ -317,21 +315,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
// expected = <N>
|
// expected = <N>
|
||||||
let expected = self.push_usize(block, source_info, len);
|
let expected = self.push_usize(block, source_info, len);
|
||||||
|
|
||||||
if let [true_bb, false_bb] = *target_blocks {
|
let [true_bb, false_bb] = *target_blocks else {
|
||||||
// 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 {
|
|
||||||
bug!("`TestKind::Len` should have two target blocks");
|
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);
|
self.diverge_from(block);
|
||||||
|
|
||||||
if let [success_block, fail_block] = *make_target_blocks(self) {
|
let [success_block, fail_block] = *make_target_blocks(self) else {
|
||||||
// check the result
|
|
||||||
self.cfg.terminate(
|
|
||||||
eq_block,
|
|
||||||
source_info,
|
|
||||||
TerminatorKind::if_(self.tcx, Operand::Move(eq_result), success_block, fail_block),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
bug!("`TestKind::Eq` should have two target blocks")
|
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
|
/// Given that we are performing `test` against `test_place`, this job
|
||||||
|
@ -47,11 +47,10 @@ use rls_data::{
|
|||||||
|
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
|
|
||||||
|
#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5213
|
||||||
macro_rules! down_cast_data {
|
macro_rules! down_cast_data {
|
||||||
($id:ident, $kind:ident, $sp:expr) => {
|
($id:ident, $kind:ident, $sp:expr) => {
|
||||||
let $id = if let super::Data::$kind(data) = $id {
|
let super::Data::$kind($id) = $id else {
|
||||||
data
|
|
||||||
} else {
|
|
||||||
span_bug!($sp, "unexpected data kind: {:?}", $id);
|
span_bug!($sp, "unexpected data kind: {:?}", $id);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
|
#![feature(let_else)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
|
#![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user