Stop calling visitors V

This commit is contained in:
Michael Goulet 2024-03-29 19:50:08 -04:00
parent 40116ad1ed
commit bda301ead8
4 changed files with 32 additions and 21 deletions

View File

@ -540,19 +540,23 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
} }
} }
/// Suggest `map[k] = v` => `map.insert(k, v)` and the like.
fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diag<'tcx>, span: Span) { fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diag<'tcx>, span: Span) {
let Some(adt) = ty.ty_adt_def() else { return }; let Some(adt) = ty.ty_adt_def() else { return };
let did = adt.did(); let did = adt.did();
if self.infcx.tcx.is_diagnostic_item(sym::HashMap, did) if self.infcx.tcx.is_diagnostic_item(sym::HashMap, did)
|| self.infcx.tcx.is_diagnostic_item(sym::BTreeMap, did) || self.infcx.tcx.is_diagnostic_item(sym::BTreeMap, did)
{ {
struct V<'a, 'tcx> { /// Walks through the HIR, looking for the corresponding span for this error.
/// When it finds it, see if it corresponds to assignment operator whose LHS
/// is an index expr.
struct SuggestIndexOperatorAlternativeVisitor<'a, 'tcx> {
assign_span: Span, assign_span: Span,
err: &'a mut Diag<'tcx>, err: &'a mut Diag<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
suggested: bool, suggested: bool,
} }
impl<'a, 'tcx> Visitor<'tcx> for V<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for SuggestIndexOperatorAlternativeVisitor<'a, 'tcx> {
fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
hir::intravisit::walk_stmt(self, stmt); hir::intravisit::walk_stmt(self, stmt);
let expr = match stmt.kind { let expr = match stmt.kind {
@ -645,7 +649,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id) else { return }; let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id) else { return };
let body = self.infcx.tcx.hir().body(body_id); let body = self.infcx.tcx.hir().body(body_id);
let mut v = V { assign_span: span, err, ty, suggested: false }; let mut v = SuggestIndexOperatorAlternativeVisitor {
assign_span: span,
err,
ty,
suggested: false,
};
v.visit_body(body); v.visit_body(body);
if !v.suggested { if !v.suggested {
err.help(format!( err.help(format!(

View File

@ -418,8 +418,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
{ {
if let &hir::ClosureBinder::For { span: for_sp, .. } = binder { if let &hir::ClosureBinder::For { span: for_sp, .. } = binder {
fn span_of_infer(ty: &hir::Ty<'_>) -> Option<Span> { fn span_of_infer(ty: &hir::Ty<'_>) -> Option<Span> {
struct V; /// Look for `_` anywhere in the signature of a `for<> ||` closure.
impl<'v> Visitor<'v> for V { /// This is currently disallowed.
struct FindInferInClosureWithBinder;
impl<'v> Visitor<'v> for FindInferInClosureWithBinder {
type Result = ControlFlow<Span>; type Result = ControlFlow<Span>;
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) -> Self::Result { fn visit_ty(&mut self, t: &'v hir::Ty<'v>) -> Self::Result {
if matches!(t.kind, hir::TyKind::Infer) { if matches!(t.kind, hir::TyKind::Infer) {
@ -429,7 +431,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
} }
} }
} }
V.visit_ty(ty).break_value() FindInferInClosureWithBinder.visit_ty(ty).break_value()
} }
let infer_in_rt_sp = match fn_decl.output { let infer_in_rt_sp = match fn_decl.output {

View File

@ -1916,22 +1916,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat: &'tcx hir::Pat<'tcx>, pat: &'tcx hir::Pat<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
) { ) {
struct V {
pat_hir_ids: Vec<hir::HirId>,
}
impl<'tcx> Visitor<'tcx> for V {
fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
self.pat_hir_ids.push(p.hir_id);
hir::intravisit::walk_pat(self, p);
}
}
if let Err(guar) = ty.error_reported() { if let Err(guar) = ty.error_reported() {
struct OverwritePatternsWithError {
pat_hir_ids: Vec<hir::HirId>,
}
impl<'tcx> Visitor<'tcx> for OverwritePatternsWithError {
fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
self.pat_hir_ids.push(p.hir_id);
hir::intravisit::walk_pat(self, p);
}
}
// Override the types everywhere with `err()` to avoid knock on errors. // Override the types everywhere with `err()` to avoid knock on errors.
let err = Ty::new_error(self.tcx, guar); let err = Ty::new_error(self.tcx, guar);
self.write_ty(hir_id, err); self.write_ty(hir_id, err);
self.write_ty(pat.hir_id, err); self.write_ty(pat.hir_id, err);
let mut visitor = V { pat_hir_ids: vec![] }; let mut visitor = OverwritePatternsWithError { pat_hir_ids: vec![] };
hir::intravisit::walk_pat(&mut visitor, pat); hir::intravisit::walk_pat(&mut visitor, pat);
// Mark all the subpatterns as `{type error}` as well. This allows errors for specific // Mark all the subpatterns as `{type error}` as well. This allows errors for specific
// subpatterns to be silenced. // subpatterns to be silenced.

View File

@ -1128,10 +1128,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
err: &mut Diag<'_>, err: &mut Diag<'_>,
) -> bool { ) -> bool {
let span = obligation.cause.span; let span = obligation.cause.span;
struct V { /// Look for the (direct) sub-expr of `?`, and return it if it's a `.` method call.
struct FindMethodSubexprOfTry {
search_span: Span, search_span: Span,
} }
impl<'v> Visitor<'v> for V { impl<'v> Visitor<'v> for FindMethodSubexprOfTry {
type Result = ControlFlow<&'v hir::Expr<'v>>; type Result = ControlFlow<&'v hir::Expr<'v>>;
fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) -> Self::Result { fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) -> Self::Result {
if let hir::ExprKind::Match(expr, _arms, hir::MatchSource::TryDesugar(_)) = ex.kind if let hir::ExprKind::Match(expr, _arms, hir::MatchSource::TryDesugar(_)) = ex.kind
@ -1149,8 +1150,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => body_id, hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => body_id,
_ => return false, _ => return false,
}; };
let ControlFlow::Break(expr) = let ControlFlow::Break(expr) = (FindMethodSubexprOfTry { search_span: span })
(V { search_span: span }).visit_body(self.tcx.hir().body(*body_id)) .visit_body(self.tcx.hir().body(*body_id))
else { else {
return false; return false;
}; };