Skip to contentSkip to conversation

rust: sync: add #[must_use] to Lock::try_lock

PATCH In review Jason Devers 6 participants 24 messages Dec 8, 2024 – Jul 19, 2025 1 message not in the archive

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 rust: sync: add #[must_use] to Lock::try_lock

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused. This could result in the lock being unlocked immediately, which is unsafe and unintended. This patch adds a #[must_use] annotation to Lock::try_lock to prevent this.

---
 rust/kernel/sync/lock.rs | 1 +
 1 file changed, 1 insertion(+)
rust/kernel/sync/lock.rs +1 -0
index 41dcddac69e2..f6a5e83ff685 100644
@@ -147,6 +147,7 @@ pub fn lock(&self) -> Guard<'_, T, B> {
     /// Tries to acquire the lock.
     ///
     /// Returns a guard that can be used to access the data protected by the lock if successful.
+    #[must_use = "if unused, the lock will be immediately unlocked"]
     pub fn try_lock(&self) -> Option<Guard<'_, T, B>> {
         // SAFETY: The constructor of the type calls `init`, so the existence of the object proves
         // that `init` was called.
Signature · 1 line
2.44.2
#1 lore raw

Hi Jason,

Thanks for the patch.

Quoted 3 lines · Jason Devers

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused. This could result in the lock being unlocked immediately, which is unsafe

I don't think not having #[must_use] will result in the locking being unlocked immediately, do you have an example?

Quoted 1 line

and unintended. This patch adds a #[must_use] annotation to

Are you sure this is unsafe? Again do you have an example showing this?

Regards,
Boqun

Quoted 24 lines

Lock::try_lock to prevent this.

---
 rust/kernel/sync/lock.rs | 1 +
 1 file changed, 1 insertion(+)
rust/kernel/sync/lock.rs +1 -0
index 41dcddac69e2..f6a5e83ff685 100644
@@ -147,6 +147,7 @@ pub fn lock(&self) -> Guard<'_, T, B> {
     /// Tries to acquire the lock.
     ///
     /// Returns a guard that can be used to access the data protected by the lock if successful.
+    #[must_use = "if unused, the lock will be immediately unlocked"]
     pub fn try_lock(&self) -> Option<Guard<'_, T, B>> {
         // SAFETY: The constructor of the type calls `init`, so the existence of the object proves
         // that `init` was called.
Signature · 1 line
2.44.2

A message that is not in the archive (sent off-list or not yet received): CAOJvc-bi6ym6ZMAbDSh4H_L6LQXoTs8oNY07SZ1crzXxY9BodQ@mail.gmail.com

author
#3 lore raw

Hi Boqun,

Thank you for the feedback, I am new to kernel development and appreciate the response.

To answer your question(s):

Quoted 2 lines

I don't think not having #[must_use] will result in the locking being unlocked immediately, do you have an example?

You're correct that the absence of #[must_use] itself does not directly result in the lock being unlocked immediately, my mistake.

How I understand the issue arises when the result of Lock::try_lock is called and its return value can be ignored, the lock is never acquired, and no guard is created. Making the caller assume the lock was successfully acquired and proceeding with operations as if the data is safely protected, e.g. calling lock.try_lock() and proceeding with critical section code.

The use of the #[must_use] macro annotation will ensure the caller cannot silently ignore its return value.

I believe the annotation can be revised to:
#[must_use = "if unused, return value may be unhandled, leading to potential race conditions"] ?

But would love to hear your thoughts and suggestions!

Best,
Jason

Quoted 67 lines · jos

Hi Boqun,

Thank you for the feedback, I am new to kernel development and appreciate the response.

To answer your question(s):

Quoted 2 lines

I don't think not having #[must_use] will result in the locking being unlocked immediately, do you have an example?

You're correct that the absence of #[must_use] itself does not directly result in the lock being unlocked immediately, my mistake.

How I understand the issue arises when the result of Lock::try_lock is called and its return value can be ignored, the lock is never acquired, and no guard is created. Making the caller assume the lock was successfully acquired and proceeding with operations as if the data is safely protected, e.g. calling lock.try_lock() and proceeding with critical section code.

