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

Assert that the first assert! expression is bool #122661

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

Conversation

estebank
Copy link
Contributor

@estebank estebank commented Mar 17, 2024

In the desugaring of assert! in 2024 edition, assign the condition expression to a bool biding in order to provide better type errors when passed the wrong thing.

The span will point only at the expression, and not the whole assert! invocation.

error[E0308]: mismatched types
  --> $DIR/issue-14091.rs:2:13
   |
LL |     assert!(1,1);
   |             ^ expected `bool`, found integer

We no longer mention the expression needing to implement the Not trait.

error[E0308]: mismatched types
  --> $DIR/issue-14091-2.rs:15:13
   |
LL |     assert!(x, x);
   |             ^ expected `bool`, found `BytePos`

In <=2021 edition, we still accept any type that implements Not<Output = bool>.

Fix #122159.

@rustbot
Copy link
Collaborator

rustbot commented Mar 17, 2024

r? @pnkfelix

rustbot has assigned @pnkfelix.
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. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Mar 17, 2024
@rustbot
Copy link
Collaborator

rustbot commented Mar 17, 2024

rust-analyzer is developed in its own repository. If possible, consider making this change to rust-lang/rust-analyzer instead.

cc @rust-lang/rust-analyzer

The Miri subtree was changed

cc @rust-lang/miri

assert!((() <= ()));
assert!((!(() > ())));
assert!((() >= ()));
assert!(!(() != ()));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

All of these are because now the unnecessary parentheses lint (correctly) triggers on assert!((expr)).

Comment on lines -1 to -14
error[E0600]: cannot apply unary operator `!` to type `BytePos`
--> $DIR/issue-14091-2.rs:15:5
error[E0308]: mismatched types
--> $DIR/issue-14091-2.rs:15:13
|
LL | assert!(x, x);
| ^^^^^^^^^^^^^ cannot apply unary operator `!`
|
note: an implementation of `Not` might be missing for `BytePos`
--> $DIR/issue-14091-2.rs:6:1
|
LL | pub struct BytePos(pub u32);
| ^^^^^^^^^^^^^^^^^^ must implement `Not`
note: the trait `Not` must be implemented
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the best example of how this is an improvement.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@estebank
Copy link
Contributor Author

Sigh, clippy shows at least one test where a suggestion causes there to be a condition that isn't a bool but rather a type where Not returns a bool. We can easily continue supporting that by making the desugaring !!cond, but would rather not do that. This happens when it suggest changing assert_eq!(non_bool, true), ending up as assert!(non_bool), which doesn't work with this change .

@rustbot
Copy link
Collaborator

rustbot commented Mar 17, 2024

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

@rust-log-analyzer

This comment has been minimized.

@pnkfelix
Copy link
Member

Isn't this technically a breaking change for e.g. (playground):

struct Booly(i32);

impl std::ops::Not for Booly {
    type Output = bool;
    fn not(self) -> Self::Output {
        self.0 == 0
    }
}

fn main() {
    assert!(Booly(1), "booly booly!")
}

@pnkfelix
Copy link
Member

At the very least, we might need to tie such a change to an edition.

I am not certain whether this decision would be a T-lang matter or a T-libs-api one. I'll nominate for T-lang for now.

(Namely: The question is whether we can start enforcing a rule that the first expression to assert! must be of bool type, which is how the macro is documented, but its current behavior is a little bit more general, as demonstrated in my prior comment)

@rustbot label +I-lang-nominated

@rustbot rustbot added the I-lang-nominated The issue / PR has been nominated for discussion during a lang team meeting. label Mar 18, 2024
@estebank
Copy link
Contributor Author

estebank commented Mar 18, 2024

@pnkfelix we can keep the current (undocumented) behavior by making the desugaring be

{
    let x: bool = !!condition;
    x
}

instead of what this PR does:

{
    let x: bool = condition;
    x
}

I believe that would still cause errors to complain about Not not being implemented, instead of the more straightforward type error, albeit with a better span. I don't particularly like the idea of keeping the current emergent behavior if there aren't people exploiting it in crates.io.

Edit: an option would be to have an internal marker trait:

