1
Fork 0

8 - Make more use of let_chains

This commit is contained in:
Caio 2022-03-02 16:02:37 -03:00
parent 08504c64aa
commit 658ff942b0
10 changed files with 146 additions and 186 deletions

View file

@ -606,17 +606,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// don't show type `_` // don't show type `_`
err.span_label(span, format!("this expression has type `{}`", ty)); err.span_label(span, format!("this expression has type `{}`", ty));
} }
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found { if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
if ty.is_box() && ty.boxed_ty() == found { && ty.is_box() && ty.boxed_ty() == found
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
err.span_suggestion( {
span, err.span_suggestion(
"consider dereferencing the boxed value", span,
format!("*{}", snippet), "consider dereferencing the boxed value",
Applicability::MachineApplicable, format!("*{}", snippet),
); Applicability::MachineApplicable,
} );
}
} }
} }
ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => { ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
@ -1748,13 +1747,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.check_and_note_conflicting_crates(diag, terr); self.check_and_note_conflicting_crates(diag, terr);
self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id()); self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id());
if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values { if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values
if let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind() { && let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind()
if let Some(def_id) = def_id.as_local() { && let Some(def_id) = def_id.as_local()
let span = self.tcx.def_span(def_id); {
diag.span_note(span, "this closure does not fulfill the lifetime requirements"); let span = self.tcx.def_span(def_id);
} diag.span_note(span, "this closure does not fulfill the lifetime requirements");
}
} }
// It reads better to have the error origin as the final // It reads better to have the error origin as the final
@ -2046,19 +2044,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// containing a single character, perhaps the user meant to write `'c'` to // containing a single character, perhaps the user meant to write `'c'` to
// specify a character literal (issue #92479) // specify a character literal (issue #92479)
(ty::Char, ty::Ref(_, r, _)) if r.is_str() => { (ty::Char, ty::Ref(_, r, _)) if r.is_str() => {
if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) { if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
if let Some(code) = && let Some(code) = code.strip_prefix('"').and_then(|s| s.strip_suffix('"'))
code.strip_prefix('"').and_then(|s| s.strip_suffix('"')) && code.chars().count() == 1
{ {
if code.chars().count() == 1 { err.span_suggestion(
err.span_suggestion( span,
span, "if you meant to write a `char` literal, use single quotes",
"if you meant to write a `char` literal, use single quotes", format!("'{}'", code),
format!("'{}'", code), Applicability::MachineApplicable,
Applicability::MachineApplicable, );
);
}
}
} }
} }
// If a string was expected and the found expression is a character literal, // If a string was expected and the found expression is a character literal,
@ -2080,18 +2075,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
_ => {} _ => {}
} }
} }
if let MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = let code = trace.cause.code();
*trace.cause.code() if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code
&& let hir::MatchSource::TryDesugar = source
&& let Some((expected_ty, found_ty)) = self.values_str(trace.values)
{ {
if let hir::MatchSource::TryDesugar = source { err.note(&format!(
if let Some((expected_ty, found_ty)) = self.values_str(trace.values) { "`?` operator cannot convert from `{}` to `{}`",
err.note(&format!( found_ty.content(),
"`?` operator cannot convert from `{}` to `{}`", expected_ty.content(),
found_ty.content(), ));
expected_ty.content(),
));
}
}
} }
err err
} }

View file

