about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2023-11-15 01:29:00 +0000
committerEsteban Küber <esteban@kuber.com.ar>2023-11-18 00:05:19 +0000
commit7141399454e75622fcc7b034b7e045a1b31f22d0 (patch)
tree12430c4e09c965d6b4c7386544629127ac0fe323
parent2831701757eb7b3105eda26a306c2f3a97e2664b (diff)
downloadrust-7141399454e75622fcc7b034b7e045a1b31f22d0.tar.gz
rust-7141399454e75622fcc7b034b7e045a1b31f22d0.zip
When a local binding shadows a fn, point at fn def in call failure
When a local binding shadows a function that is then called, this local
binding will cause an E0618 error. We now point not only at the binding
definition, but also at the locally defined function of the same name.

```
error[E0618]: expected function, found `&str`
  --> $DIR/issue-22468.rs:3:13
   |
LL |     let foo = "bar";
   |         --- `foo` has type `&str`
LL |     let x = foo("baz");
   |             ^^^-------
   |             |
   |             call expression requires function
...
LL | fn foo(file: &str) -> bool {
   | -------------------------- this function of the same name is avalable here, but it shadowed by the local binding of the same name
```

Fix #53841
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs19
-rw-r--r--tests/ui/issues/issue-22468.stderr3
2 files changed, 22 insertions, 0 deletions
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 6b6d1574b2b..173186e6d9f 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -625,6 +625,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             );
         }
 
+        if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = callee_expr.kind
+            && let Res::Local(_) = path.res
+            && let [segment] = &path.segments[..]
+        {
+            for id in self.tcx.hir().items() {
+                if let Some(node) = self.tcx.hir().get_if_local(id.owner_id.into())
+                    && let hir::Node::Item(item) = node
+                    && let hir::ItemKind::Fn(..) = item.kind
+                    && item.ident.name == segment.ident.name
+                {
+                    err.span_label(
+                        self.tcx.def_span(id.owner_id),
+                        "this function of the same name is available here, but it's shadowed by \
+                         the local binding",
+                    );
+                }
+            }
+        }
+
         let mut inner_callee_path = None;
         let def = match callee_expr.kind {
             hir::ExprKind::Path(ref qpath) => {
diff --git a/tests/ui/issues/issue-22468.stderr b/tests/ui/issues/issue-22468.stderr
index 3fff91acbc2..fb2b9b42859 100644
--- a/tests/ui/issues/issue-22468.stderr
+++ b/tests/ui/issues/issue-22468.stderr
@@ -7,6 +7,9 @@ LL |     let x = foo("baz");
    |             ^^^-------
    |             |
    |             call expression requires function
+...
+LL | fn foo(file: &str) -> bool {
+   | -------------------------- this function of the same name is available here, but it's shadowed by the local binding
 
 error: aborting due to previous error