use std::ops::Not;
trait CanAssert {}
impl<T: Not<Output = bool>> CanAssert for T {}

fn main() {
    let _ = Box::new(true) as Box<dyn CanAssert>;
    let _ = Box::new(42) as Box<dyn CanAssert>;
}
error[E0271]: type mismatch resolving `<i32 as Not>::Output == bool`
 --> src/main.rs:7:13
  |
7 |     let _ = Box::new(42) as Box<dyn CanAssert>;
  |             ^^^^^^^^^^^^ expected `bool`, found `i32`
  |
note: required for `i32` to implement `CanAssert`
 --> src/main.rs:3:29
  |
3 | impl<T: Not<Output = bool>> CanAssert for T {}
  |             -------------   ^^^^^^^^^     ^
  |             |
  |             unsatisfied trait bound introduced here
  = note: required for the cast from `Box<i32>` to `Box<dyn CanAssert>`

@pnkfelix
Copy link
Member

pnkfelix commented Mar 18, 2024

@estebank what about making the expansion edition-dependent? Is there precedent for that?

Then, editions >= 2024 would expand to what you have proposed in the code of this PR, and editions < 2024 could expand to the !!condition variant form that you have discussed in the comments?

@pnkfelix
Copy link
Member

what about making the expansion edition-dependent? Is there precedent for that?

(to answer my own question, panic! is one obvious precedent here. So it seems like making it edition-dependent would be one acceptable path; no opinion yet as to which is best...)

@rustbot
Copy link
Collaborator

rustbot commented Mar 19, 2024

Some changes occurred in coverage tests.

cc @Zalathar

@estebank
Copy link
Contributor Author

I tried the marker trait approach for <=2021, and it kind of worked, but the diagnostics were actually worse than just doing { let x: bool = !!$expr; x }, which accounts for pretty much everything we currently support, but with better spans and better errors (if typeof($expr) implements <Not<Output = NotBool>, we now produce an appropriate E0308 type error).

@rust-log-analyzer

This comment has been minimized.

@compiler-errors
Copy link
Member

Since I don't think it's been acknowledged above, for the record, this breaks the following code:

fn hello(x: &bool) {
  assert!(x);
}

Because &bool: Not<Output = bool>.

@estebank
Copy link
Contributor Author

@compiler-errors that is indeed the case for 2024 onwards, not for previous editions.

@pnkfelix
Copy link
Member

pnkfelix commented Mar 20, 2024

@compiler-errors that is indeed the case for 2024 onwards, not for previous editions.

I think the critical point is whether an edition-dependent expansion is worth breaking that case (of assert!(x) where x: &bool), or if we should do a non-breaking non-edition-dependent expansion using the let x: bool = !!$expr trick across the board...


Update: I don't know whether it is worth going through this exercise explicitly, but there is a design space here. E.g. one set of options is:

  1. (stable Rust behavior): in all editions, support arbitrary impl Not<Output=bool> for first parameter to assert!;
  2. in edition >= 2024, support just Deref<Target=bool> for first parameter to assert! (e.g. by expanding to let x: &bool = &$expr;), or
  3. (this PR): in edition >= 2024, support just bool for first parameter to assert!.

(And then there's variations thereof about how to handle editions < 2024, but that's a separate debate IMO.)

@pnkfelix
Copy link
Member

pnkfelix commented Mar 22, 2024

(this is waiting for a decision from T-lang and/or T-libs regarding what interface we want to commit to for assert!)

@rustbot label: +S-waiting-on-team -S-waiting-on-review

@rustbot rustbot added S-waiting-on-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 22, 2024
@bors
Copy link
Contributor

bors commented Mar 23, 2024