The use of the #[must_use] macro annotation will ensure the caller cannot silently ignore its return value. I believe the annotation can be revised to:
#[must_use = "if unused, return value may be unhandled, leading to potential race conditions"] ?

But would love to hear your thoughts?

Best,
Jason

Quoted 44 lines · Boqun Feng

Hi Jason,

Thanks for the patch.

Quoted 3 lines · Jason Devers

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused. This could result in the lock being unlocked immediately, which is unsafe

I don't think not having #[must_use] will result in the locking being unlocked immediately, do you have an example?

Quoted 1 line

and unintended. This patch adds a #[must_use] annotation to

Are you sure this is unsafe? Again do you have an example showing this?

Regards,
Boqun

Quoted 24 lines

Lock::try_lock to prevent this.

---
 rust/kernel/sync/lock.rs | 1 +
 1 file changed, 1 insertion(+)
rust/kernel/sync/lock.rs +1 -1
index 41dcddac69e2..f6a5e83ff685 100644
@@ -147,6 +147,7 @@ pub fn lock(&self) -> Guard<'_, T, B> {
     /// Tries to acquire the lock.
     ///
     /// Returns a guard that can be used to access the data protected by the lock if successful.
+    #[must_use = "if unused, the lock will be immediately unlocked"]
     pub fn try_lock(&self) -> Option<Guard<'_, T, B>> {
         // SAFETY: The constructor of the type calls `init`, so the existence of the object proves
         // that `init` was called.
--

2.44.2

#4 lore raw
In reply to a message not in the archive
Quoted 10 lines · jos

Hi Boqun,

Thank you for the feedback, I am new to kernel development and appreciate the response.

To answer your question(s):

Quoted 2 lines

I don't think not having #[must_use] will result in the locking being unlocked immediately, do you have an example?

Quoted 9 lines

You're correct that the absence of #[must_use] itself does not directly result in the lock being unlocked immediately, my mistake.

How I understand the issue arises when the result of Lock::try_lock is called and its return value can be ignored, the lock is never acquired, and no guard is created. Making the caller assume the lock was successfully acquired and proceeding with operations as if the data is safely protected, e.g. calling lock.try_lock() and proceeding with critical section code.

Well, in most cases, locking is data-oriented, i.e. you have to have the Guard to access locked data, so the "issue" you mention could not happen. Besides, it's relatively easy to "get around" #[must_use] by doing:

	let _ = l.try_lock()?;

Overall, #[must_use] here should be the tool to avoid some code that obviously doesn't make sense (like acquring and releasing lock without any code in between), rather than silver bullets for a serious safety issue. So I think you should reword the commit log to reflect this.

Quoted 6 lines

The use of the #[must_use] macro annotation will ensure the caller cannot silently ignore its return value. I believe the annotation can be revised to:
#[must_use = "if unused, return value may be unhandled, leading to potential race conditions"] ?

I would just say "if unused, leading to an empty critical section", i.e. it's bad but not a correct-or-wrong issue. Does this make sense?

Regards,
Boqun

Quoted 53 lines

But would love to hear your thoughts?

Best,
Jason

Quoted 46 lines · Boqun Feng

Hi Jason,

Thanks for the patch.

Quoted 3 lines · Jason Devers

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused. This could result in the lock being unlocked immediately, which is unsafe

I don't think not having #[must_use] will result in the locking being unlocked immediately, do you have an example?

Quoted 1 line

and unintended. This patch adds a #[must_use] annotation to

Are you sure this is unsafe? Again do you have an example showing this?

Regards,
Boqun

Quoted 14 lines

Lock::try_lock to prevent this.

---
 rust/kernel/sync/lock.rs | 1 +
 1 file changed, 1 insertion(+)
rust/kernel/sync/lock.rs +0 -0
index 41dcddac69e2..f6a5e83ff685 100644

rust/kernel/sync/lock.rs pub fn lock(&self) -> Guard<'_, T, B> { · line 149

