Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8 - Make more use of let_chains #94484

Merged
merged 1 commit into from
Mar 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 35 additions & 42 deletions compiler/rustc_infer/src/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,17 +606,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// don't show type `_`
err.span_label(span, format!("this expression has type `{}`", ty));
}
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
if ty.is_box() && ty.boxed_ty() == found {
if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
err.span_suggestion(
span,
"consider dereferencing the boxed value",
format!("*{}", snippet),
Applicability::MachineApplicable,
);
}
}
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
&& ty.is_box() && ty.boxed_ty() == found
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
{
err.span_suggestion(
span,
"consider dereferencing the boxed value",
format!("*{}", snippet),
Applicability::MachineApplicable,
);
}
}
ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
Expand Down Expand Up @@ -1748,13 +1747,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
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());

if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values {
if let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind() {
if 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");
}
}
if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values
&& let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind()
&& 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");
}

// It reads better to have the error origin as the final
Expand Down Expand Up @@ -2046,19 +2044,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// containing a single character, perhaps the user meant to write `'c'` to
// specify a character literal (issue #92479)
(ty::Char, ty::Ref(_, r, _)) if r.is_str() => {
if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) {
if let Some(code) =
code.strip_prefix('"').and_then(|s| s.strip_suffix('"'))
{
if code.chars().count() == 1 {
err.span_suggestion(
span,
"if you meant to write a `char` literal, use single quotes",
format!("'{}'", code),
Applicability::MachineApplicable,
);
}
}
if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
&& let Some(code) = code.strip_prefix('"').and_then(|s| s.strip_suffix('"'))
&& code.chars().count() == 1
{
err.span_suggestion(
span,
"if you meant to write a `char` literal, use single quotes",
format!("'{}'", code),
Applicability::MachineApplicable,
);
}
}
// If a string was expected and the found expression is a character literal,
Expand All @@ -2080,18 +2075,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
_ => {}
}
}
if let MatchExpressionArm(box MatchExpressionArmCause { source, .. }) =
*trace.cause.code()
let 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 {
if let Some((expected_ty, found_ty)) = self.values_str(trace.values) {
err.note(&format!(
"`?` operator cannot convert from `{}` to `{}`",
found_ty.content(),
expected_ty.content(),
));
}
}
err.note(&format!(
"`?` operator cannot convert from `{}` to `{}`",
found_ty.content(),
expected_ty.content(),
));
}
err
}
Expand Down
89 changes: 41 additions & 48 deletions compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,28 +114,25 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
}

fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
if let ExprKind::Match(scrutinee, [_, arm], MatchSource::ForLoopDesugar) = expr.kind {
if let Some(pat) = arm.pat.for_loop_some() {
if let Some(ty) = self.node_ty_contains_target(pat.hir_id) {
self.found_for_loop_iter = Some(scrutinee);
self.found_node_ty = Some(ty);
return;
}
}
if let ExprKind::Match(scrutinee, [_, arm], MatchSource::ForLoopDesugar) = expr.kind
&& let Some(pat) = arm.pat.for_loop_some()
&& let Some(ty) = self.node_ty_contains_target(pat.hir_id)
{
self.found_for_loop_iter = Some(scrutinee);
self.found_node_ty = Some(ty);
return;
}
if let ExprKind::MethodCall(segment, exprs, _) = expr.kind {
if segment.ident.span == self.target_span
&& Some(self.target)
== self.infcx.in_progress_typeck_results.and_then(|typeck_results| {
typeck_results
.borrow()
.node_type_opt(exprs.first().unwrap().hir_id)
.map(Into::into)
})
{
self.found_exact_method_call = Some(&expr);
return;
}
if let ExprKind::MethodCall(segment, exprs, _) = expr.kind
&& segment.ident.span == self.target_span
&& Some(self.target) == self.infcx.in_progress_typeck_results.and_then(|typeck_results| {
typeck_results
.borrow()
.node_type_opt(exprs.first().unwrap().hir_id)
.map(Into::into)
})
{
self.found_exact_method_call = Some(&expr);
return;
}

// FIXME(const_generics): Currently, any uninferred `const` generics arguments
Expand Down Expand Up @@ -602,10 +599,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);

let use_diag = local_visitor.found_use_diagnostic.as_ref();
if let Some(use_diag) = use_diag {
if use_diag.applies_to(err_span) {
use_diag.attach_note(&mut err);
}
if let Some(use_diag) = use_diag && use_diag.applies_to(err_span) {
use_diag.attach_note(&mut err);
}

let param_type = arg_data.kind.descr();
Expand Down Expand Up @@ -736,29 +731,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// | help: specify type like: `<Impl as Into<u32>>::into(foo_impl)`
// |
// = note: cannot satisfy `Impl: Into<_>`
if !impl_candidates.is_empty() && e.span.contains(span) {
if let Some(expr) = exprs.first() {
if let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind {
if let [path_segment] = path.segments {
let candidate_len = impl_candidates.len();
let suggestions = impl_candidates.iter().map(|candidate| {
format!(
"{}::{}({})",
candidate, segment.ident, path_segment.ident
)
});
err.span_suggestions(
e.span,
&format!(
"use the fully qualified path for the potential candidate{}",
pluralize!(candidate_len),
),
suggestions,
Applicability::MaybeIncorrect,
);
}
}
};
if !impl_candidates.is_empty() && e.span.contains(span)
&& let Some(expr) = exprs.first()
&& let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind
&& let [path_segment] = path.segments
{
let candidate_len = impl_candidates.len();
let suggestions = impl_candidates.iter().map(|candidate| {
format!(
"{}::{}({})",
candidate, segment.ident, path_segment.ident
)
});
err.span_suggestions(
e.span,
&format!(
"use the fully qualified path for the potential candidate{}",
pluralize!(candidate_len),
),
suggestions,
Applicability::MaybeIncorrect,
);
}
// Suggest specifying type params or point out the return type of the call:
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 mut override_error_code = None;
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin {
if let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code() {
// 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()`.
if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) {
override_error_code = Some(ctxt.assoc_item.name);
}
}
if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = &sup_origin
&& let ObligationCauseCode::UnifyReceiver(ctxt) = cause.code()
// 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()`.
&& self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt)
{
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(),
_ => cause.code(),
};
if let (ObligationCauseCode::ItemObligation(item_def_id), None) =
(code, override_error_code)
}
&& let (ObligationCauseCode::ItemObligation(item_def_id), None) = (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`
// 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);
}
}
override_error_code = Some(ident.name);
}
}
if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,51 +23,39 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let error = self.error.as_ref()?;
debug!("try_report_impl_not_conforming_to_trait {:?}", error);
if let RegionResolutionError::SubSupConflict(
_,
var_origin,
sub_origin,
_sub,
sup_origin,
_sup,
_,
) = error.clone()
_, var_origin, sub_origin, _sub, sup_origin, _sup, _,
) = error.clone()
&& let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin)
&& let (
sub_expected_found @ Some((sub_expected, sub_found)),
sup_expected_found @ Some(_),
CompareImplMethodObligation { trait_item_def_id, .. },
) = (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) {
if let (
sub_expected_found @ Some((sub_expected, sub_found)),
sup_expected_found @ Some(_),
CompareImplMethodObligation { trait_item_def_id, .. },
) = (&sub_trace.values.ty(), &sup_trace.values.ty(), sub_trace.cause.code())
{
if sup_expected_found == sub_expected_found {
self.emit_err(
var_origin.span(),
*sub_expected,
*sub_found,
*trait_item_def_id,
);
return Some(ErrorGuaranteed);
}
}
}
self.emit_err(
var_origin.span(),
sub_expected,
sub_found,
*trait_item_def_id,
);
return Some(ErrorGuaranteed);
}
if let RegionResolutionError::ConcreteFailure(origin, _, _)
| RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone()
{
if let SubregionOrigin::CompareImplTypeObligation {
| RegionResolutionError::GenericBoundFailure(origin, _, _) = error.clone()
&& let SubregionOrigin::CompareImplTypeObligation {
span,
impl_item_def_id,
trait_item_def_id,
} = origin
{
self.emit_associated_type_err(
span,
self.infcx.tcx.item_name(impl_item_def_id),
impl_item_def_id,
trait_item_def_id,
);
return Some(ErrorGuaranteed);
}
{
self.emit_associated_type_err(
span,
self.infcx.tcx.item_name(impl_item_def_id),
impl_item_def_id,
trait_item_def_id,
);
return Some(ErrorGuaranteed);
}
None
}
Expand Down
10 changes: 4 additions & 6 deletions compiler/rustc_infer/src/infer/fudge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
if let ty::ReVar(vid) = *r {
if self.region_vars.0.contains(&vid) {
let idx = vid.index() - self.region_vars.0.start.index();
let origin = self.region_vars.1[idx];
return self.infcx.next_region_var(origin);
}
if let ty::ReVar(vid) = *r && self.region_vars.0.contains(&vid) {
let idx = vid.index() - self.region_vars.0.start.index();
let origin = self.region_vars.1[idx];
return self.infcx.next_region_var(origin);
}
r
}
Expand Down
12 changes: 4 additions & 8 deletions compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,10 +304,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// check below for a common case, here purely as an
// optimization.
let b_universe = self.var_infos[b_vid].universe;
if let ReEmpty(a_universe) = *a_region {
if a_universe == b_universe {
return false;
}
if let ReEmpty(a_universe) = *a_region && a_universe == b_universe {
return false;
}

let mut lub = self.lub_concrete_regions(a_region, cur_region);
Expand All @@ -324,10 +322,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
// tighter bound than `'static`.
//
// (This might e.g. arise from being asked to prove `for<'a> { 'b: 'a }`.)
if let ty::RePlaceholder(p) = *lub {
if b_universe.cannot_name(p.universe) {
lub = self.tcx().lifetimes.re_static;
}
if let ty::RePlaceholder(p) = *lub && b_universe.cannot_name(p.universe) {
lub = self.tcx().lifetimes.re_static;
}

debug!("Expanding value of {:?} from {:?} to {:?}", b_vid, cur_region, lub);
Expand Down
Loading