☔ The latest upstream changes (presumably #122947) made this pull request unmergeable. Please resolve the merge conflicts.

@scottmcm scottmcm added the I-libs-api-nominated The issue / PR has been nominated for discussion during a libs-api team meeting. label Mar 27, 2024
@scottmcm
Copy link
Member

Nominated for libs-api, because for things that are hypothetically macros written in core I'd mostly lean on them.

Personally this makes sense to me.

DUMMY_SP,
false,
ident,
Some(cx.ty_ident(span, Ident::new(sym::bool, DUMMY_SP))),
Copy link
Member

Choose a reason for hiding this comment

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

The hygiene is not sufficient here. This example now breaks:

fn main() {
    type bool = i32;
    assert!(true);
}
error[E0308]: mismatched types
 --> src/main.rs:3:13
  |
3 |     assert!(true);
  |             ^^^^ expected `i32`, found `bool`
  |

Copy link
Member

Choose a reason for hiding this comment

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

It's probably better and easier to just use if <expr> {} else { panic!(..) }, without making any block expressions or local bindings, and without making any changes to the expansion in previous editions.

Comment on lines 185 to 187
// `{ let assert_macro: bool = !!$expr; assert_macro }`
let not = |expr| parser.mk_expr(span, ast::ExprKind::Unary(ast::UnOp::Not, expr));
not(not(cond_expr))
Copy link
Member

Choose a reason for hiding this comment

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

The !! solution adds more issues: this is now accepted:

use std::ops::Not;

struct A;
struct B;

impl Not for A {
    type Output = B;
    fn not(self) -> B { B }
}

impl Not for B {
    type Output = bool;
    fn not(self) -> bool { true }
}

fn main() {
    assert!(A);
}

@m-ou-se
Copy link
Member

m-ou-se commented Apr 2, 2024

We briefly discussed this in the lib-api meeting.

This seems fine, but we thought it is important to consider if this could just be a non-edition change, considering how rare using Not<Output=bool> in assert!() probably is.

However, in the meeting we failed to realize that that includes &bool; I assume that would have changed the outcome. ^^'

Note to self: For the next libs-api meeting, we should look at what Felix wrote here: #122661 (comment)

@m-ou-se m-ou-se added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. and removed T-libs Relevant to the library team, which will review and decide on the PR/issue. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 10, 2024
@Amanieu Amanieu removed the I-libs-api-nominated The issue / PR has been nominated for discussion during a libs-api team meeting. label Apr 16, 2024
@m-ou-se
Copy link
Member

m-ou-se commented Apr 30, 2024

We discussed this again in the libs-api meeting. We think it's fine if assert!() no longer supports &bool (and other Not<Output=bool> types) in the next edition. It might be worth checking (with crater) if it's possible to get away with that (breaking) change in all editions, but that seems unlikely.

@m-ou-se m-ou-se 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-team Status: Awaiting decision from the relevant subteam (see the T-<team> label). labels Apr 30, 2024
In the desugaring of `assert!`, assign the condition expression to a `bool`
biding in order to provide better type errors when passed the wrong thing.

The span will point only at the expression, and not the whole `assert!`
invokation.

```
error[E0308]: mismatched types
  --> $DIR/issue-14091.rs:2:13
   |
LL |     assert!(1,1);
   |             ^
   |             |
   |             expected `bool`, found integer
   |             expected due to this
```

We no longer mention the expression needing to implement the `Not` trait.

```
error[E0308]: mismatched types
  --> $DIR/issue-14091-2.rs:15:13
   |
LL |     assert!(x, x);
   |             ^
   |             |
   |             expected `bool`, found `BytePos`
   |             expected due to this
```

Fix rust-lang#122159.
@estebank
Copy link
Contributor Author

estebank commented May 7, 2024

It just dawned on me that changing the macro from expanding to if !cond { then } to if cond {} else { then }, we get the consistent behavior we want in every edition without any "tricks".

This approach works on *every* edition and emits the desired output consistently:

```
error[E0308]: mismatched types
  --> $DIR/issue-28308.rs:6:13
   |
LL |     assert!("foo");
   |             ^^^^^ expected `bool`, found `&str`
```
@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)

     Running tests/compile-test.rs (obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/compile_test-8cd08568846ce1e1)

