about summary refs log tree commit diff
diff options
context:
space:
mode:
authoryukang <moorekang@gmail.com>2023-06-30 14:50:27 +0800
committeryukang <moorekang@gmail.com>2023-06-30 14:50:27 +0800
commit4189faa21edc123e2ccfd3b444b0ad3c030aba0a (patch)
treede6c281d62571581d959ca75ab689cbf9fae4fe8
parent44a8a8d0ca407a08612b87eaff1211dda1528633 (diff)
downloadrust-4189faa21edc123e2ccfd3b444b0ad3c030aba0a.tar.gz
rust-4189faa21edc123e2ccfd3b444b0ad3c030aba0a.zip
add typecheck for iterator
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs37
1 files changed, 17 insertions, 20 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 8a6bdb72968..93eef4d5966 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -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;
@@ -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> {
@@ -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`.");
         }
     }