Quoted 3 lines
rust/kernel/sync/lock.rs +0 -0
@@ -147,6 +147,7 @@ pub fn lock(&self) -> Guard<'_, T, B> {
     /// Tries to acquire the lock.
     ///
     /// Returns a guard that can be used to access the data protected

by the lock if successful.

rust/kernel/sync/lock.rs pub fn lock(&self) -> Guard<'_, T, B> {

Quoted 3 lines
rust/kernel/sync/lock.rs +1 -0
+    #[must_use = "if unused, the lock will be immediately unlocked"]
     pub fn try_lock(&self) -> Option<Guard<'_, T, B>> {
         // SAFETY: The constructor of the type calls `init`, so the

existence of the object proves

Quoted 4 lines
rust/kernel/sync/lock.rs +0 -1
         // that `init` was called.
--

2.44.2

#5 lore raw

PATCH 1/1 rust: sync: add #[must_use] to Lock::try_lock

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused.
To avoid potential bugs, the #[must_use] annotation is added to ensure proper usage.

---
 rust/kernel/sync/lock.rs | 1 +
 1 file changed, 1 insertion(+)
rust/kernel/sync/lock.rs +1 -0
index 41dcddac69e2..f7d355c5d90a 100644
@@ -147,6 +147,7 @@ pub fn lock(&self) -> Guard<'_, T, B> {
     /// Tries to acquire the lock.
     ///
     /// Returns a guard that can be used to access the data protected by the lock if successful.
+    #[must_use = "if unused, leading to an empty critical section"]
     pub fn try_lock(&self) -> Option<Guard<'_, T, B>> {
         // SAFETY: The constructor of the type calls `init`, so the existence of the object proves
         // that `init` was called.
Signature · 1 line
2.44.2
#6 lore raw
Quoted 4 lines · Jason Devers

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused.
To avoid potential bugs, the #[must_use] annotation is added to ensure proper usage.

It'd be great to mention in this message (and perhaps in the code) that the reason this annotation is necessary is that Option<T> is not #[must_use] regardless of T being #[must_use]. It might also be handy to leave a breadcrumb pointing to
https://github.com/rust-lang/rust/issues/71368.

author
#7 lore raw
Quoted 2 lines

I may be misunderstanding what you are trying to say, but the guard is created, and the lock is acquired.

Apologizes, I had a misunderstanding of the macro that was being used. Thank you Boqun and Miguel for providing clarity, much appreciated!

Quoted 5 lines

It'd be great to mention in this message (and perhaps in the code) that the reason this annotation is necessary is that Option<T> is not #[must_use] regardless of T being #[must_use]. It might also be handy to leave a breadcrumb pointing to
https://github.com/rust-lang/rust/issues/71368.

Sure I can do that, thank you for the suggestion!

Thanks,
Jason

Quoted 12 lines · Tamir Duberstein
Quoted 4 lines · Jason Devers

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused.
To avoid potential bugs, the #[must_use] annotation is added to ensure proper usage.

It'd be great to mention in this message (and perhaps in the code) that the reason this annotation is necessary is that Option<T> is not #[must_use] regardless of T being #[must_use]. It might also be handy to leave a breadcrumb pointing to
https://github.com/rust-lang/rust/issues/71368.

#8 lore raw

PATCH 1/1 rust: sync: add #[must_use] to Lock::try_lock

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused.
To avoid potential bugs, the #[must_use] annotation is added to ensure proper usage.

Note that T is #[must_use] but Option<T> is not.
For more context, see: https://github.com/rust-lang/rust/issues/71368.

---
 rust/kernel/sync/lock.rs | 1 +
 1 file changed, 1 insertion(+)
rust/kernel/sync/lock.rs +1 -0
index 41dcddac69e2..f7d355c5d90a 100644
@@ -147,6 +147,7 @@ pub fn lock(&self) -> Guard<'_, T, B> {
     /// Tries to acquire the lock.
     ///
     /// Returns a guard that can be used to access the data protected by the lock if successful.
+    #[must_use = "if unused, leading to an empty critical section"]
     pub fn try_lock(&self) -> Option<Guard<'_, T, B>> {
         // SAFETY: The constructor of the type calls `init`, so the existence of the object proves
         // that `init` was called.
