Skip to content

Commit

Permalink
add typecheck for iterator
Browse files Browse the repository at this point in the history
  • Loading branch information
chenyukang committed Jun 30, 2023
1 parent 44a8a8d commit 4189faa
Showing 1 changed file with 17 additions and 20 deletions.
37 changes: 17 additions & 20 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ use rustc_span::{BytePos, Span, Symbol};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::ObligationCtxt;
use std::iter;
use std::marker::PhantomData;

use crate::borrow_set::TwoPhaseActivation;
use crate::borrowck_errors;
Expand Down Expand Up @@ -1305,12 +1304,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let hir = tcx.hir();

let Some(body_id) = hir.get(self.mir_hir_id()).body_id() else { return };
let typeck_results = tcx.typeck(self.mir_def_id());

struct ExprFinder<'hir> {
phantom: PhantomData<&'hir hir::Expr<'hir>>,
issue_span: Span,
expr_span: Span,
found_body_expr: bool,
body_expr: Option<&'hir hir::Expr<'hir>>,
loop_bind: Option<Symbol>,
}
impl<'hir> Visitor<'hir> for ExprFinder<'hir> {
Expand All @@ -1326,30 +1325,28 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
self.loop_bind = Some(ident.name);
}

if let hir::ExprKind::MethodCall(body_call, ..) = ex.kind &&
body_call.ident.name == sym::next &&
ex.span.source_equal(self.expr_span) {
self.found_body_expr = true;
if let hir::ExprKind::MethodCall(body_call, _recv, ..) = ex.kind &&
body_call.ident.name == sym::next && ex.span.source_equal(self.expr_span) {
self.body_expr = Some(ex);
}

hir::intravisit::walk_expr(self, ex);
}
}
let mut finder = ExprFinder {
phantom: PhantomData,
expr_span: span,
issue_span,
loop_bind: None,
found_body_expr: false,
};
let mut finder =
ExprFinder { expr_span: span, issue_span, loop_bind: None, body_expr: None };
finder.visit_expr(hir.body(body_id).value);

if let Some(loop_bind) = finder.loop_bind &&
finder.found_body_expr {
err.note(format!(
"a for loop advances the iterator for you, the result is stored in `{}`.",
loop_bind
));
err.help("if you want to call `next` on a iterator within the loop, consider using `while let`.");
let Some(body_expr) = finder.body_expr &&
let Some(def_id) = typeck_results.type_dependent_def_id(body_expr.hir_id) &&
let Some(trait_did) = tcx.trait_of_item(def_id) &&
tcx.is_diagnostic_item(sym::Iterator, trait_did) {
err.note(format!(
"a for loop advances the iterator for you, the result is stored in `{}`.",
loop_bind
));
err.help("if you want to call `next` on a iterator within the loop, consider using `while let`.");
}
}

Expand Down

0 comments on commit 4189faa

Please sign in to comment.