FAILED TEST: tests/ui/assertions_on_result_states.rs
command: CLIPPY_CONF_DIR="tests" RUSTC_ICE="0" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/clippy-driver" "--error-format=json" "--emit=metadata" "-Aunused" "-Ainternal_features" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Dwarnings" "-Ldependency=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps" "--extern=clippy_config=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libclippy_config-8c8dc72c21921ba3.rlib" "--extern=clippy_lints=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libclippy_lints-6d6455405521dc34.rlib" "--extern=clippy_utils=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libclippy_utils-2de095cd716cbf0c.rlib" "--extern=futures=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libfutures-35d37adbfdfa9dbb.rlib" "--extern=if_chain=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libif_chain-ae846d6788d6a9f1.rlib" "--extern=itertools=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libitertools-9152caa60d22e5d6.rlib" "--extern=parking_lot=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libparking_lot-2c8e9f211ec0a5f8.rlib" "--extern=quote=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libquote-2336100e84e1156c.rlib" "--extern=regex=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libregex-5689c7175177147d.rlib" "--extern=serde=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libserde-5a558154da602083.rlib" "--extern=serde_derive=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/release/deps/libserde_derive-c18e5bce8d145559.so" "--extern=syn=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libsyn-f468dba3e65cc08b.rlib" "--extern=tokio=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libtokio-e9d338b744af34e7.rlib" "-Ldependency=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/release/deps" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/ui_test/tests/ui" "tests/ui/assertions_on_result_states.rs" "--edition" "2021"
error: actual output differed from expected
Execute `cargo uibless` to update `tests/ui/assertions_on_result_states.stderr` to the actual output
--- tests/ui/assertions_on_result_states.stderr
+++ <stderr output>
+++ <stderr output>
-error: called `assert!` with `Result::is_ok`
-   |
-   |
-LL |     assert!(r.is_ok());
-   |     ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()`
-   = note: `-D clippy::assertions-on-result-states` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::assertions_on_result_states)]`
-
-
-error: called `assert!` with `Result::is_ok`
-   |
-   |
-LL |     assert!(get_ok().is_ok());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get_ok().unwrap()`
-
-error: called `assert!` with `Result::is_ok`
-   |
-   |
-LL |     assert!(get_ok_macro!().is_ok());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `get_ok_macro!().unwrap()`
-
-error: called `assert!` with `Result::is_ok`
-   |
-   |
-LL |     assert!(r.is_ok());
-   |     ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()`
-
-error: called `assert!` with `Result::is_ok`
-   |
-   |
-LL |         assert!(r.is_ok());
-   |         ^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap()`
-
-error: called `assert!` with `Result::is_err`
-   |
-   |
-LL |     assert!(r.is_err());
-   |     ^^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap_err()`
-
-error: called `assert!` with `Result::is_err`
-   |
-   |
-LL |     assert!(res.is_err())
-   |     ^^^^^^^^^^^^^^^^^^^^^ help: replace with: `res.unwrap_err();`
-error: aborting due to 7 previous errors
-



full stderr:

full stdout:



FAILED TEST: tests/ui/missing_asserts_for_indexing_unfixable.rs
command: CLIPPY_CONF_DIR="tests" RUSTC_ICE="0" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/clippy-driver" "--error-format=json" "--emit=metadata" "-Aunused" "-Ainternal_features" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Dwarnings" "-Ldependency=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps" "--extern=clippy_config=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libclippy_config-8c8dc72c21921ba3.rlib" "--extern=clippy_lints=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libclippy_lints-6d6455405521dc34.rlib" "--extern=clippy_utils=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libclippy_utils-2de095cd716cbf0c.rlib" "--extern=futures=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libfutures-35d37adbfdfa9dbb.rlib" "--extern=if_chain=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libif_chain-ae846d6788d6a9f1.rlib" "--extern=itertools=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libitertools-9152caa60d22e5d6.rlib" "--extern=parking_lot=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libparking_lot-2c8e9f211ec0a5f8.rlib" "--extern=quote=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libquote-2336100e84e1156c.rlib" "--extern=regex=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libregex-5689c7175177147d.rlib" "--extern=serde=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libserde-5a558154da602083.rlib" "--extern=serde_derive=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/release/deps/libserde_derive-c18e5bce8d145559.so" "--extern=syn=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libsyn-f468dba3e65cc08b.rlib" "--extern=tokio=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libtokio-e9d338b744af34e7.rlib" "-Ldependency=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/release/deps" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/ui_test/tests/ui" "tests/ui/missing_asserts_for_indexing_unfixable.rs" "--edition" "2021"
error: actual output differed from expected
Execute `cargo uibless` to update `tests/ui/missing_asserts_for_indexing_unfixable.stderr` to the actual output
--- tests/ui/missing_asserts_for_indexing_unfixable.stderr
+++ <stderr output>
+++ <stderr output>
 error: indexing into a slice multiple times without an `assert`
