Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unnecessary references lint #138230

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

obeis
Copy link
Contributor

@obeis obeis commented Mar 8, 2025

Close #127724

@rustbot
Copy link
Collaborator

rustbot commented Mar 8, 2025

r? @Noratrieb

rustbot has assigned @Noratrieb.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 8, 2025
@rustbot
Copy link
Collaborator

rustbot commented Mar 8, 2025

These commits modify the Cargo.lock file. Unintentional changes to Cargo.lock can be introduced when switching branches and rebasing PRs.

If this was unintentional then you should revert the changes before this PR is merged.
Otherwise, you can ignore this comment.

@rust-log-analyzer

This comment has been minimized.

Copy link
Member

@compiler-errors compiler-errors left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This lint seems really specific to a single kind of expression, and there are plenty of other cases where unnecessary references are created when the user is trying to create a raw pointer. Unless this can be greatly generalized, it doesn't really seem worth adding this.

@compiler-errors
Copy link
Member

r? RalfJung

@rustbot rustbot assigned RalfJung and unassigned Noratrieb Mar 8, 2025
@obeis
Copy link
Contributor Author

obeis commented Mar 8, 2025

I agree, and my intention is to generalize this lint to cover all unnecessarily created references. Could you please list other cases that you think should be included? I can update this PR to cover them or create an issue to track these cases and mention that they should be added to the unnecessary_refs lint.

@RalfJung
Copy link
Member

RalfJung commented Mar 9, 2025 via email

@rustbot rustbot assigned SparrowLii and unassigned RalfJung Mar 9, 2025
@traviscross traviscross added T-lang Relevant to the language team, which will review and decide on the PR/issue. needs-fcp This change is insta-stable, so needs a completed FCP to proceed. labels Mar 9, 2025
Copy link
Member

@SparrowLii SparrowLii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know little about lints' impls so r? compiler

@rustbot rustbot assigned Nadrieril and unassigned SparrowLii Mar 10, 2025
@RalfJung
Copy link
Member

Do we have some people who are our "linting experts"?

@RalfJung
Copy link
Member

This lint seems really specific to a single kind of expression, and there are plenty of other cases where unnecessary references are created when the user is trying to create a raw pointer. Unless this can be greatly generalized, it doesn't really seem worth adding this.

Which examples did you have in mind?

A starting point might be to uplift https://rust-lang.github.io/rust-clippy/master/index.html#borrow_as_ptr from cliippy to rustc, as you mention. It is not clear to me what the difference is between that lint and this one.

@traviscross
Copy link
Contributor

Do we have some people who are our "linting experts"?

cc @Urgau

@Urgau
Copy link
Member

Urgau commented Mar 10, 2025

Happy to take over the review. If @Nadrieril doesn't want to review it of course.

As for the lint it-self, I join @RalfJung that this is lint is currently clippy::borrow_as_ptr, which will need to be dropped from clippy. Look at 1fee1a4 for the changes needed.

As a drive-by, rustc_hir_pretty should not be necessary, a multi-part suggestion should be used instead, with some span manipulation to get the correct spans.

@Nadrieril
Copy link
Member

Much appreciated :) r? @Urgau

@rustbot rustbot assigned Urgau and unassigned Nadrieril Mar 11, 2025
@Urgau Urgau added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 12, 2025
@obeis obeis force-pushed the lint-unnecessary-reference branch from 1e686f1 to e113827 Compare March 18, 2025 18:26
@obeis obeis requested a review from Urgau March 18, 2025 18:27
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 18, 2025
@obeis obeis force-pushed the lint-unnecessary-reference branch from e113827 to faf0620 Compare March 18, 2025 18:49
@rust-log-analyzer
Copy link
Collaborator

The job x86_64-gnu-tools failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
tests/fail/function_calls/exported_symbol_bad_unwind2.rs (revision `definition`) ... ok
tests/fail/function_calls/exported_symbol_bad_unwind2.rs (revision `both`) ... ok

FAILED TEST: tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs
command: MIRI_ENV_VAR_TEST="0" MIRI_TEMP="/tmp/miri-uitest-pD8Dem" RUST_BACKTRACE="1" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/miri" "--error-format=json" "--sysroot=/checkout/obj/build/x86_64-unknown-linux-gnu/miri-sysroot" "-Dwarnings" "-Dunused" "-Ainternal_features" "-Zui-testing" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/miri_ui/0/tests/fail/dangling_pointers" "tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs" "--edition" "2021"

error: actual output differed from expected
Execute `./miri test --bless` to update `tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.stderr` to the actual output
--- tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.stderr
+++ <stderr output>
-error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x10[noalloc] which is a dangling pointer (it has no provenance)
+error: creating a intermediate reference implies aliasing requirements even when immediately casting to raw pointers
   --> tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs:LL:CC
    |
 LL |     unsafe { &(*x).0 as *const i32 }
