9 - Make more use of let_chains

Continuation of #94376.

cc #53667
This commit is contained in:
Caio 2022-03-01 18:34:35 -03:00
parent f0c4da4998
commit a7b4d667fe
8 changed files with 176 additions and 218 deletions

View file

@ -10,19 +10,20 @@
//! //!
//! This API is completely unstable and subject to change. //! This API is completely unstable and subject to change.
#![allow(rustc::potential_query_instability)]
#![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(bool_to_option)] #![feature(bool_to_option)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(drain_filter)] #![feature(control_flow_enum)]
#![feature(crate_visibility_modifier)]
#![feature(derive_default_enum)] #![feature(derive_default_enum)]
#![feature(drain_filter)]
#![feature(hash_drain_filter)] #![feature(hash_drain_filter)]
#![feature(label_break_value)] #![feature(label_break_value)]
#![feature(let_chains)]
#![feature(let_else)] #![feature(let_else)]
#![feature(never_type)] #![feature(never_type)]
#![feature(crate_visibility_modifier)]
#![feature(control_flow_enum)]
#![recursion_limit = "512"] // For rustdoc #![recursion_limit = "512"] // For rustdoc
#![allow(rustc::potential_query_instability)]
#[macro_use] #[macro_use]
extern crate rustc_macros; extern crate rustc_macros;

View file

@ -1098,42 +1098,43 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
); );
} }
} }
if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] { if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..]
if fields.len() == found_args.len() && is_closure { && fields.len() == found_args.len()
let sugg = format!( && is_closure
"|({}){}|", {
found_args let sugg = format!(
.iter() "|({}){}|",
.map(|arg| match arg { found_args
ArgKind::Arg(name, _) => name.to_owned(), .iter()
_ => "_".to_owned(), .map(|arg| match arg {
}) ArgKind::Arg(name, _) => name.to_owned(),
.collect::<Vec<String>>() _ => "_".to_owned(),
.join(", "), })
// add type annotations if available .collect::<Vec<String>>()
if found_args.iter().any(|arg| match arg { .join(", "),
ArgKind::Arg(_, ty) => ty != "_", // add type annotations if available
_ => false, if found_args.iter().any(|arg| match arg {
}) { ArgKind::Arg(_, ty) => ty != "_",
format!( _ => false,
": ({})", }) {
fields format!(
.iter() ": ({})",
.map(|(_, ty)| ty.to_owned()) fields
.collect::<Vec<String>>() .iter()
.join(", ") .map(|(_, ty)| ty.to_owned())
) .collect::<Vec<String>>()
} else { .join(", ")
String::new() )
}, } else {
); String::new()
err.span_suggestion_verbose( },
found_span, );
"change the closure to accept a tuple instead of individual arguments", err.span_suggestion_verbose(
sugg, found_span,
Applicability::MachineApplicable, "change the closure to accept a tuple instead of individual arguments",
); sugg,
} Applicability::MachineApplicable,
);
} }
} }
@ -2231,16 +2232,13 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
if obligated_types.iter().any(|ot| ot == &self_ty) { if obligated_types.iter().any(|ot| ot == &self_ty) {
return true; return true;
} }
if let ty::Adt(def, substs) = self_ty.kind() { if let ty::Adt(def, substs) = self_ty.kind()
if let [arg] = &substs[..] { && let [arg] = &substs[..]
if let ty::subst::GenericArgKind::Type(ty) = arg.unpack() { && let ty::subst::GenericArgKind::Type(ty) = arg.unpack()
if let ty::Adt(inner_def, _) = ty.kind() { && let ty::Adt(inner_def, _) = ty.kind()
if inner_def == def { && inner_def == def
return true; {
} return true;
}
}
}
} }
} }
false false

View file