Signature · 1 line
2.44.2
#9 lore raw
Quoted 11 lines · Jason Devers

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused.
To avoid potential bugs, the #[must_use] annotation is added to ensure proper usage.

Note that T is #[must_use] but Option<T> is not.
For more context, see: https://github.com/rust-lang/rust/issues/71368.

Please use the version option of format-patch, e.g. -v4, when you send new versions, so that they are tagged as such. Otherwise, all the patches look like they are the first version, which is confusing for tooling (and people :)

Also, in general, it is best to wait a day or two to give people a chance to review your patches, so that you do not need to accumulate too many versions.

Quoted 1 line

+ #[must_use = "if unused, leading to an empty critical section"]

I am not a native speaker, but this sounds a bit strange. Is it written like this due to how it gets "rendered" by the compiler later on?

Thanks!

Cheers,
Miguel

author
#10 lore raw
Quoted 1 line

I use [email protected] for kernel contributions.

Sorry about this, I will update with the correct email!

Quoted 8 lines

Please use the version option of format-patch, e.g. -v4, when you send new versions, so that they are tagged as such. Otherwise, all the patches look like they are the first version, which is confusing for tooling (and people :)

Also, in general, it is best to wait a day or two to give people a chance to review your patches, so that you do not need to accumulate too many versions.

Will do! I really appreciate the patience and feedback, please continue doing so :)

Quoted 5 lines

+ #[must_use = "if unused, leading to an empty critical section"]

I am not a native speaker, but this sounds a bit strange. Is it written like this due to how it gets "rendered" by the compiler later on?

I agree this sounds a bit strange, perhaps it would sound more proper to say:

#[must_use = "if unused, leads to an empty critical section"]

Will give it some time to receive more thoughts before sending an updated version.

Thanks,
Jason

Quoted 33 lines · Miguel Ojeda
Quoted 11 lines · Jason Devers

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused.
To avoid potential bugs, the #[must_use] annotation is added to ensure proper usage.

Note that T is #[must_use] but Option<T> is not.
For more context, see: https://github.com/rust-lang/rust/issues/71368.

Please use the version option of format-patch, e.g. -v4, when you send new versions, so that they are tagged as such. Otherwise, all the patches look like they are the first version, which is confusing for tooling (and people :)

Also, in general, it is best to wait a day or two to give people a chance to review your patches, so that you do not need to accumulate too many versions.

Quoted 1 line

+ #[must_use = "if unused, leading to an empty critical section"]

I am not a native speaker, but this sounds a bit strange. Is it written like this due to how it gets "rendered" by the compiler later on?

Thanks!

Cheers,
Miguel

#11 lore raw

PATCH v4 1/1 rust: sync: add #[must_use] to Lock::try_lock

In reply to jos

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused.
To avoid potential bugs, the #[must_use] annotation is added to ensure proper usage.

Note that T is #[must_use] but Option<T> is not.
For more context, see: https://github.com/rust-lang/rust/issues/71368.

---
 rust/kernel/sync/lock.rs | 2 ++
 1 file changed, 2 insertions(+)
rust/kernel/sync/lock.rs +2 -0
index 41dcddac69e2..39f8c07d2287 100644
@@ -147,6 +147,8 @@ pub fn lock(&self) -> Guard<'_, T, B> {
     /// Tries to acquire the lock.
     ///
     /// Returns a guard that can be used to access the data protected by the lock if successful.
+    /// Note that `T` is `#[must_use]` but `Option<T>` is not.
+    #[must_use = "if unused, leads to an empty critical section"]
     pub fn try_lock(&self) -> Option<Guard<'_, T, B>> {
         // SAFETY: The constructor of the type calls `init`, so the existence of the object proves
         // that `init` was called.
Signature · 1 line
2.44.2
maintainer
#12 lore raw
Quoted 20 lines · Jason Devers

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused.
To avoid potential bugs, the #[must_use] annotation is added to ensure proper usage.