@ -114,28 +114,25 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
} }
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
if let ExprKind::Match(scrutinee, [_, arm], MatchSource::ForLoopDesugar) = expr.kind { if let ExprKind::Match(scrutinee, [_, arm], MatchSource::ForLoopDesugar) = expr.kind
if let Some(pat) = arm.pat.for_loop_some() { && let Some(pat) = arm.pat.for_loop_some()
if let Some(ty) = self.node_ty_contains_target(pat.hir_id) { && let Some(ty) = self.node_ty_contains_target(pat.hir_id)
self.found_for_loop_iter = Some(scrutinee); {
self.found_node_ty = Some(ty); self.found_for_loop_iter = Some(scrutinee);
return; self.found_node_ty = Some(ty);
} return;
}
} }
if let ExprKind::MethodCall(segment, exprs, _) = expr.kind { if let ExprKind::MethodCall(segment, exprs, _) = expr.kind
if segment.ident.span == self.target_span && segment.ident.span == self.target_span
&& Some(self.target) && Some(self.target) == self.infcx.in_progress_typeck_results.and_then(|typeck_results| {
== self.infcx.in_progress_typeck_results.and_then(|typeck_results| { typeck_results
typeck_results .borrow()
.borrow() .node_type_opt(exprs.first().unwrap().hir_id)
.node_type_opt(exprs.first().unwrap().hir_id) .map(Into::into)
.map(Into::into) })
}) {
{ self.found_exact_method_call = Some(&expr);
self.found_exact_method_call = Some(&expr); return;
return;
}
} }
// FIXME(const_generics): Currently, any uninferred `const` generics arguments // FIXME(const_generics): Currently, any uninferred `const` generics arguments
@ -602,10 +599,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
); );
let use_diag = local_visitor.found_use_diagnostic.as_ref(); let use_diag = local_visitor.found_use_diagnostic.as_ref();
if let Some(use_diag) = use_diag { if let Some(use_diag) = use_diag && use_diag.applies_to(err_span) {
if use_diag.applies_to(err_span) { use_diag.attach_note(&mut err);
use_diag.attach_note(&mut err);
}
} }
let param_type = arg_data.kind.descr(); let param_type = arg_data.kind.descr();
@ -736,29 +731,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// | help: specify type like: `<Impl as Into<u32>>::into(foo_impl)` // | help: specify type like: `<Impl as Into<u32>>::into(foo_impl)`
// | // |
// = note: cannot satisfy `Impl: Into<_>` // = note: cannot satisfy `Impl: Into<_>`
if !impl_candidates.is_empty() && e.span.contains(span) { if !impl_candidates.is_empty() && e.span.contains(span)
if let Some(expr) = exprs.first() { && let Some(expr) = exprs.first()
if let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind { && let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind
if let [path_segment] = path.segments { && let [path_segment] = path.segments
let candidate_len = impl_candidates.len(); {
let suggestions = impl_candidates.iter().map(|candidate| { let candidate_len = impl_candidates.len();
format!( let suggestions = impl_candidates.iter().map(|candidate| {
"{}::{}({})", format!(
candidate, segment.ident, path_segment.ident "{}::{}({})",
) candidate, segment.ident, path_segment.ident
}); )
err.span_suggestions( });
e.span, err.span_suggestions(
&format!( e.span,
"use the fully qualified path for the potential candidate{}", &format!(
pluralize!(candidate_len), "use the fully qualified path for the potential candidate{}",
), pluralize!(candidate_len),
suggestions, ),
Applicability::MaybeIncorrect, suggestions,
); Applicability::MaybeIncorrect,
} );
}
};
} }
// Suggest specifying type params or point out the return type of the call: // Suggest specifying type params or point out the return type of the call:
// //

View file

