about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2023-10-16 19:48:53 +0000
committerEsteban Küber <esteban@kuber.com.ar>2023-10-16 19:48:53 +0000
commit26954f60ffd4fa462b06edf05290104aa8cdbdc3 (patch)
tree8b82f3844b0cfd2a3a86fadb20235b0c2f036308 /compiler
parent6d23ee8430df1b2dfedb48f8321d9c47b26d7858 (diff)
downloadrust-26954f60ffd4fa462b06edf05290104aa8cdbdc3.tar.gz
rust-26954f60ffd4fa462b06edf05290104aa8cdbdc3.zip
address review comment
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs215
1 files changed, 125 insertions, 90 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index fd52d629660..34097cb173e 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -313,6 +313,18 @@ pub trait TypeErrCtxtExt<'tcx> {
         predicate: ty::Predicate<'tcx>,
         call_hir_id: HirId,
     );
+
+    fn look_for_iterator_item_mistakes(
+        &self,
+        assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>],
+        typeck_results: &TypeckResults<'tcx>,
+        type_diffs: &[TypeError<'tcx>],
+        param_env: ty::ParamEnv<'tcx>,
+        path_segment: &hir::PathSegment<'_>,
+        args: &[hir::Expr<'_>],
+        err: &mut Diagnostic,
+    );
+
     fn point_at_chain(
         &self,
         expr: &hir::Expr<'_>,
@@ -321,6 +333,7 @@ pub trait TypeErrCtxtExt<'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         err: &mut Diagnostic,
     );
+
     fn probe_assoc_types_at_expr(
         &self,
         type_diffs: &[TypeError<'tcx>],
@@ -3592,6 +3605,109 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         }
     }
 
+    fn look_for_iterator_item_mistakes(
+        &self,
+        assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>],
+        typeck_results: &TypeckResults<'tcx>,
+        type_diffs: &[TypeError<'tcx>],
+        param_env: ty::ParamEnv<'tcx>,
+        path_segment: &hir::PathSegment<'_>,
+        args: &[hir::Expr<'_>],
+        err: &mut Diagnostic,
+    ) {
+        let tcx = self.tcx;
+        // Special case for iterator chains, we look at potential failures of `Iterator::Item`
+        // not being `: Clone` and `Iterator::map` calls with spurious trailing `;`.
+        for entry in assocs_in_this_method {
+            let Some((_span, (def_id, ty))) = entry else {
+                continue;
+            };
+            for diff in type_diffs {
+                let Sorts(expected_found) = diff else {
+                    continue;
+                };
+                if tcx.is_diagnostic_item(sym::IteratorItem, *def_id)
+                    && path_segment.ident.name == sym::map
+                    && self.can_eq(param_env, expected_found.found, *ty)
+                    && let [arg] = args
+                    && let hir::ExprKind::Closure(closure) = arg.kind
+                {
+                    let body = tcx.hir().body(closure.body);
+                    if let hir::ExprKind::Block(block, None) = body.value.kind
+                        && let None = block.expr
+                        && let [.., stmt] = block.stmts
+                        && let hir::StmtKind::Semi(expr) = stmt.kind
+                        // FIXME: actually check the expected vs found types, but right now
+                        // the expected is a projection that we need to resolve.
+                        // && let Some(tail_ty) = typeck_results.expr_ty_opt(expr)
+                        && expected_found.found.is_unit()
+                    {
+                        err.span_suggestion_verbose(
+                            expr.span.shrink_to_hi().with_hi(stmt.span.hi()),
+                            "consider removing this semicolon",
+                            String::new(),
+                            Applicability::MachineApplicable,
+                        );
+                    }
+                    let expr = if let hir::ExprKind::Block(block, None) = body.value.kind
+                        && let Some(expr) = block.expr
+                    {
+                        expr
+                    } else {
+                        body.value
+                    };
+                    if let hir::ExprKind::MethodCall(path_segment, rcvr, [], span) = expr.kind
+                        && path_segment.ident.name == sym::clone
+                        && let Some(expr_ty) = typeck_results.expr_ty_opt(expr)
+                        && let Some(rcvr_ty) = typeck_results.expr_ty_opt(rcvr)
+                        && self.can_eq(param_env, expr_ty, rcvr_ty)
+                        && let ty::Ref(_, ty, _) = expr_ty.kind()
+                    {
+                        err.span_label(
+                            span,
+                            format!(
+                                "this method call is cloning the reference `{expr_ty}`, not \
+                                 `{ty}` which doesn't implement `Clone`",
+                            ),
+                        );
+                        let ty::Param(..) = ty.kind() else {
+                            continue;
+                        };
+                        let hir = tcx.hir();
+                        let node = hir.get_by_def_id(hir.get_parent_item(expr.hir_id).def_id);
+
+                        let pred = ty::Binder::dummy(ty::TraitPredicate {
+                            trait_ref: ty::TraitRef::from_lang_item(
+                                tcx,
+                                LangItem::Clone,
+                                span,
+                                [*ty],
+                            ),
+                            polarity: ty::ImplPolarity::Positive,
+                        });
+                        let Some(generics) = node.generics() else {
+                            continue;
+                        };
+                        let Some(body_id) = node.body_id() else {
+                            continue;
+                        };
+                        suggest_restriction(
+                            tcx,
+                            hir.body_owner_def_id(body_id),
+                            &generics,
+                            &format!("type parameter `{ty}`"),
+                            err,
+                            node.fn_sig(),
+                            None,
+                            pred,
+                            None,
+                        );
+                    }
+                }
+            }
+        }
+    }
+
     fn point_at_chain(
         &self,
         expr: &hir::Expr<'_>,
@@ -3618,96 +3734,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             expr = rcvr_expr;
             let assocs_in_this_method =
                 self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
-            // Special case for iterator chains, we look at potential failures of `Iterator::Item`
-            // not being `: Clone` and `Iterator::map` calls with spurious trailing `;`.
-            for entry in &assocs_in_this_method {
-                let Some((_span, (def_id, ty))) = entry else {
-                    continue;
-                };
-                for diff in &type_diffs {
-                    let Sorts(expected_found) = diff else {
-                        continue;
-                    };
-                    if tcx.is_diagnostic_item(sym::IteratorItem, *def_id)
-                        && path_segment.ident.name == sym::map
-                        && self.can_eq(param_env, expected_found.found, *ty)
-                        && let [arg] = args
-                        && let hir::ExprKind::Closure(closure) = arg.kind
-                    {
-                        let body = tcx.hir().body(closure.body);
-                        if let hir::ExprKind::Block(block, None) = body.value.kind
-                            && let None = block.expr
-                            && let [.., stmt] = block.stmts
-                            && let hir::StmtKind::Semi(expr) = stmt.kind
-                            // FIXME: actually check the expected vs found types, but right now
-                            // the expected is a projection that we need to resolve.
-                            // && let Some(tail_ty) = typeck_results.expr_ty_opt(expr)
-                            && expected_found.found.is_unit()
-                        {
-                            err.span_suggestion_verbose(
-                                expr.span.shrink_to_hi().with_hi(stmt.span.hi()),
-                                "consider removing this semicolon",
-                                String::new(),
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                        let expr = if let hir::ExprKind::Block(block, None) = body.value.kind
-                            && let Some(expr) = block.expr
-                        {
-                            expr
-                        } else {
-                            body.value
-                        };
-                        if let hir::ExprKind::MethodCall(path_segment, rcvr, [], span) = expr.kind
-                            && path_segment.ident.name == sym::clone
-                            && let Some(expr_ty) = typeck_results.expr_ty_opt(expr)
-                            && let Some(rcvr_ty) = typeck_results.expr_ty_opt(rcvr)
-                            && self.can_eq(param_env, expr_ty, rcvr_ty)
-                            && let ty::Ref(_, ty, _) = expr_ty.kind()
-                        {
-                            err.span_label(
-                                span,
-                                format!(
-                                    "this method call is cloning the reference `{expr_ty}`, not \
-                                     `{ty}` which doesn't implement `Clone`",
-                                ),
-                            );
-                            let ty::Param(..) = ty.kind() else {
-                                continue;
-                            };
-                            let hir = tcx.hir();
-                            let node = hir.get_by_def_id(hir.get_parent_item(expr.hir_id).def_id);
-
-                            let pred = ty::Binder::dummy(ty::TraitPredicate {
-                                trait_ref: ty::TraitRef::from_lang_item(
-                                    tcx,
-                                    LangItem::Clone,
-                                    span,
-                                    [*ty],
-                                ),
-                                polarity: ty::ImplPolarity::Positive,
-                            });
-                            let Some(generics) = node.generics() else {
-                                continue;
-                            };
-                            let Some(body_id) = node.body_id() else {
-                                continue;
-                            };
-                            suggest_restriction(
-                                tcx,
-                                hir.body_owner_def_id(body_id),
-                                &generics,
-                                &format!("type parameter `{ty}`"),
-                                err,
-                                node.fn_sig(),
-                                None,
-                                pred,
-                                None,
-                            );
-                        }
-                    }
-                }
-            }
+            self.look_for_iterator_item_mistakes(
+                &assocs_in_this_method,
+                typeck_results,
+                &type_diffs,
+                param_env,
+                path_segment,
+                args,
+                err,
+            );
             assocs.push(assocs_in_this_method);
             prev_ty = self.resolve_vars_if_possible(
                 typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)),