Note that T is #[must_use] but Option<T> is not.
For more context, see: https://github.com/rust-lang/rust/issues/71368.

---
 rust/kernel/sync/lock.rs | 2 ++
 1 file changed, 2 insertions(+)
rust/kernel/sync/lock.rs +0 -0
index 41dcddac69e2..39f8c07d2287 100644

rust/kernel/sync/lock.rs pub fn lock(&self) -> Guard<'_, T, B> { · line 151

Quoted 5 lines
rust/kernel/sync/lock.rs +2 -0
@@ -147,6 +147,8 @@ pub fn lock(&self) -> Guard<'_, T, B> {
     /// Tries to acquire the lock.
     ///
     /// Returns a guard that can be used to access the data protected by the lock if successful.
+    /// Note that `T` is `#[must_use]` but `Option<T>` is not.
+    #[must_use = "if unused, leads to an empty critical section"]

Can't we use the same warning message as Guard?

#[must_use = "the lock unlocks immediately when the guard is unused"]

Alice

#13 lore raw
In reply to Jason Devers
Quoted 2 lines · Jason Devers

+ /// Note that T is #[must_use] but Option<T> is not.

Should this be a comment, i.e. //, rather than part of the documentation?

I would also reword to explain the "what", not just "why", e.g. something like:

    // `Option<T>` is not `#[must_use]` even if `T` is, thus the

attribute is needed here.

Cheers,
Miguel

author
#14 lore raw
Quoted 3 lines

Can't we use the same warning message as Guard?

#[must_use = "the lock unlocks immediately when the guard is unused"]

That is what I originally had in my first patch and how I understood the annotation should be phrased, but @Boqun Feng maybe you can chime in with your input?

Quoted 3 lines
Quoted 1 line

+ /// Note that T is #[must_use] but Option<T> is not.

Should this be a comment, i.e. //, rather than part of the documentation?

Agreed, after reading more documentation conventions
(https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md),
this should not be part of the rustdocs.

Quoted 4 lines

I would also reword to explain the "what", not just "why", e.g. something like:

   // `Option<T>` is not `#[must_use]` even if `T` is, thus the

attribute is needed here.

Thank you for the insight, I can see how there is missing clarity in the current comment, will update in the next patch.

Thanks,
Jason

Quoted 14 lines · Miguel Ojeda
Quoted 2 lines · Jason Devers

+ /// Note that T is #[must_use] but Option<T> is not.

Should this be a comment, i.e. //, rather than part of the documentation?

I would also reword to explain the "what", not just "why", e.g. something like:

    // `Option<T>` is not `#[must_use]` even if `T` is, thus the

attribute is needed here.

Cheers,
Miguel

#15 lore raw
Quoted 8 lines · jos
Quoted 3 lines

Can't we use the same warning message as Guard?

#[must_use = "the lock unlocks immediately when the guard is unused"]

That is what I originally had in my first patch and how I understood the annotation should be phrased, but @Boqun Feng maybe you can chime in with your input?

Hmm... I think it was a mis-communication. In the v1, you said "..but it currently does not issue a warning if the return value is unused. This could result in the lock being unlocked immediately.." I thought "This" means "not having #[must_use]", but you probably meant "not using the value"? My comment is more to that commit log instead of the warning message in the #[must_use = ...] block.

Anyway, I think the warning message in your v1 works for me. Again, to be clear, my concern was on the commit log then. Hope it clarifies things.

Regards,
Boqun

Quoted 36 lines
Quoted 3 lines
Quoted 1 line

+ /// Note that T is #[must_use] but Option<T> is not.

Should this be a comment, i.e. //, rather than part of the documentation?

Agreed, after reading more documentation conventions
(https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md),
this should not be part of the rustdocs.

Quoted 4 lines

I would also reword to explain the "what", not just "why", e.g. something like:

   // `Option<T>` is not `#[must_use]` even if `T` is, thus the

attribute is needed here.

Thank you for the insight, I can see how there is missing clarity in the current comment, will update in the next patch.

Thanks,
Jason

Quoted 14 lines · Miguel Ojeda
Quoted 2 lines · Jason Devers