@ -223,35 +223,32 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id);
let mut override_error_code = None; let mut override_error_code = None;
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin { if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin
if let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() { && let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code()
// Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a // Handle case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a
// `'static` lifetime when called as a method on a binding: `bar.qux()`. // `'static` lifetime when called as a method on a binding: `bar.qux()`.
if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { && self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt)
override_error_code = Some(ctxt.assoc_item.name); {
} override_error_code = Some(ctxt.assoc_item.name);
}
} }
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin {
let code = match cause.code() { if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sub_origin
&& let code = match cause.code() {
ObligationCauseCode::MatchImpl(parent, ..) => parent.code(), ObligationCauseCode::MatchImpl(parent, ..) => parent.code(),
_ => cause.code(), _ => cause.code(),
}; }
if let (ObligationCauseCode::ItemObligation(item_def_id), None) = && let (ObligationCauseCode::ItemObligation(item_def_id), None) = (code, override_error_code)
(code, override_error_code) {
// Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static`
// lifetime as above, but called using a fully-qualified path to the method:
// `Foo::qux(bar)`.
let mut v = TraitObjectVisitor(FxHashSet::default());
v.visit_ty(param.param_ty);
if let Some((ident, self_ty)) =
self.get_impl_ident_and_self_ty_from_trait(*item_def_id, &v.0)
&& self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0, ident, self_ty)
{ {
// Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static` override_error_code = Some(ident.name);
// lifetime as above, but called using a fully-qualified path to the method:
// `Foo::qux(bar)`.
let mut v = TraitObjectVisitor(FxHashSet::default());
v.visit_ty(param.param_ty);
if let Some((ident, self_ty)) =
self.get_impl_ident_and_self_ty_from_trait(*item_def_id, &v.0)
{
if self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0, ident, self_ty) {
override_error_code = Some(ident.name);
}
}
} }
} }
if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) { if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) {

View file

@ -23,51 +23,39 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let error = self.error.as_ref()?; let error = self.error.as_ref()?;
debug!("try_report_impl_not_conforming_to_trait {:?}", error); debug!("try_report_impl_not_conforming_to_trait {:?}", error);
if let RegionResolutionError::SubSupConflict( if let RegionResolutionError::SubSupConflict(
_, _, var_origin, sub_origin, _sub, sup_origin, _sup, _,
var_origin, ) = error.clone()
sub_origin, && let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin)
_sub, && let (
sup_origin, sub_expected_found @ Some((sub_expected, sub_found)),
_sup, sup_expected_found @ Some(_),
_, CompareImplMethodObligation { trait_item_def_id, .. },
) = error.clone() ) = (sub_trace.values.ty(), sup_trace.values.ty(), sub_trace.cause.code())
&& sup_expected_found == sub_expected_found
{ {
if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) { self.emit_err(
if let ( var_origin.span(),
sub_expected_found @ Some((sub_expected, sub_found)), sub_expected,
sup_expected_found @ Some(_), sub_found,
CompareImplMethodObligation { trait_item_def_id, .. }, *trait_item_def_id,
) = (&sub_trace.values.ty(), &sup_trace.values.ty(), sub_trace.cause.code()) );
{ return Some(ErrorGuaranteed);
if sup_expected_found == sub_expected_found {
self.emit_err(
var_origin.span(),
*sub_expected,
*sub_found,
*trait_item_def_id,
);
return Some(ErrorGuaranteed);
}
}
}
} }
if let RegionResolutionError::ConcreteFailure(origin, _, _) if let RegionResolutionError::ConcreteFailure(origin, _, _)
| RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone() | RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone()
{ && let SubregionOrigin::CompareImplTypeObligation {
if let SubregionOrigin::CompareImplTypeObligation {
span, span,
impl_item_def_id, impl_item_def_id,
trait_item_def_id, trait_item_def_id,
} = origin } = origin
{ {
self.emit_associated_type_err( self.emit_associated_type_err(
span, span,
self.infcx.tcx.item_name(impl_item_def_id), self.infcx.tcx.item_name(impl_item_def_id),
impl_item_def_id, impl_item_def_id,
trait_item_def_id, trait_item_def_id,
); );
return Some(ErrorGuaranteed); return Some(ErrorGuaranteed);
}
} }
None None
} }

View file

@ -220,12 +220,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> {
} }
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
if let ty::ReVar(vid) = *r { if let ty::ReVar(vid) = *r && self.region_vars.0.contains(&vid) {
if self.region_vars.0.contains(&vid) { let idx = vid.index() - self.region_vars.0.start.index();
let idx = vid.index() - self.region_vars.0.start.index(); let origin = self.region_vars.1[idx];
let origin = self.region_vars.1[idx]; return self.infcx.next_region_var(origin);
return self.infcx.next_region_var(origin);
}
} }
r r
} }

