Description
This lint does not include the place at which you can apply an attribute to ignore the lint, which can leave users very confused.
Take the following code
match e.downcast::<RustlsError>() {
Ok(rustls_err) => match rustls_err {
RustlsError::InvalidMessage(e) => match e {
// non https request is received
InvalidMessage::InvalidContentType => (),
_ => eprintln!(
"Error during tls handshake from {addr}: {rustls_err:?}",
),
},
RustlsError::AlertReceived(e) => match e {
// self-signed certs
AlertDescription::CertificateUnknown => (),
_ => eprintln!(
"Error during tls handshake from {addr}: {rustls_err:?}",
),
},
_ => eprintln!(
"Error during tls handshake from {addr}: {rustls_err:?}",
),
},
Err(e) => match e.kind() {
// https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#unexpected-eof
ErrorKind::UnexpectedEof => (),
_ => {
eprintln!("Error during tls handshake from {addr}: {e:?}");
}
},
};
$ cargo clippy
warning: this `match` can be collapsed into the outer `match`
--> server/src/main.rs:137:51
|
137 | RustlsError::InvalidMessage(e) => match e {
| ___________________________________________________^
138 | | // non https request is received
139 | | InvalidMessage::InvalidContentType => (),
... |
143 | | ),
144 | | },
| |_________________^
|
help: the outer pattern can be modified to include the inner pattern
--> server/src/main.rs:137:45
|
137 | RustlsError::InvalidMessage(e) => match e {
| ^ replace this binding
138 | // non https request is received
139 | InvalidMessage::InvalidContentType => (),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ with this pattern
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match
= note: `#[warn(clippy::collapsible_match)]` on by default
warning: this `match` can be collapsed into the outer `match`
--> server/src/main.rs:146:50
|
146 | RustlsError::AlertReceived(e) => match e {
| __________________________________________________^
147 | | // self-signed certs
148 | | AlertDescription::CertificateUnknown => (),
... |
152 | | ),
153 | | },
| |_________________^
|
help: the outer pattern can be modified to include the inner pattern
--> server/src/main.rs:146:44
|
146 | RustlsError::AlertReceived(e) => match e {
| ^ replace this binding
147 | // self-signed certs
148 | AlertDescription::CertificateUnknown => (),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ with this pattern
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match
Ok, whatever. I like my code the way it is, I will ignore the warnings.
match e.downcast::<RustlsError>() {
Ok(rustls_err) => match rustls_err {
RustlsError::InvalidMessage(e) => {
+ #[expect(clippy::collapsible_match)]
match e {
// non https request is received
InvalidMessage::InvalidContentType => (),
...
}
RustlsError::AlertReceived(e) => {
+ #[expect(clippy::collapsible_match)]
match e {
// self-signed certs
AlertDescription::CertificateUnknown => (),
...
(& formatting changes)
$ cargo clippy
warning: this `match` can be collapsed into the outer `match`
--> server/src/main.rs:139:19
|
139 | / match e {
140 | | // non https request is received
141 | | InvalidMessage::InvalidContentType => (),
... |
145 | | ),
146 | | }
| |___________________^
|
help: the outer pattern can be modified to include the inner pattern
--> server/src/main.rs:137:45
|
137 | RustlsError::InvalidMessage(e) => {
| ^ replace this binding
...
141 | InvalidMessage::InvalidContentType => (),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ with this pattern
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match
= note: `#[warn(clippy::collapsible_match)]` on by default
warning: this `match` can be collapsed into the outer `match`
--> server/src/main.rs:151:19
|
151 | / match e {
152 | | // self-signed certs
153 | | AlertDescription::CertificateUnknown => (),
... |
157 | | ),
158 | | }
| |___________________^
|
help: the outer pattern can be modified to include the inner pattern
--> server/src/main.rs:149:44
|
149 | RustlsError::AlertReceived(e) => {
| ^ replace this binding
...
153 | AlertDescription::CertificateUnknown => (),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ with this pattern
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match
warning: this lint expectation is unfulfilled
--> server/src/main.rs:138:28
|
138 | #[expect(clippy::collapsible_match)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unfulfilled_lint_expectations)]` on by default
warning: this lint expectation is unfulfilled
--> server/src/main.rs:150:28
|
150 | #[expect(clippy::collapsible_match)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
Very confused, I tried to undo my changes and reapply but the warnings still persisted. I then tried to apply the attributes to the e
bindings but got syntax errors.
Now even more confused, I glanced back at the code and saw that the 2 branches looked very similar. Out of curiosity I added a character to one of the strings, and the warning for that block disappeared. Maybe clippy detected that I was doing the same thing as the parent match
in both cases and thus issued the warnings? To test it, I added the same character at the same position in the string in the parent block (match rustls_err
) and suddenly the warning switched from the block without the character to the one that did. I undid all changes and applied the attribute to the parent block, and the warnings disappeared.