@ -891,23 +891,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
} }
if let Some(typeck_results) = if let Some(typeck_results) =
self.in_progress_typeck_results.map(|t| t.borrow()) self.in_progress_typeck_results.map(|t| t.borrow())
&& let ty = typeck_results.expr_ty_adjusted(base)
&& let ty::FnDef(def_id, _substs) = ty.kind()
&& let Some(hir::Node::Item(hir::Item { span, ident, .. })) =
hir.get_if_local(*def_id)
{ {
let ty = typeck_results.expr_ty_adjusted(base); err.span_suggestion_verbose(
if let ty::FnDef(def_id, _substs) = ty.kind() { span.shrink_to_lo(),
if let Some(hir::Node::Item(hir::Item { span, ident, .. })) = &format!(
hir.get_if_local(*def_id) "alternatively, consider making `fn {}` asynchronous",
{ ident
err.span_suggestion_verbose( ),
span.shrink_to_lo(), "async ".to_string(),
&format!( Applicability::MaybeIncorrect,
"alternatively, consider making `fn {}` asynchronous", );
ident
),
"async ".to_string(),
Applicability::MaybeIncorrect,
);
}
}
} }
} }
} }
@ -1000,34 +997,24 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
span: Span, span: Span,
trait_pred: ty::PolyTraitPredicate<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
) { ) {
let is_empty_tuple =
|ty: ty::Binder<'tcx, Ty<'_>>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty());
let hir = self.tcx.hir(); let hir = self.tcx.hir();
let parent_node = hir.get_parent_node(obligation.cause.body_id); let parent_node = hir.get_parent_node(obligation.cause.body_id);
let node = hir.find(parent_node); let node = hir.find(parent_node);
if let Some(hir::Node::Item(hir::Item { if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })) = node
kind: hir::ItemKind::Fn(sig, _, body_id), .. && let body = hir.body(*body_id)
})) = node && let hir::ExprKind::Block(blk, _) = &body.value.kind
&& sig.decl.output.span().overlaps(span)
&& blk.expr.is_none()
&& *trait_pred.self_ty().skip_binder().kind() == ty::Tuple(ty::List::empty())
// FIXME(estebank): When encountering a method with a trait
// bound not satisfied in the return type with a body that has
// no return, suggest removal of semicolon on last statement.
// Once that is added, close #54771.
&& let Some(stmt) = blk.stmts.last()
&& let hir::StmtKind::Semi(_) = stmt.kind
{ {
let body = hir.body(*body_id); let sp = self.tcx.sess.source_map().end_point(stmt.span);
if let hir::ExprKind::Block(blk, _) = &body.value.kind { err.span_label(sp, "consider removing this semicolon");
if sig.decl.output.span().overlaps(span)
&& blk.expr.is_none()
&& is_empty_tuple(trait_pred.self_ty())
{
// FIXME(estebank): When encountering a method with a trait
// bound not satisfied in the return type with a body that has
// no return, suggest removal of semicolon on last statement.
// Once that is added, close #54771.
if let Some(ref stmt) = blk.stmts.last() {
if let hir::StmtKind::Semi(_) = stmt.kind {
let sp = self.tcx.sess.source_map().end_point(stmt.span);
err.span_label(sp, "consider removing this semicolon");
}
}
}
}
} }
} }
@ -2481,17 +2468,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation); debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation);
if self.predicate_may_hold(&try_obligation) if self.predicate_may_hold(&try_obligation)
&& impls_future.must_apply_modulo_regions() && impls_future.must_apply_modulo_regions()
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
&& snippet.ends_with('?')
{ {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { err.span_suggestion_verbose(
if snippet.ends_with('?') { span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(),
err.span_suggestion_verbose( "consider `await`ing on the `Future`",
span.with_hi(span.hi() - BytePos(1)).shrink_to_hi(), ".await".to_string(),
"consider `await`ing on the `Future`", Applicability::MaybeIncorrect,
".await".to_string(), );
Applicability::MaybeIncorrect,
);
}
}
} }
} }
} }

View file