... 121 lines skipped ...
 
 
 error: indexing into a slice multiple times without an `assert`
+   |
+   |
+LL |     let _ = v1[0] + v1[12];
+   |
+   |
+   = help: consider asserting the length before indexing: `assert!(v1.len() > 12);`
+note: slice indexed here
+   |
+   |
+LL |     let _ = v1[0] + v1[12];
+note: slice indexed here
+  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:30:21
+   |
+   |
+LL |     let _ = v1[0] + v1[12];
+   = note: asserting the length before indexing will elide bounds checks
+
+
+error: indexing into a slice multiple times without an `assert`
    |
... 52 lines skipped ...
    = note: asserting the length before indexing will elide bounds checks
 
 
-error: aborting due to 8 previous errors
+error: indexing into a slice multiple times without an `assert`
+error: aborting due to 10 previous errors
+



full stderr:
error: indexing into a slice multiple times without an `assert`
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
   |
   |
   = help: consider asserting the length before indexing: `assert!(v.len() > 4);`
note: slice indexed here
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:5:12
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:5:19
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:5:26
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:5:33
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
   = note: asserting the length before indexing will elide bounds checks
   = note: `-D clippy::missing-asserts-for-indexing` implied by `-D warnings`
   = help: to override `-D warnings` add `#[allow(clippy::missing_asserts_for_indexing)]`


error: indexing into a slice multiple times without an `assert`
   |
LL |       let _ = v[0];
   |  _____________^
LL | |
LL | |
LL | |     let _ = v[1..4];
   |
   |
   = help: consider asserting the length before indexing: `assert!(v.len() > 3);`
note: slice indexed here
   |
LL |     let _ = v[0];
   |             ^^^^
note: slice indexed here
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:12:13
   |
LL |     let _ = v[1..4];
   = note: asserting the length before indexing will elide bounds checks


error: indexing into a slice multiple times without an `assert`
   |
LL |       let a = v[0];
   |  _____________^
LL | |
LL | |
LL | |     let b = v[1];
LL | |     let c = v[2];
   | |________________^
   |
   = help: consider asserting the length before indexing: `assert!(v.len() > 2);`
note: slice indexed here
   |
LL |     let a = v[0];
   |             ^^^^
note: slice indexed here
---
LL |     let c = v[2];
   |             ^^^^
   = note: asserting the length before indexing will elide bounds checks

error: indexing into a slice multiple times without an `assert`
   |
   |
LL |     let _ = v1[0] + v1[12];
   |
   |
   = help: consider asserting the length before indexing: `assert!(v1.len() > 12);`
note: slice indexed here
   |
   |
LL |     let _ = v1[0] + v1[12];
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:24:21
   |
   |
LL |     let _ = v1[0] + v1[12];
   = note: asserting the length before indexing will elide bounds checks


error: indexing into a slice multiple times without an `assert`
   |
   |
LL |     let _ = v2[5] + v2[15];
   |
   |
   = help: consider asserting the length before indexing: `assert!(v2.len() > 15);`
note: slice indexed here
   |
   |
LL |     let _ = v2[5] + v2[15];
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:25:21
   |
   |
LL |     let _ = v2[5] + v2[15];
   = note: asserting the length before indexing will elide bounds checks


error: indexing into a slice multiple times without an `assert`
   |
   |
LL |     let _ = v1[0] + v1[12];
   |
   |
   = help: consider asserting the length before indexing: `assert!(v1.len() > 12);`
note: slice indexed here
   |
   |
LL |     let _ = v1[0] + v1[12];
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:30:21
   |
   |
LL |     let _ = v1[0] + v1[12];
   = note: asserting the length before indexing will elide bounds checks


error: indexing into a slice multiple times without an `assert`
   |
   |
LL |     let _ = v2[5] + v2[15];
   |
   |
   = help: consider asserting the length before indexing: `assert!(v2.len() > 15);`
