Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upSet unwrap lints to warn or deny, rather than allow. #1300
Comments
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
BurntSushi
Oct 26, 2016
Member
unwrap (or expect) are perfectly sensible things to do in library code, so long as it's acknowledged that an unwrap failing corresponds to a bug in your code.
Linting against unwrap is isomorphic to linting against xs[5], for example.
|
Linting against |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
mutantmell
Oct 27, 2016
unwrap can both be a perfectly sensible thing to do and lint to warn by default.
unwrap can panic if you use it incorrectly. You should preferentially use other functions if possible. You should know what you are doing if you are using it. That sounds like a warn state to me.
mutantmell
commented
Oct 27, 2016
•
|
|
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
BurntSushi
Oct 27, 2016
Member
@mutantmell Do you also think xs[5] should be linted against?
unwrap/expect is an explicit acknowledgment of a runtime invariant that you either couldn't or wouldn't move into the type system. This isn't something to be warned against IMO.
|
@mutantmell Do you also think
|
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
mutantmell
Oct 27, 2016
While I agree with you on technical grounds that xs[5] and unwrap are isomorphic issues, for people coming from other languages, this may not be intuitively obvious. Many developers are used to working with arrays but are less familiar with working with options. unwrap/expect have very tempting type signatures (I need a T, but I have an Option<T>. unwrap gets me a T), and have runtime implications that are not immediately obvious.
Again, unwrap can panic if you use it incorrectly. A warning from a linter is not a statement that you shouldn't use it, it's a statement that you should ensure that you know what you are doing.
If you want me to take an opinion on xs[5], then yes, I do believe it should be linted against. That is not what this ticket is about though, and a discussion about adding that as a lint option should be a separate discussion.
mutantmell
commented
Oct 27, 2016
|
While I agree with you on technical grounds that Again, If you want me to take an opinion on |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
llogiq
Oct 27, 2016
Collaborator
IIRC I was the one who changed that lints to allow by default because a) their suggestions are not easy to act upon (what would you do instead of panic?) and they tend to drown out other warnings in test code.
So I think those lints are useful, and authors of library code should set them to warn or deny in code where useful error handling is a requirement.
|
IIRC I was the one who changed that lints to So I think those lints are useful, and authors of library code should set them to |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
AndrewBrinker
Oct 27, 2016
Given all the arguments made here, I think warning is the right default. As @mutantmell says, newer Rust developers are likely to default to unwrap() in contexts where it is not a good option, and this is particular problematic for new developers publishing crates. The goal of the lint here is to inform the programmer that unwrap() is a poor default, and encourage them to seek out other options. If unwrap() really is the right option, then they can silence the warnings.
I agree that unwrap() is isomorphic to any other panicking operation, but I don't think that means that linting against unwrap() can only be reasonably done if linting against array indexing is also done. We shouldn't let the perfect be the enemy of the good.
AndrewBrinker
commented
Oct 27, 2016
|
Given all the arguments made here, I think warning is the right default. As @mutantmell says, newer Rust developers are likely to default to I agree that |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
BurntSushi
Oct 27, 2016
Member
So I think those lints are useful, and authors of library code should set them to warn or deny in code where useful error handling is a requirement.
I don't understand. Useful error handling and panicking when a runtime invariant is violated (i.e., a bug) seem like orthogonal issues to me.
I agree that unwrap() is isomorphic to any other panicking operation, but I don't think that means that linting against unwrap() can only be reasonably done if linting against array indexing is also done. We shouldn't let the perfect be the enemy of the good.
I don't really follow this logic. &xs[5] is the same as xs.get(5).unwrap(). Why should only the latter be linted against? They seem like the exact same footgun that you're trying to protect against.
As @mutantmell says, newer Rust developers are likely to default to unwrap() in contexts where it is not a good option, and this is particular problematic for new developers publishing crates.
The flip side to this is that people don't like disabling lints and we'll end up with errors that describe bugs. For example, if I wrote a panic free library, my error type would probably need to look something like this:
enum Error {
Io(io::Error),
SomeLibrarySpecificError(...),
// Occurs only if there's a bug in my code,
// but I was told unwrap was bad.
PoppedFromEmptyStack(...),
}
To me, linting against unwrap is like linting against runtime invariants themselves. It just doesn't seem right to me.
I don't understand. Useful error handling and panicking when a runtime invariant is violated (i.e., a bug) seem like orthogonal issues to me.
I don't really follow this logic.
The flip side to this is that people don't like disabling lints and we'll end up with errors that describe bugs. For example, if I wrote a panic free library, my error type would probably need to look something like this:
To me, linting against |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
AndrewBrinker
Oct 27, 2016
@BurntSushi, I agree with you in the case that unwrap is actually being used only for runtime invariants (that is, being used properly). But as I see it, part of the purpose of lints is to defend against the misuse of features, and the misuse of unwrap is a particularly common issue for new Rust programmers, as a lot of example Rust code uses unwrap for expediency. Setting use of unwrap to warn helps educate newer Rust programmers about when unwrap should be used, and can be easily turned off for people that don't need it.
AndrewBrinker
commented
Oct 27, 2016
|
@BurntSushi, I agree with you in the case that |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
mulkieran
Jun 28, 2017
I have been favouring changing all unwrap()s to expect()s. The different part is that the expect() string explains why this unwrap action is expected never to fail. That seems to me the only good use of the string argument to expect, so that is how I use it. If an unwrap() is still in my source, this is, by definition, a TODO or FIXME.
Here are some illustrative examples of the use of expect: https://github.com/stratis-storage/stratisd/blob/master/src/engine/structures.rs.
So, the lint could encourage the programmer to change an unwrap() to an expect() with an explanation of the invariant OR to return an error.
mulkieran
commented
Jun 28, 2017
|
I have been favouring changing all Here are some illustrative examples of the use of So, the lint could encourage the programmer to change an unwrap() to an expect() with an explanation of the invariant OR to return an error. |
AndrewBrinker
closed this
Aug 1, 2017
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
mulkieran
Aug 2, 2017
@AndrewBrinker Was this closed because something good is happening regarding the issue or because nothing good is ever going to happen?
mulkieran
commented
Aug 2, 2017
|
@AndrewBrinker Was this closed because something good is happening regarding the issue or because nothing good is ever going to happen? |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
AndrewBrinker
Aug 2, 2017
It was closed because on further consideration I am convinced by @BurntSushi's arguments, and no longer think this is a good change.
AndrewBrinker
commented
Aug 2, 2017
|
It was closed because on further consideration I am convinced by @BurntSushi's arguments, and no longer think this is a good change. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
mulkieran
commented
Aug 2, 2017
|
Ok. I'll open a new issue. |
AndrewBrinker commentedOct 26, 2016
Right now the following lints are set to allow:
option_map_unwrap_oroption_map_unwrap_or_elseoption_unwrap_usedresult_unwrap_usedIt seems to me that setting these lints to warn or deny would be a safer default. Having unwraps hidden in library code can cause a variety of problems for downstream users, who are often given no indication that the library they're using may cause a panic. This situation is even more difficult when considering transient dependencies.
While it would be outside the scope of clippy to check the source of all dependencies for potential panics, I think a lot could be done to improve the situation by at least checking the current source for uses of unwrap.
While I would prefer these lints be set to deny, I understand that uses still exist for
unwrap, and that warning may be the right middle ground.Thoughts?