add typecheck for iterator
This commit is contained in:
parent
44a8a8d0ca
commit
4189faa21e
@ -28,7 +28,6 @@ use rustc_span::{BytePos, Span, Symbol};
|
|||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits::ObligationCtxt;
|
use rustc_trait_selection::traits::ObligationCtxt;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
use crate::borrow_set::TwoPhaseActivation;
|
use crate::borrow_set::TwoPhaseActivation;
|
||||||
use crate::borrowck_errors;
|
use crate::borrowck_errors;
|
||||||
@ -1305,12 +1304,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
let hir = tcx.hir();
|
let hir = tcx.hir();
|
||||||
|
|
||||||
let Some(body_id) = hir.get(self.mir_hir_id()).body_id() else { return };
|
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> {
|
struct ExprFinder<'hir> {
|
||||||
phantom: PhantomData<&'hir hir::Expr<'hir>>,
|
|
||||||
issue_span: Span,
|
issue_span: Span,
|
||||||
expr_span: Span,
|
expr_span: Span,
|
||||||
found_body_expr: bool,
|
body_expr: Option<&'hir hir::Expr<'hir>>,
|
||||||
loop_bind: Option<Symbol>,
|
loop_bind: Option<Symbol>,
|
||||||
}
|
}
|
||||||
impl<'hir> Visitor<'hir> for ExprFinder<'hir> {
|
impl<'hir> Visitor<'hir> for ExprFinder<'hir> {
|
||||||
@ -1326,25 +1325,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
self.loop_bind = Some(ident.name);
|
self.loop_bind = Some(ident.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let hir::ExprKind::MethodCall(body_call, ..) = ex.kind &&
|
if let hir::ExprKind::MethodCall(body_call, _recv, ..) = ex.kind &&
|
||||||
body_call.ident.name == sym::next &&
|
body_call.ident.name == sym::next && ex.span.source_equal(self.expr_span) {
|
||||||
ex.span.source_equal(self.expr_span) {
|
self.body_expr = Some(ex);
|
||||||
self.found_body_expr = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::intravisit::walk_expr(self, ex);
|
hir::intravisit::walk_expr(self, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut finder = ExprFinder {
|
let mut finder =
|
||||||
phantom: PhantomData,
|
ExprFinder { expr_span: span, issue_span, loop_bind: None, body_expr: None };
|
||||||
expr_span: span,
|
|
||||||
issue_span,
|
|
||||||
loop_bind: None,
|
|
||||||
found_body_expr: false,
|
|
||||||
};
|
|
||||||
finder.visit_expr(hir.body(body_id).value);
|
finder.visit_expr(hir.body(body_id).value);
|
||||||
|
|
||||||
if let Some(loop_bind) = finder.loop_bind &&
|
if let Some(loop_bind) = finder.loop_bind &&
|
||||||
finder.found_body_expr {
|
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!(
|
err.note(format!(
|
||||||
"a for loop advances the iterator for you, the result is stored in `{}`.",
|
"a for loop advances the iterator for you, the result is stored in `{}`.",
|
||||||
loop_bind
|
loop_bind
|
||||||
|
Loading…
x
Reference in New Issue
Block a user