note: slice indexed here
   |
   |
LL |     let _ = v2[5] + v2[15];
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:31:21
   |
   |
LL |     let _ = v2[5] + v2[15];
   = note: asserting the length before indexing will elide bounds checks


error: indexing into a slice multiple times without an `assert`
   |
   |
LL |     let _ = f.v[0] + f.v[1];
   |
   |
   = help: consider asserting the length before indexing: `assert!(f.v.len() > 1);`
note: slice indexed here
   |
   |
LL |     let _ = f.v[0] + f.v[1];
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:40:22
   |
   |
LL |     let _ = f.v[0] + f.v[1];
   = note: asserting the length before indexing will elide bounds checks


error: indexing into a slice multiple times without an `assert`
   |
   |
LL |     let _ = x[0] + x[1];
   |
   |
   = help: consider asserting the length before indexing: `assert!(x.len() > 1);`
note: slice indexed here
   |
   |
LL |     let _ = x[0] + x[1];
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:54:20
   |
   |
LL |     let _ = x[0] + x[1];
   = note: asserting the length before indexing will elide bounds checks


error: indexing into a slice multiple times without an `assert`
   |
   |
LL |           if w[0] < w[1] {
   |  ____________^
LL | |             ascending.push((w[0], w[1]));
LL | |         } else {
LL | |             ascending.push((w[1], w[0]));
   |
   |
   = help: consider asserting the length before indexing: `assert!(w.len() > 1);`
note: slice indexed here
   |
   |
LL |         if w[0] < w[1] {
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:62:19
   |
   |
LL |         if w[0] < w[1] {
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:63:29
   |
   |
LL |             ascending.push((w[0], w[1]));
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:63:35
   |
   |
LL |             ascending.push((w[0], w[1]));
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:65:29
   |
   |
LL |             ascending.push((w[1], w[0]));
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing_unfixable.rs:65:35
   |
   |
LL |             ascending.push((w[1], w[0]));
   = note: asserting the length before indexing will elide bounds checks

error: aborting due to 10 previous errors



full stdout:



FAILED TEST: tests/ui/missing_asserts_for_indexing.rs
command: CLIPPY_CONF_DIR="tests" RUSTC_ICE="0" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/clippy-driver" "--error-format=json" "--emit=metadata" "-Aunused" "-Ainternal_features" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Dwarnings" "-Ldependency=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps" "--extern=clippy_config=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libclippy_config-8c8dc72c21921ba3.rlib" "--extern=clippy_lints=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libclippy_lints-6d6455405521dc34.rlib" "--extern=clippy_utils=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libclippy_utils-2de095cd716cbf0c.rlib" "--extern=futures=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libfutures-35d37adbfdfa9dbb.rlib" "--extern=if_chain=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libif_chain-ae846d6788d6a9f1.rlib" "--extern=itertools=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libitertools-9152caa60d22e5d6.rlib" "--extern=parking_lot=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libparking_lot-2c8e9f211ec0a5f8.rlib" "--extern=quote=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libquote-2336100e84e1156c.rlib" "--extern=regex=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libregex-5689c7175177147d.rlib" "--extern=serde=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libserde-5a558154da602083.rlib" "--extern=serde_derive=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/release/deps/libserde_derive-c18e5bce8d145559.so" "--extern=syn=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libsyn-f468dba3e65cc08b.rlib" "--extern=tokio=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/deps/libtokio-e9d338b744af34e7.rlib" "-Ldependency=/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/release/deps" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2-tools/ui_test/tests/ui" "tests/ui/missing_asserts_for_indexing.rs" "--edition" "2021"
error: actual output differed from expected
Execute `cargo uibless` to update `tests/ui/missing_asserts_for_indexing.stderr` to the actual output
--- tests/ui/missing_asserts_for_indexing.stderr
+++ <stderr output>
+++ <stderr output>
-error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+error: indexing into a slice multiple times without an `assert`
    |
    |
-LL |     assert!(v.len() < 5);
-   |     -------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)`
 LL |     v[0] + v[1] + v[2] + v[3] + v[4]
    |
    |
+   = help: consider asserting the length before indexing: `assert!(v.len() > 4);`
 note: slice indexed here
... 22 lines skipped ...
    |                                 ^^^^
    = note: asserting the length before indexing will elide bounds checks
-   = note: `-D clippy::missing-asserts-for-indexing` implied by `-D warnings`
-   = note: `-D clippy::missing-asserts-for-indexing` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::missing_asserts_for_indexing)]`
 
-error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+error: indexing into a slice multiple times without an `assert`
    |
    |
-LL |     assert!(v.len() <= 5);
-   |     --------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)`
 LL |     v[0] + v[1] + v[2] + v[3] + v[4]
    |
    |
+   = help: consider asserting the length before indexing: `assert!(v.len() > 4);`
 note: slice indexed here
... 23 lines skipped ...
    = note: asserting the length before indexing will elide bounds checks
 
 
-error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+error: indexing into a slice multiple times without an `assert`
    |
    |
-LL |     assert!(v.len() > 3);
-   |     -------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)`
 LL |     v[0] + v[1] + v[2] + v[3] + v[4]
    |
    |
+   = help: consider asserting the length before indexing: `assert!(v.len() > 4);`
 note: slice indexed here
... 23 lines skipped ...
    = note: asserting the length before indexing will elide bounds checks
 
 
-error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+error: indexing into a slice multiple times without an `assert`
    |
    |
-LL |     assert!(v.len() >= 4);
-   |     --------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)`
 LL |     v[0] + v[1] + v[2] + v[3] + v[4]
    |
    |
+   = help: consider asserting the length before indexing: `assert!(v.len() > 4);`
 note: slice indexed here
... 23 lines skipped ...
    = note: asserting the length before indexing will elide bounds checks
 
 
-error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+error: indexing into a slice multiple times without an `assert`
    |
    |
-LL |       assert!(v.len() >= 3);
-   |       --------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 3)`
 LL |       let _ = v[0];
