Don't call closures immediately, use try{}
blocks
This commit is contained in:
parent
bddbf38af2
commit
360e978437
10 changed files with 88 additions and 115 deletions
|
@ -47,42 +47,22 @@ pub(super) fn compare_impl_method<'tcx>(
|
||||||
|
|
||||||
let impl_m_span = tcx.def_span(impl_m.def_id);
|
let impl_m_span = tcx.def_span(impl_m.def_id);
|
||||||
|
|
||||||
if let Err(_) = compare_self_type(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref) {
|
let _: Result<_, ErrorGuaranteed> = try {
|
||||||
return;
|
compare_self_type(tcx, impl_m, impl_m_span, trait_m, impl_trait_ref)?;
|
||||||
}
|
compare_number_of_generics(tcx, impl_m, trait_m, trait_item_span, false)?;
|
||||||
|
compare_generic_param_kinds(tcx, impl_m, trait_m, false)?;
|
||||||
if let Err(_) = compare_number_of_generics(tcx, impl_m, trait_m, trait_item_span, false) {
|
compare_number_of_method_arguments(tcx, impl_m, impl_m_span, trait_m, trait_item_span)?;
|
||||||
return;
|
compare_synthetic_generics(tcx, impl_m, trait_m)?;
|
||||||
}
|
compare_asyncness(tcx, impl_m, impl_m_span, trait_m, trait_item_span)?;
|
||||||
|
compare_method_predicate_entailment(
|
||||||
if let Err(_) = compare_generic_param_kinds(tcx, impl_m, trait_m, false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(_) =
|
|
||||||
compare_number_of_method_arguments(tcx, impl_m, impl_m_span, trait_m, trait_item_span)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(_) = compare_synthetic_generics(tcx, impl_m, trait_m) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(_) = compare_asyncness(tcx, impl_m, impl_m_span, trait_m, trait_item_span) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(_) = compare_method_predicate_entailment(
|
|
||||||
tcx,
|
tcx,
|
||||||
impl_m,
|
impl_m,
|
||||||
impl_m_span,
|
impl_m_span,
|
||||||
trait_m,
|
trait_m,
|
||||||
impl_trait_ref,
|
impl_trait_ref,
|
||||||
CheckImpliedWfMode::Check,
|
CheckImpliedWfMode::Check,
|
||||||
) {
|
)?;
|
||||||
return;
|
};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function is best explained by example. Consider a trait:
|
/// This function is best explained by example. Consider a trait:
|
||||||
|
@ -1493,7 +1473,7 @@ fn compare_synthetic_generics<'tcx>(
|
||||||
// explicit generics
|
// explicit generics
|
||||||
(true, false) => {
|
(true, false) => {
|
||||||
err.span_label(impl_span, "expected generic parameter, found `impl Trait`");
|
err.span_label(impl_span, "expected generic parameter, found `impl Trait`");
|
||||||
(|| {
|
let _: Option<_> = try {
|
||||||
// try taking the name from the trait impl
|
// try taking the name from the trait impl
|
||||||
// FIXME: this is obviously suboptimal since the name can already be used
|
// FIXME: this is obviously suboptimal since the name can already be used
|
||||||
// as another generic argument
|
// as another generic argument
|
||||||
|
@ -1526,14 +1506,13 @@ fn compare_synthetic_generics<'tcx>(
|
||||||
],
|
],
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
Some(())
|
};
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
// The case where the trait method uses `impl Trait`, but the impl method uses
|
// The case where the trait method uses `impl Trait`, but the impl method uses
|
||||||
// explicit generics.
|
// explicit generics.
|
||||||
(false, true) => {
|
(false, true) => {
|
||||||
err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
|
err.span_label(impl_span, "expected `impl Trait`, found generic parameter");
|
||||||
(|| {
|
let _: Option<_> = try {
|
||||||
let impl_m = impl_m.def_id.as_local()?;
|
let impl_m = impl_m.def_id.as_local()?;
|
||||||
let impl_m = tcx.hir().expect_impl_item(impl_m);
|
let impl_m = tcx.hir().expect_impl_item(impl_m);
|
||||||
let input_tys = match impl_m.kind {
|
let input_tys = match impl_m.kind {
|
||||||
|
@ -1573,8 +1552,7 @@ fn compare_synthetic_generics<'tcx>(
|
||||||
],
|
],
|
||||||
Applicability::MaybeIncorrect,
|
Applicability::MaybeIncorrect,
|
||||||
);
|
);
|
||||||
Some(())
|
};
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
@ -1799,7 +1777,7 @@ pub(super) fn compare_impl_ty<'tcx>(
|
||||||
) {
|
) {
|
||||||
debug!("compare_impl_type(impl_trait_ref={:?})", impl_trait_ref);
|
debug!("compare_impl_type(impl_trait_ref={:?})", impl_trait_ref);
|
||||||
|
|
||||||
let _: Result<(), ErrorGuaranteed> = (|| {
|
let _: Result<(), ErrorGuaranteed> = try {
|
||||||
compare_number_of_generics(tcx, impl_ty, trait_ty, trait_item_span, false)?;
|
compare_number_of_generics(tcx, impl_ty, trait_ty, trait_item_span, false)?;
|
||||||
|
|
||||||
compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
|
compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
|
||||||
|
@ -1807,8 +1785,8 @@ pub(super) fn compare_impl_ty<'tcx>(
|
||||||
let sp = tcx.def_span(impl_ty.def_id);
|
let sp = tcx.def_span(impl_ty.def_id);
|
||||||
compare_type_predicate_entailment(tcx, impl_ty, sp, trait_ty, impl_trait_ref)?;
|
compare_type_predicate_entailment(tcx, impl_ty, sp, trait_ty, impl_trait_ref)?;
|
||||||
|
|
||||||
check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)
|
check_type_bounds(tcx, trait_ty, impl_ty, impl_ty_span, impl_trait_ref)?;
|
||||||
})();
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The equivalent of [compare_method_predicate_entailment], but for associated types
|
/// The equivalent of [compare_method_predicate_entailment], but for associated types
|
||||||
|
|
|
@ -251,7 +251,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
||||||
VarValue::Empty(a_universe) => {
|
VarValue::Empty(a_universe) => {
|
||||||
let b_data = var_values.value_mut(b_vid);
|
let b_data = var_values.value_mut(b_vid);
|
||||||
|
|
||||||
let changed = (|| match *b_data {
|
let changed = match *b_data {
|
||||||
VarValue::Empty(b_universe) => {
|
VarValue::Empty(b_universe) => {
|
||||||
// Empty regions are ordered according to the universe
|
// Empty regions are ordered according to the universe
|
||||||
// they are associated with.
|
// they are associated with.
|
||||||
|
@ -280,9 +280,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if lub == cur_region {
|
if lub == cur_region {
|
||||||
return false;
|
false
|
||||||
}
|
} else {
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"Expanding value of {:?} from {:?} to {:?}",
|
"Expanding value of {:?} from {:?} to {:?}",
|
||||||
b_vid, cur_region, lub
|
b_vid, cur_region, lub
|
||||||
|
@ -291,9 +290,10 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
||||||
*b_data = VarValue::Value(lub);
|
*b_data = VarValue::Value(lub);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VarValue::ErrorValue => false,
|
VarValue::ErrorValue => false,
|
||||||
})();
|
};
|
||||||
|
|
||||||
if changed {
|
if changed {
|
||||||
changes.push(b_vid);
|
changes.push(b_vid);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#![feature(internal_output_capture)]
|
#![feature(internal_output_capture)]
|
||||||
#![feature(thread_spawn_unchecked)]
|
#![feature(thread_spawn_unchecked)]
|
||||||
#![feature(once_cell)]
|
#![feature(once_cell)]
|
||||||
|
#![feature(try_blocks)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
#![allow(rustc::potential_query_instability)]
|
#![allow(rustc::potential_query_instability)]
|
||||||
#![deny(rustc::untranslatable_diagnostic)]
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
|
|
|
@ -559,7 +559,7 @@ fn write_out_deps(
|
||||||
}
|
}
|
||||||
let deps_filename = outputs.path(OutputType::DepInfo);
|
let deps_filename = outputs.path(OutputType::DepInfo);
|
||||||
|
|
||||||
let result = (|| -> io::Result<()> {
|
let result: io::Result<()> = try {
|
||||||
// Build a list of files used to compile the output and
|
// Build a list of files used to compile the output and
|
||||||
// write Makefile-compatible dependency rules
|
// write Makefile-compatible dependency rules
|
||||||
let mut files: Vec<String> = sess
|
let mut files: Vec<String> = sess
|
||||||
|
@ -646,9 +646,7 @@ fn write_out_deps(
|
||||||
writeln!(file)?;
|
writeln!(file)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
Ok(())
|
|
||||||
})();
|
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
|
|
|
@ -159,7 +159,8 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
|
||||||
}
|
}
|
||||||
chalk_ir::TyKind::Array(ty, len) => Some(write!(fmt, "[{:?}; {:?}]", ty, len)),
|
chalk_ir::TyKind::Array(ty, len) => Some(write!(fmt, "[{:?}; {:?}]", ty, len)),
|
||||||
chalk_ir::TyKind::Slice(ty) => Some(write!(fmt, "[{:?}]", ty)),
|
chalk_ir::TyKind::Slice(ty) => Some(write!(fmt, "[{:?}]", ty)),
|
||||||
chalk_ir::TyKind::Tuple(len, substs) => Some((|| {
|
chalk_ir::TyKind::Tuple(len, substs) => Some(
|
||||||
|
try {
|
||||||
write!(fmt, "(")?;
|
write!(fmt, "(")?;
|
||||||
for (idx, substitution) in substs.interned().iter().enumerate() {
|
for (idx, substitution) in substs.interned().iter().enumerate() {
|
||||||
if idx == *len && *len != 1 {
|
if idx == *len && *len != 1 {
|
||||||
|
@ -169,8 +170,9 @@ impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> {
|
||||||
write!(fmt, "{:?},", substitution)?;
|
write!(fmt, "{:?},", substitution)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write!(fmt, ")")
|
write!(fmt, ")")?;
|
||||||
})()),
|
},
|
||||||
|
),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,10 +86,10 @@ pub(super) fn build_custom_mir<'tcx>(
|
||||||
block_map: FxHashMap::default(),
|
block_map: FxHashMap::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = (|| {
|
let res: PResult<_> = try {
|
||||||
pctxt.parse_args(¶ms)?;
|
pctxt.parse_args(¶ms)?;
|
||||||
pctxt.parse_body(expr)
|
pctxt.parse_body(expr)?;
|
||||||
})();
|
};
|
||||||
if let Err(err) = res {
|
if let Err(err) = res {
|
||||||
tcx.sess.diagnostic().span_fatal(
|
tcx.sess.diagnostic().span_fatal(
|
||||||
err.span,
|
err.span,
|
||||||
|
|
|
@ -113,7 +113,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
//
|
//
|
||||||
// it is usually better to focus on `the_value` rather
|
// it is usually better to focus on `the_value` rather
|
||||||
// than the entirety of block(s) surrounding it.
|
// than the entirety of block(s) surrounding it.
|
||||||
let adjusted_span = (|| {
|
let adjusted_span =
|
||||||
if let ExprKind::Block { block } = expr.kind
|
if let ExprKind::Block { block } = expr.kind
|
||||||
&& let Some(tail_ex) = this.thir[block].expr
|
&& let Some(tail_ex) = this.thir[block].expr
|
||||||
{
|
{
|
||||||
|
@ -135,10 +135,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
tail_result_is_ignored: true,
|
tail_result_is_ignored: true,
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
});
|
});
|
||||||
return Some(expr.span);
|
Some(expr.span)
|
||||||
}
|
} else {
|
||||||
None
|
None
|
||||||
})();
|
};
|
||||||
|
|
||||||
let temp =
|
let temp =
|
||||||
unpack!(block = this.as_temp(block, statement_scope, expr, Mutability::Not));
|
unpack!(block = this.as_temp(block, statement_scope, expr, Mutability::Not));
|
||||||
|
|
|
@ -141,27 +141,23 @@ impl IntRange {
|
||||||
) -> Option<IntRange> {
|
) -> Option<IntRange> {
|
||||||
let ty = value.ty();
|
let ty = value.ty();
|
||||||
if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, ty) {
|
if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, ty) {
|
||||||
let val = (|| {
|
let val =
|
||||||
match value {
|
if let mir::ConstantKind::Val(ConstValue::Scalar(scalar), _) = value {
|
||||||
mir::ConstantKind::Val(ConstValue::Scalar(scalar), _) => {
|
|
||||||
// For this specific pattern we can skip a lot of effort and go
|
// For this specific pattern we can skip a lot of effort and go
|
||||||
// straight to the result, after doing a bit of checking. (We
|
// straight to the result, after doing a bit of checking. (We
|
||||||
// could remove this branch and just fall through, which
|
// could remove this branch and just fall through, which
|
||||||
// is more general but much slower.)
|
// is more general but much slower.)
|
||||||
return scalar.to_bits_or_ptr_internal(target_size).unwrap().left();
|
scalar.to_bits_or_ptr_internal(target_size).unwrap().left()?
|
||||||
}
|
} else {
|
||||||
mir::ConstantKind::Ty(c) => match c.kind() {
|
if let mir::ConstantKind::Ty(c) = value
|
||||||
ty::ConstKind::Value(_) => bug!(
|
&& let ty::ConstKind::Value(_) = c.kind()
|
||||||
"encountered ConstValue in mir::ConstantKind::Ty, whereas this is expected to be in ConstantKind::Val"
|
{
|
||||||
),
|
bug!("encountered ConstValue in mir::ConstantKind::Ty, whereas this is expected to be in ConstantKind::Val");
|
||||||
_ => {}
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a more general form of the previous case.
|
// This is a more general form of the previous case.
|
||||||
value.try_eval_bits(tcx, param_env, ty)
|
value.try_eval_bits(tcx, param_env, ty)?
|
||||||
})()?;
|
};
|
||||||
let val = val ^ bias;
|
let val = val ^ bias;
|
||||||
Some(IntRange { range: val..=val, bias })
|
Some(IntRange { range: val..=val, bias })
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -208,14 +208,12 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
||||||
_ => {
|
_ => {
|
||||||
// This `for` loop was once a call to `all()`, but this lower-level
|
// This `for` loop was once a call to `all()`, but this lower-level
|
||||||
// form was a perf win. See #64545 for details.
|
// form was a perf win. See #64545 for details.
|
||||||
(|| {
|
|
||||||
for &infer_var in &pending_obligation.stalled_on {
|
for &infer_var in &pending_obligation.stalled_on {
|
||||||
if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
|
if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
})()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,7 +201,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
||||||
// wait to fold the substs.
|
// wait to fold the substs.
|
||||||
|
|
||||||
// Wrap this in a closure so we don't accidentally return from the outer function
|
// Wrap this in a closure so we don't accidentally return from the outer function
|
||||||
let res = (|| match *ty.kind() {
|
let res = match *ty.kind() {
|
||||||
// This is really important. While we *can* handle this, this has
|
// This is really important. While we *can* handle this, this has
|
||||||
// severe performance implications for large opaque types with
|
// severe performance implications for large opaque types with
|
||||||
// late-bound regions. See `issue-88862` benchmark.
|
// late-bound regions. See `issue-88862` benchmark.
|
||||||
|
@ -210,7 +210,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
||||||
{
|
{
|
||||||
// Only normalize `impl Trait` outside of type inference, usually in codegen.
|
// Only normalize `impl Trait` outside of type inference, usually in codegen.
|
||||||
match self.param_env.reveal() {
|
match self.param_env.reveal() {
|
||||||
Reveal::UserFacing => ty.try_super_fold_with(self),
|
Reveal::UserFacing => ty.try_super_fold_with(self)?,
|
||||||
|
|
||||||
Reveal::All => {
|
Reveal::All => {
|
||||||
let substs = substs.try_fold_with(self)?;
|
let substs = substs.try_fold_with(self)?;
|
||||||
|
@ -239,7 +239,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
let folded_ty = ensure_sufficient_stack(|| self.try_fold_ty(concrete_ty));
|
let folded_ty = ensure_sufficient_stack(|| self.try_fold_ty(concrete_ty));
|
||||||
self.anon_depth -= 1;
|
self.anon_depth -= 1;
|
||||||
folded_ty
|
folded_ty?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,9 +287,9 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
||||||
// `tcx.normalize_projection_ty` may normalize to a type that still has
|
// `tcx.normalize_projection_ty` may normalize to a type that still has
|
||||||
// unevaluated consts, so keep normalizing here if that's the case.
|
// unevaluated consts, so keep normalizing here if that's the case.
|
||||||
if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
|
if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
|
||||||
Ok(res.try_super_fold_with(self)?)
|
res.try_super_fold_with(self)?
|
||||||
} else {
|
} else {
|
||||||
Ok(res)
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,14 +344,14 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
||||||
// `tcx.normalize_projection_ty` may normalize to a type that still has
|
// `tcx.normalize_projection_ty` may normalize to a type that still has
|
||||||
// unevaluated consts, so keep normalizing here if that's the case.
|
// unevaluated consts, so keep normalizing here if that's the case.
|
||||||
if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
|
if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
|
||||||
Ok(res.try_super_fold_with(self)?)
|
res.try_super_fold_with(self)?
|
||||||
} else {
|
} else {
|
||||||
Ok(res)
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => ty.try_super_fold_with(self),
|
_ => ty.try_super_fold_with(self)?,
|
||||||
})()?;
|
};
|
||||||
|
|
||||||
self.cache.insert(ty, res);
|
self.cache.insert(ty, res);
|
||||||
Ok(res)
|
Ok(res)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue