about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-05-31 18:51:47 +0200
committerGitHub <noreply@github.com>2025-05-31 18:51:47 +0200
commit05debb0d0d2ec468e75ffb1bf6b53c702cb819b2 (patch)
tree8d8d0e4cd3e677662fce7dd036a5f4ba8cffb235
parent738c08b63c4f9e3ebdaec5eece7b6fbc354f6467 (diff)
parent17352e6937fde53c4f75dfd8600ecff4f1077ca2 (diff)
downloadrust-05debb0d0d2ec468e75ffb1bf6b53c702cb819b2.tar.gz
rust-05debb0d0d2ec468e75ffb1bf6b53c702cb819b2.zip
Rollup merge of #140787 - xizheyin:issue-140491, r=nnethercote
Note expr being cast when encounter NonScalar cast error

Fixes #140491

I added note for `expr` so that it doesn't treat `&x as T` as `&(x as T)` but `(&x) as T`. But I'm not sure if I want to add note for all NonScalar, maybe for specific `expr_ty`?

r? compiler
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs10
-rw-r--r--tests/ui/cast/func-pointer-issue-140491.rs7
-rw-r--r--tests/ui/cast/func-pointer-issue-140491.stderr11
-rw-r--r--tests/ui/coercion/issue-73886.stderr2
4 files changed, 30 insertions, 0 deletions
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index c044c4f7c37..e144a6ab599 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -408,6 +408,16 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     self.expr_ty,
                     fcx.ty_to_string(self.cast_ty)
                 );
+
+                if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span)
+                    && matches!(self.expr.kind, ExprKind::AddrOf(..))
+                {
+                    err.note(format!(
+                        "casting reference expression `{}` because `&` binds tighter than `as`",
+                        snippet
+                    ));
+                }
+
                 let mut sugg = None;
                 let mut sugg_mutref = false;
                 if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() {
diff --git a/tests/ui/cast/func-pointer-issue-140491.rs b/tests/ui/cast/func-pointer-issue-140491.rs
new file mode 100644
index 00000000000..d5d86a66f5a
--- /dev/null
+++ b/tests/ui/cast/func-pointer-issue-140491.rs
@@ -0,0 +1,7 @@
+fn my_fn(event: &Event<'_>) {}
+
+struct Event<'a>(&'a ());
+
+fn main() {
+    const ptr: &fn(&Event<'_>) = &my_fn as _; //~ ERROR non-primitive cast: `&for<'a, 'b> fn(&'a Event<'b>) {my_fn}` as `&for<'a, 'b> fn(&'a Event<'b>)` [E0605]
+}
diff --git a/tests/ui/cast/func-pointer-issue-140491.stderr b/tests/ui/cast/func-pointer-issue-140491.stderr
new file mode 100644
index 00000000000..e1c07010e69
--- /dev/null
+++ b/tests/ui/cast/func-pointer-issue-140491.stderr
@@ -0,0 +1,11 @@
+error[E0605]: non-primitive cast: `&for<'a, 'b> fn(&'a Event<'b>) {my_fn}` as `&for<'a, 'b> fn(&'a Event<'b>)`
+  --> $DIR/func-pointer-issue-140491.rs:6:34
+   |
+LL | ..._>) = &my_fn as _;
+   |          ^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+   |
+   = note: casting reference expression `&my_fn` because `&` binds tighter than `as`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0605`.
diff --git a/tests/ui/coercion/issue-73886.stderr b/tests/ui/coercion/issue-73886.stderr
index 0d4c90017cf..a287aa29e11 100644
--- a/tests/ui/coercion/issue-73886.stderr
+++ b/tests/ui/coercion/issue-73886.stderr
@@ -3,6 +3,8 @@ error[E0605]: non-primitive cast: `&&[i32; 1]` as `&[_]`
    |
 LL |     let _ = &&[0] as &[_];
    |             ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
+   |
+   = note: casting reference expression `&&[0]` because `&` binds tighter than `as`
 
 error[E0605]: non-primitive cast: `u32` as `Option<_>`
   --> $DIR/issue-73886.rs:4:13