... 2 lines skipped ...
    | |___________________^
    |
    |
+   = help: consider asserting the length before indexing: `assert!(v.len() > 3);`
 note: slice indexed here
... 8 lines skipped ...
    = note: asserting the length before indexing will elide bounds checks
 
 
-error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+error: indexing into a slice multiple times without an `assert`
    |
    |
-LL |       assert!(v.len() >= 4);
-   |       --------------------- help: provide the highest index that is indexed with: `assert!(v.len() > 4)`
 LL |       let _ = v[0];
... 2 lines skipped ...
    | |____________________^
    |
    |
+   = help: consider asserting the length before indexing: `assert!(v.len() > 4);`
 note: slice indexed here
... 8 lines skipped ...
    = note: asserting the length before indexing will elide bounds checks
 
 
-error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+error: indexing into a slice multiple times without an `assert`
    |
    |
-LL |     assert!(v1.len() >= 12);
-   |     ----------------------- help: provide the highest index that is indexed with: `assert!(v1.len() > 12)`
-LL |     assert!(v2.len() >= 15);
 LL |     let _ = v1[0] + v1[12];
    |
    |
+   = help: consider asserting the length before indexing: `assert!(v1.len() > 12);`
 note: slice indexed here
... 8 lines skipped ...
    = note: asserting the length before indexing will elide bounds checks
 
 
-error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+error: indexing into a slice multiple times without an `assert`
    |
    |
-LL |     assert!(v2.len() >= 15);
-   |     ----------------------- help: provide the highest index that is indexed with: `assert!(v2.len() > 15)`
-...
 LL |     let _ = v2[5] + v2[15];
    |
    |
+   = help: consider asserting the length before indexing: `assert!(v2.len() > 15);`
 note: slice indexed here
... 8 lines skipped ...
    = note: asserting the length before indexing will elide bounds checks
 
 
-error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+error: indexing into a slice multiple times without an `assert`
    |
    |
-LL |     assert!(v1.len() >= 12);
-   |     ----------------------- help: provide the highest index that is indexed with: `assert!(v1.len() > 12)`
-LL |     assert!(v2.len() > 15);
 LL |     let _ = v1[0] + v1[12];
    |
    |
+   = help: consider asserting the length before indexing: `assert!(v1.len() > 12);`
 note: slice indexed here