@ -91,10 +91,8 @@ impl<'tcx> OnUnimplementedDirective {
) )
})?; })?;
attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| { attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| {
if let Some(symbol) = item.value_str() { if let Some(symbol) = item.value_str() && parse_value(symbol).is_err() {
if parse_value(symbol).is_err() { errored = true;
errored = true;
}
} }
true true
}); });
@ -232,24 +230,22 @@ impl<'tcx> OnUnimplementedDirective {
options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect(); options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
for command in self.subcommands.iter().chain(Some(self)).rev() { for command in self.subcommands.iter().chain(Some(self)).rev() {
if let Some(ref condition) = command.condition { if let Some(ref condition) = command.condition && !attr::eval_condition(
if !attr::eval_condition( condition,
condition, &tcx.sess.parse_sess,
&tcx.sess.parse_sess, Some(tcx.features()),
Some(tcx.features()), &mut |c| {
&mut |c| { c.ident().map_or(false, |ident| {
c.ident().map_or(false, |ident| { let value = c.value_str().map(|s| {
let value = c.value_str().map(|s| { OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map)
OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map) });
});
options.contains(&(ident.name, value)) options.contains(&(ident.name, value))
}) })
}, },
) { ) {
debug!("evaluate: skipping {:?} due to condition", command); debug!("evaluate: skipping {:?} due to condition", command);
continue; continue;
}
} }
debug!("evaluate: {:?} succeeded", command); debug!("evaluate: {:?} succeeded", command);
if let Some(ref message_) = command.message { if let Some(ref message_) = command.message {

View file

@ -43,21 +43,19 @@ impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
let c_ty = self.infcx.canonicalize_query(self.param_env.and(ty), &mut orig_values); let c_ty = self.infcx.canonicalize_query(self.param_env.and(ty), &mut orig_values);
let span = self.cause.span; let span = self.cause.span;
debug!("c_ty = {:?}", c_ty); debug!("c_ty = {:?}", c_ty);
if let Ok(result) = tcx.dropck_outlives(c_ty) { if let Ok(result) = tcx.dropck_outlives(c_ty)
if result.is_proven() { && result.is_proven()
if let Ok(InferOk { value, obligations }) = && let Ok(InferOk { value, obligations }) =
self.infcx.instantiate_query_response_and_region_obligations( self.infcx.instantiate_query_response_and_region_obligations(
self.cause, self.cause,
self.param_env, self.param_env,
&orig_values, &orig_values,
result, result,
) )
{ {
let ty = self.infcx.resolve_vars_if_possible(ty); let ty = self.infcx.resolve_vars_if_possible(ty);
let kinds = value.into_kinds_reporting_overflows(tcx, span, ty); let kinds = value.into_kinds_reporting_overflows(tcx, span, ty);
return InferOk { value: kinds, obligations }; return InferOk { value: kinds, obligations };
}
}
} }
// Errors and ambiuity in dropck occur in two cases: // Errors and ambiuity in dropck occur in two cases:

View file

@ -12,50 +12,38 @@ pub(crate) fn update<'tcx, T>(
T: TraitEngine<'tcx>, T: TraitEngine<'tcx>,
{ {
// (*) binder skipped // (*) binder skipped
if let ty::PredicateKind::Trait(predicate) = obligation.predicate.kind().skip_binder() { if let ty::PredicateKind::Trait(tpred) = obligation.predicate.kind().skip_binder()
if let Some(ty) = && let Some(ty) = infcx.shallow_resolve(tpred.self_ty()).ty_vid().map(|t| infcx.root_var(t))
infcx.shallow_resolve(predicate.self_ty()).ty_vid().map(|t| infcx.root_var(t)) && infcx.tcx.lang_items().sized_trait().map_or(false, |st| st != tpred.trait_ref.def_id)
{ {
if infcx let new_self_ty = infcx.tcx.types.unit;
.tcx
.lang_items()
.sized_trait()
.map_or(false, |st| st != predicate.trait_ref.def_id)
{
let new_self_ty = infcx.tcx.types.unit;
let trait_ref = ty::TraitRef { let trait_ref = ty::TraitRef {
substs: infcx substs: infcx.tcx.mk_substs_trait(new_self_ty, &tpred.trait_ref.substs[1..]),
.tcx ..tpred.trait_ref
.mk_substs_trait(new_self_ty, &predicate.trait_ref.substs[1..]), };
..predicate.trait_ref
};
// Then contstruct a new obligation with Self = () added // Then contstruct a new obligation with Self = () added
// to the ParamEnv, and see if it holds. // to the ParamEnv, and see if it holds.
let o = rustc_infer::traits::Obligation::new( let o = rustc_infer::traits::Obligation::new(
ObligationCause::dummy(), ObligationCause::dummy(),
obligation.param_env, obligation.param_env,
obligation obligation
.predicate .predicate
.kind() .kind()
.map_bound(|_| { .map_bound(|_| {
// (*) binder moved here // (*) binder moved here
ty::PredicateKind::Trait(ty::TraitPredicate { ty::PredicateKind::Trait(ty::TraitPredicate {
trait_ref, trait_ref,
constness: predicate.constness, constness: tpred.constness,
polarity: predicate.polarity, polarity: tpred.polarity,
}) })
}) })
.to_predicate(infcx.tcx), .to_predicate(infcx.tcx),
); );
// Don't report overflow errors. Otherwise equivalent to may_hold. // Don't report overflow errors. Otherwise equivalent to may_hold.
if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) { if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) && result.may_apply() {
if result.may_apply() { engine.relationships().entry(ty).or_default().self_in_trait = true;
engine.relationships().entry(ty).or_default().self_in_trait = true;
}
}
}
} }
} }

View file

@ -579,24 +579,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
previous_stack, previous_stack,
subobligations, subobligations,
); );
if let Ok(res) = res { if let Ok(eval_rslt) = res
if res == EvaluatedToOk || res == EvaluatedToOkModuloRegions { && (eval_rslt == EvaluatedToOk || eval_rslt == EvaluatedToOkModuloRegions)
if let Some(key) = && let Some(key) =
ProjectionCacheKey::from_poly_projection_predicate( ProjectionCacheKey::from_poly_projection_predicate(
self, data, self, data,
) )
{ {
// If the result is something that we can cache, then mark this // If the result is something that we can cache, then mark this
// entry as 'complete'. This will allow us to skip evaluating the // entry as 'complete'. This will allow us to skip evaluating the
// suboligations at all the next time we evaluate the projection // suboligations at all the next time we evaluate the projection
// predicate. // predicate.
self.infcx self.infcx
.inner .inner
.borrow_mut() .borrow_mut()
.projection_cache() .projection_cache()
.complete(key, res); .complete(key, eval_rslt);
}
}
} }
res res
} }