View file

@ -304,10 +304,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// check below for a common case, here purely as an // check below for a common case, here purely as an
// optimization. // optimization.
let b_universe = self.var_infos[b_vid].universe; let b_universe = self.var_infos[b_vid].universe;
if let ReEmpty(a_universe) = *a_region { if let ReEmpty(a_universe) = *a_region && a_universe == b_universe {
if a_universe == b_universe { return false;
return false;
}
} }
let mut lub = self.lub_concrete_regions(a_region, cur_region); let mut lub = self.lub_concrete_regions(a_region, cur_region);
@ -324,10 +322,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// tighter bound than `'static`. // tighter bound than `'static`.
// //
// (This might e.g. arise from being asked to prove `for<'a> { 'b: 'a }`.) // (This might e.g. arise from being asked to prove `for<'a> { 'b: 'a }`.)
if let ty::RePlaceholder(p) = *lub { if let ty::RePlaceholder(p) = *lub && b_universe.cannot_name(p.universe) {
if b_universe.cannot_name(p.universe) { lub = self.tcx().lifetimes.re_static;
lub = self.tcx().lifetimes.re_static;
}
} }
debug!("Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub); debug!("Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub);

View file

@ -963,10 +963,8 @@ where
) -> RelateResult<'tcx, ty::Region<'tcx>> { ) -> RelateResult<'tcx, ty::Region<'tcx>> {
debug!("TypeGeneralizer::regions(a={:?})", a); debug!("TypeGeneralizer::regions(a={:?})", a);
if let ty::ReLateBound(debruijn, _) = *a { if let ty::ReLateBound(debruijn, _) = *a && debruijn < self.first_free_index {
if debruijn < self.first_free_index { return Ok(a);
return Ok(a);
}
} }
// For now, we just always create a fresh region variable to // For now, we just always create a fresh region variable to

View file

@ -470,10 +470,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
debug!("RegionConstraintCollector: add_verify({:?})", verify); debug!("RegionConstraintCollector: add_verify({:?})", verify);
// skip no-op cases known to be satisfied // skip no-op cases known to be satisfied
if let VerifyBound::AllBounds(ref bs) = verify.bound { if let VerifyBound::AllBounds(ref bs) = verify.bound && bs.is_empty() {
if bs.is_empty() { return;
return;
}
} }
let index = self.data.verifys.len(); let index = self.data.verifys.len();

View file

@ -12,18 +12,19 @@
//! //!
//! 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(control_flow_enum)]
#![feature(derive_default_enum)] #![feature(derive_default_enum)]
#![feature(extend_one)] #![feature(extend_one)]
#![feature(let_else)]
#![feature(never_type)]
#![feature(control_flow_enum)]
#![feature(min_specialization)]
#![feature(label_break_value)] #![feature(label_break_value)]
#![feature(let_chains)]
#![feature(let_else)]
#![feature(min_specialization)]
#![feature(never_type)]
#![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

@ -60,12 +60,10 @@ pub fn report_object_safety_error<'tcx>(
let mut multi_span = vec![]; let mut multi_span = vec![];
let mut messages = vec![]; let mut messages = vec![];
for violation in violations { for violation in violations {
if let ObjectSafetyViolation::SizedSelf(sp) = &violation { if let ObjectSafetyViolation::SizedSelf(sp) = &violation && !sp.is_empty() {
if !sp.is_empty() { // Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations
// Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations // with a `Span`.
// with a `Span`. reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into()));
reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into()));
}
} }
if reported_violations.insert(violation.clone()) { if reported_violations.insert(violation.clone()) {
let spans = violation.spans(); let spans = violation.spans();