... 8 lines skipped ...
    = note: asserting the length before indexing will elide bounds checks
 
 
-error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+error: indexing into a slice multiple times without an `assert`
    |
    |
-LL |     assert!(v1.len() == 2);
-   |     ---------------------- help: provide the highest index that is indexed with: `assert!(v1.len() == 3)`
-...
 LL |     let _ = v1[0] + v1[1] + v1[2];
    |
    |
+   = help: consider asserting the length before indexing: `assert!(v1.len() > 2);`
 note: slice indexed here
... 13 lines skipped ...
    = note: asserting the length before indexing will elide bounds checks
 
 
-error: indexing into a slice multiple times with an `assert` that does not cover the highest index
+error: indexing into a slice multiple times without an `assert`
    |
    |
-LL |     assert!(2 == v3.len());
-   |     ---------------------- help: provide the highest index that is indexed with: `assert!(v3.len() == 3)`
-...
 LL |     let _ = v3[0] + v3[1] + v3[2];
    |
    |
+   = help: consider asserting the length before indexing: `assert!(v3.len() > 2);`
 note: slice indexed here
... 13 lines skipped ...
    = note: asserting the length before indexing will elide bounds checks
 
-error: aborting due to 11 previous errors
-error: aborting due to 11 previous errors
+error: indexing into a slice multiple times without an `assert`
+error: aborting due to 22 previous errors
+



error: `indexing into a slice multiple times with an `assert` that does not cover the` not found in diagnostics on line 30
   |
   |
31 |     //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
   |


error: `indexing into a slice multiple times with an `assert` that does not cover the` not found in diagnostics on line 36
   |
   |
37 |     //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
   |


error: `indexing into a slice multiple times with an `assert` that does not cover the` not found in diagnostics on line 42
   |
   |
43 |     //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
   |


error: `indexing into a slice multiple times with an `assert` that does not cover the` not found in diagnostics on line 48
   |
   |
49 |     //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
   |


error: `indexing into a slice multiple times with an `assert` that does not cover the` not found in diagnostics on line 66
   |
   |
67 |     //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
   |


error: `indexing into a slice multiple times with an `assert` that does not cover the` not found in diagnostics on line 80
   |
   |
81 |     //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
   |


error: `indexing into a slice multiple times with an `assert` that does not cover the` not found in diagnostics on line 95
   |
   |
96 |     //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
   |


error: `indexing into a slice multiple times with an `assert` that does not cover the` not found in diagnostics on line 97
   |
   |
98 |     //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
   |


error: `indexing into a slice multiple times with an `assert` that does not cover the` not found in diagnostics on line 103
    |
    |
104 |     //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
    |


error: `indexing into a slice multiple times with an `assert` that does not cover the` not found in diagnostics on line 127
    |
    |
128 |     //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
    |


error: `indexing into a slice multiple times with an `assert` that does not cover the` not found in diagnostics on line 131
    |
    |
132 |     //~^ ERROR: indexing into a slice multiple times with an `assert` that does not cover the
    |

full stderr:
full stderr:
error: indexing into a slice multiple times without an `assert`
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
   |
   |
   = help: consider asserting the length before indexing: `assert!(v.len() > 4);`
note: slice indexed here
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing.rs:7:12
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing.rs:7:19
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing.rs:7:26
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing.rs:7:33
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
   = note: asserting the length before indexing will elide bounds checks
   = note: `-D clippy::missing-asserts-for-indexing` implied by `-D warnings`
   = help: to override `-D warnings` add `#[allow(clippy::missing_asserts_for_indexing)]`


error: indexing into a slice multiple times without an `assert`
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
   |
   |
   = help: consider asserting the length before indexing: `assert!(v.len() > 4);`
note: slice indexed here
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing.rs:13:12
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing.rs:13:19
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
note: slice indexed here
  --> tests/ui/missing_asserts_for_indexing.rs:13:26
   |
   |
LL |     v[0] + v[1] + v[2] + v[3] + v[4]
note: slice indexed here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I-lang-nominated The issue / PR has been nominated for discussion during a lang team meeting. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

inconsistent and confusing error message about first argument of assert!