+ /// Note that T is #[must_use] but Option<T> is not.

Should this be a comment, i.e. //, rather than part of the documentation?

I would also reword to explain the "what", not just "why", e.g. something like:

    // `Option<T>` is not `#[must_use]` even if `T` is, thus the

attribute is needed here.

Cheers,
Miguel

#16 lore raw

PATCH v5 1/1 rust: sync: add #[must_use] to Lock::try_lock

In reply to jos

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused.
To avoid potential bugs, the #[must_use] annotation is added to ensure proper usage.

Note that T is #[must_use] but Option<T> is not.
For more context, see: https://github.com/rust-lang/rust/issues/71368.

---
 rust/kernel/sync/lock.rs | 2 ++
 1 file changed, 2 insertions(+)
rust/kernel/sync/lock.rs +2 -0
index 41dcddac69e2..dd187812aeb4 100644
@@ -147,6 +147,8 @@ pub fn lock(&self) -> Guard<'_, T, B> {
     /// Tries to acquire the lock.
     ///
     /// Returns a guard that can be used to access the data protected by the lock if successful.
+    // Note that `T` is `#[must_use]` but `Option<T>` is not.
+    #[must_use = "if unused, the lock will be immediately unlocked"]
     pub fn try_lock(&self) -> Option<Guard<'_, T, B>> {
         // SAFETY: The constructor of the type calls `init`, so the existence of the object proves
         // that `init` was called.
Signature · 1 line
2.44.2
#17 lore raw
Quoted 2 lines · Jason Devers

+ // Note that T is #[must_use] but Option<T> is not.

I think the wording of the comment was not updated? If there is a reason for not doing it, then you should normally put it in the changelog (i.e. after the first --- line) or you would reply to the original feedback with the reason.

Thanks!

Cheers,
Miguel

#18 lore raw

PATCH v6 1/1 rust: sync: add #[must_use] to Lock::try_lock

In reply to jos

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused.
To avoid potential bugs, the #[must_use] annotation is added to ensure proper usage.

Note that T is #[must_use] but Option<T> is not.
For more context, see: https://github.com/rust-lang/rust/issues/71368.

---
 rust/kernel/sync/lock.rs | 2 ++
 1 file changed, 2 insertions(+)
rust/kernel/sync/lock.rs +2 -0
index 41dcddac69e2..aacc227536cb 100644
@@ -147,6 +147,8 @@ pub fn lock(&self) -> Guard<'_, T, B> {
     /// Tries to acquire the lock.
     ///
     /// Returns a guard that can be used to access the data protected by the lock if successful.
+    // `Option<T>` is not `#[must_use]` even if `T` is, thus the attribute is needed here.
+    #[must_use = "if unused, the lock will be immediately unlocked"]
     pub fn try_lock(&self) -> Option<Guard<'_, T, B>> {
         // SAFETY: The constructor of the type calls `init`, so the existence of the object proves
         // that `init` was called.
Signature · 1 line
2.44.2
#19 lore raw

Hi Jason,

Quoted 9 lines · Jason Devers

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused.
To avoid potential bugs, the #[must_use] annotation is added to ensure proper usage.

Note that T is #[must_use] but Option<T> is not.
For more context, see: https://github.com/rust-lang/rust/issues/71368.

I think you could add Alice's Reviewed-by from the previous version:

https://lore.kernel.org/rust-for-linux/CAH5fLghjR4fctjoLT9Zom3drNMQ6vdE9hUTnZZ4Ms1qQHGFe=A@mail.gmail.com/

or you have any reason that you need another "Reviewed-by" tag?

