-
Notifications
You must be signed in to change notification settings - Fork 13.8k
unused_must_use: Don't warn on Result<(), Uninhabited>
or ControlFlow<Uninhabited, ()>
#147382
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
base: master
Are you sure you want to change the base?
unused_must_use: Don't warn on Result<(), Uninhabited>
or ControlFlow<Uninhabited, ()>
#147382
Conversation
This simplifies the initial conditional, and will allow reusing the variable in subsequent checks.
I'll be waiting for the outcome of T-lang's triage meeting before reviewing this since the proposed rules might very well change drastically (e.g., trait-driven vs. not trait-driven; cc Zulip discussion). |
Summarizing the Zulip discussion:
|
My proposal, here, is that we handle this simple case to make common patterns more usable. This does not rule out the possibility of adding more cases in the future, including general trait-based cases. However, I don't think we should make this common case wait on the more general cases. In particular, this solution does not close any doors on replacing this special case with a general case. This would unblock some planned work in the standard library to make |
As a general rule I think this should follow the same rules what |
This suppresses warnings on things like `Result<(), !>`, which helps simplify code using the common pattern of having an `Error` associated type: code will only have to check the error if there is a possibility of error.
d9d6c49
to
23a0751
Compare
I've updated this to follow the same pattern as other inhabitedness checking, of only caring about I've also updated it to handle |
Result<(), Uninhabited>
Result<(), Uninhabited>
or ControlFlow<Uninhabited, ()>
huh... |
This makes it easier to review without cross-referencing each test function with its invocation.
Added, thanks! |
Is this the same as "don't Thus it could be phrased as "change the |
@scottmcm I don't want to generalize that here yet, because someone might e.g. have some |
This makes sense to me, in particular how this helps with @rfcbot fcp merge |
Team member @traviscross has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns. |
&& args.type_at(1).is_unit() | ||
&& !args.type_at(0).is_inhabited_from( | ||
cx.tcx, | ||
parent_mod_did, | ||
cx.typing_env(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels weird to me. ControlFlow
is all about not giving a particular "human intent" to one or the other (just getting the ?
polarity you want), so I would expect ControlFlow<(), !>
and ControlFlow<!, ()>
to either both lint or both not lint.
(Not supporting Result<!, ()>
I understand since we generally tell people not to use ()
there in the first place, but for ControlFlow
both ways are plausible.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@scottmcm I don't have any strong opinions about ControlFlow
here. My own impression was that it'd be confusing to do that, but I'd love to hear feedback from other users of ControlFlow
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely support the intent here, so I do have a non-quite-concern about the current implementation for |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
@rfcbot reviewed Seems sensible. |
@rfcbot reviewed I think this is a positive change for the language. I'd be happy to see a generalization down the line so that other types can make use of it. Maybe in the form of a diagnostic attribute on a type parameter, e.g. #[must_use]
pub enum Result<T, #[diagnostic::may_discard_if_uninhabited] E> {
Ok(T),
Err(E),
} |
I feel like if we're generalizing we might as well go to a trait-based solution so that, for example, Otherwise we're recreating all these systems in diagnostics instead... |
Interesting. That would be a nice direction too. The biggest design question I can think of there is whether removing a MustUse impl (or changing its bounds, as this PR would be doing) is considered semver-breaking. Probably it shouldn't be. |
This comment was marked as outdated.
This comment was marked as outdated.
@tmandry Ideally it'd be impossible to reference the trait outside of Also, it's not clear how to implement the exceptions to All that said, I'd love to see a design proposal for a more general version, and I'm also glad we're shipping this version. :) |
This suppresses warnings on things like
Result<(), !>
, which helps simplify code using the common pattern of having anError
associated type: code will only have to check the error if there is a possibility of error.This will, for instance, help with future refactorings of
write!
in the standard library.As this is a user-visible change to lint behavior, it'll require a lang FCP.
My proposal, here, is that we handle this simple case to make common patterns more usable. This does not rule out the possibility of adding more cases in the future, including general trait-based cases. However, I don't think we should make this common case wait on the more general cases. In particular, this solution does not close any doors on replacing this special case with a general case.
This would unblock some planned work in the standard library to make
write!
more usable for infallible cases (e.g. writing into aVec
orString
).