View file

@ -224,36 +224,30 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
// projection coming from another associated type. See // projection coming from another associated type. See
// `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs` and
// `traits-assoc-type-in-supertrait-bad.rs`. // `traits-assoc-type-in-supertrait-bad.rs`.
if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind()) { if let Some(ty::Projection(projection_ty)) = proj.term.ty().map(|ty| ty.kind())
if let Some(&impl_item_id) = && let Some(&impl_item_id) =
tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id) tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id)
{ && let Some(impl_item_span) = items
if let Some(impl_item_span) = items .iter()
.iter() .find(|item| item.id.def_id.to_def_id() == impl_item_id)
.find(|item| item.id.def_id.to_def_id() == impl_item_id) .map(fix_span)
.map(fix_span) {
{ cause.span = impl_item_span;
cause.span = impl_item_span;
}
}
} }
} }
ty::PredicateKind::Trait(pred) => { ty::PredicateKind::Trait(pred) => {
// An associated item obligation born out of the `trait` failed to be met. An example // An associated item obligation born out of the `trait` failed to be met. An example
// can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`. // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred); debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind() { if let ty::Projection(ty::ProjectionTy { item_def_id, .. }) = *pred.self_ty().kind()
if let Some(&impl_item_id) = && let Some(&impl_item_id) =
tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id) tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id)
{ && let Some(impl_item_span) = items
if let Some(impl_item_span) = items .iter()
.iter() .find(|item| item.id.def_id.to_def_id() == impl_item_id)
.find(|item| item.id.def_id.to_def_id() == impl_item_id) .map(fix_span)
.map(fix_span) {
{ cause.span = impl_item_span;
cause.span = impl_item_span;
}
}
} }
} }
_ => {} _ => {}