-   |              ^^^^^^^ out-of-bounds pointer use: expected a pointer to 4 bytes of memory, but got 0x10[noalloc] which is a dangling pointer (it has no provenance)
+   |              ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = note: `-D unnecessary-refs` implied by `-D warnings`
-   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = help: to override `-D warnings` add `#[allow(unnecessary_refs)]`
-   = note: BACKTRACE:
+help: consider using `&raw const` for a safer and more explicit raw pointer
    |
-LL |     via_ref(ptr); // this is not
+LL -     unsafe { &(*x).0 as *const i32 }
-   |     ^^^^^^^^^^^^
+LL +     unsafe { &raw const (*x).0 }
 
-note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+error: miri cannot be run on programs that fail compilation
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 


error: `dangling pointer` not found in diagnostics on line 11
##[error]  --> tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs:11:48
   |
11 |     unsafe { &(*x).0 as *const i32 } //~ERROR: dangling pointer
   |                                                ^^^^^^^^^^^^^^^^ expected because of this pattern
   |

error: there were 1 unmatched diagnostics that occurred outside the testfile and had no pattern
    Error: miri cannot be run on programs that fail compilation

error: there were 1 unmatched diagnostics
##[error]  --> tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs:11:14
   |
11 |     unsafe { &(*x).0 as *const i32 } //~ERROR: dangling pointer
   |              ^^^^^^^^^^^^^^^^^^^^^ Error[unnecessary_refs]: creating a intermediate reference implies aliasing requirements even when immediately casting to raw pointers
   |

full stderr:
error: creating a intermediate reference implies aliasing requirements even when immediately casting to raw pointers
##[error]  --> tests/fail/dangling_pointers/dangling_pointer_to_raw_pointer.rs:11:14
   |
LL |     unsafe { &(*x).0 as *const i32 }
   |              ^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `-D unnecessary-refs` implied by `-D warnings`
   = help: to override `-D warnings` add `#[allow(unnecessary_refs)]`
help: consider using `&raw const` for a safer and more explicit raw pointer
   |
LL -     unsafe { &(*x).0 as *const i32 }
LL +     unsafe { &raw const (*x).0 }
   |

error: miri cannot be run on programs that fail compilation

error: aborting due to 2 previous errors
---

Location:
   /cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ui_test-0.28.0/src/lib.rs:369

Backtrace omitted. Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.
error: test failed, to rerun pass `--test ui`

Caused by:
  process didn't exit successfully: `/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/x86_64-unknown-linux-gnu/release/deps/ui-9d7bd8a6b4242d84` (exit status: 1)
Command has failed. Rerun with -v to see more details.
Build completed unsuccessfully in 0:04:34
  local time: Tue Mar 18 19:27:36 UTC 2025
  network time: Tue, 18 Mar 2025 19:27:36 GMT
##[error]Process completed with exit code 1.
Post job cleanup.

@@ -894,6 +894,9 @@ lint_unnameable_test_items = cannot test inner items
lint_unnecessary_qualification = unnecessary qualification
.suggestion = remove the unnecessary path segments

lint_unnecessary_refs = creating a intermediate reference implies aliasing requirements even when immediately casting to raw pointers
.suggestion = consider using `&raw const` for a safer and more explicit raw pointer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the suggestion also needs to have the right mutability

Suggested change
.suggestion = consider using `&raw const` for a safer and more explicit raw pointer
.suggestion = consider using `&raw {$mutbl}` for a safer and more explicit raw pointer

Comment on lines +42 to +43
&& let ExprKind::AddrOf(bk, mutbl, addr_of_exp) = exp.kind
&& matches!(bk, BorrowKind::Ref)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason not to match directly?

Suggested change
&& let ExprKind::AddrOf(bk, mutbl, addr_of_exp) = exp.kind
&& matches!(bk, BorrowKind::Ref)
&& let ExprKind::AddrOf(BorrowKind::Ref, mutbl, addr_of_exp) = exp.kind

Comment on lines +45 to +46
&& let ExprKind::Unary(uo, _) = exp.kind
&& matches!(uo, UnOp::Deref)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
&& let ExprKind::Unary(uo, _) = exp.kind
&& matches!(uo, UnOp::Deref)
&& let ExprKind::Unary(UnOp::Deref, _) = exp.kind

@@ -0,0 +1,31 @@
//@ run-rustfix

#![deny(unnecessary_refs)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer that we do not override the lint level

Suggested change
#![deny(unnecessary_refs)]

and use //@ check-pass/WARN

Comment on lines +44 to +46
&& let ExprKind::Field(exp, _) = addr_of_exp.kind
&& let ExprKind::Unary(uo, _) = exp.kind
&& matches!(uo, UnOp::Deref)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the reason for limiting the lint to expressions with a field access? the reasoning also applies to field-less access like &val as *const i32 no?

we should IMO just lint on every operation like this &<expr> as *<const/mut> <type>

Suggested change
&& let ExprKind::Field(exp, _) = addr_of_exp.kind
&& let ExprKind::Unary(uo, _) = exp.kind
&& matches!(uo, UnOp::Deref)

@Urgau Urgau added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-fcp This change is insta-stable, so needs a completed FCP to proceed. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Lint against expressions that unnecessarily create references
10 participants