(No need to send a new version, I'm just making sure you and Alice both agree the "Reviewed-by" tag still applies to this patch.)

Regards,
Boqun

Quoted 21 lines
---
 rust/kernel/sync/lock.rs | 2 ++
 1 file changed, 2 insertions(+)
rust/kernel/sync/lock.rs +2 -0
index 41dcddac69e2..aacc227536cb 100644
@@ -147,6 +147,8 @@ pub fn lock(&self) -> Guard<'_, T, B> {
     /// Tries to acquire the lock.
     ///
     /// Returns a guard that can be used to access the data protected by the lock if successful.
+    // `Option<T>` is not `#[must_use]` even if `T` is, thus the attribute is needed here.
+    #[must_use = "if unused, the lock will be immediately unlocked"]
     pub fn try_lock(&self) -> Option<Guard<'_, T, B>> {
         // SAFETY: The constructor of the type calls `init`, so the existence of the object proves
         // that `init` was called.
Signature · 1 line
2.44.2
maintainer Reviewed-by on v6 1/1
#20 lore raw
In reply to Jason Devers
Quoted 11 lines · Jason Devers

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused.
To avoid potential bugs, the #[must_use] annotation is added to ensure proper usage.

Note that T is #[must_use] but Option<T> is not.
For more context, see: https://github.com/rust-lang/rust/issues/71368.

#21 lore raw
Quoted 6 lines · Alice Ryhl
Quoted 5 lines · Jason Devers

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused.
To avoid potential bugs, the #[must_use] annotation is added to ensure proper usage.

Quoted 8 lines
Quoted 6 lines

Note that T is #[must_use] but Option<T> is not.
For more context, see: https://github.com/rust-lang/rust/issues/71368.

Queued. I reworded a bit on the commit log because of the tip maintainer guideline. Thank you both!

Regards,
Boqun

merge bot Applied
#22 lore raw

[tip: locking/core] rust: sync: Add #[must_use] to Lock::try_lock()

In reply to Jason Devers
The following commit has been merged into the locking/core branch of tip:

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     99214efedea521f1b79fa2a28ff142e933fc3eba
Gitweb:        https://git.kernel.org/tip/99214efedea521f1b79fa2a28ff142e933fc3eba
Author:        Jason Devers <[email protected]>
AuthorDate:    Thu, 12 Dec 2024 10:47:53 -05:00
Committer:     Boqun Feng <[email protected]>
CommitterDate: Fri, 11 Jul 2025 15:11:54 -07:00

rust: sync: Add #[must_use] to Lock::try_lock()

The Lock::try_lock() function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused. To avoid potential bugs, the #[must_use] annotation is added to ensure proper usage.

Note that T is #[must_use] but Option<T> is not.
For more context, see: https://github.com/rust-lang/rust/issues/71368.

---
 rust/kernel/sync/lock.rs | 2 ++
 1 file changed, 2 insertions(+)
rust/kernel/sync/lock.rs +2 -0
index e82fa5b..27202be 100644
@@ -175,6 +175,8 @@ impl<T: ?Sized, B: Backend> Lock<T, B> {
     /// Tries to acquire the lock.
     ///
     /// Returns a guard that can be used to access the data protected by the lock if successful.
+    // `Option<T>` is not `#[must_use]` even if `T` is, thus the attribute is needed here.
+    #[must_use = "if unused, the lock will be immediately unlocked"]
     pub fn try_lock(&self) -> Option<Guard<'_, T, B>> {
         // SAFETY: The constructor of the type calls `init`, so the existence of the object proves
         // that `init` was called.
#23 lore raw
In reply to a message not in the archive
Quoted 2 lines · jos

How I understand the issue arises when the result of Lock::try_lock is called and its return value can be ignored, the lock is never acquired, and no guard is created.

I may be misunderstanding what you are trying to say, but the guard is created, and the lock is acquired.

So the issue is that someone does not keep the guard around, so the guard is dropped right away and so the critical section is empty.

Cheers,
Miguel

maintainer Reviewed-by on v1 1/1
#24 lore raw
In reply to Jason Devers
Quoted 6 lines · Jason Devers

The Lock::try_lock function returns an Option<Guard<...>>, but it currently does not issue a warning if the return value is unused. This could result in the lock being unlocked immediately, which is unsafe and unintended. This patch adds a #[must_use] annotation to Lock::try_lock to prevent this.

I agree that "unsafe" is the wrong word here. We can just say "which is probably not what the user intended".

Quoted 1 line

I use [email protected] for kernel contributions.

Quoted 2 lines

Overall looks good to me! You may add: