1 #![allow(
2     clippy::diverging_sub_expression,
3     clippy::if_same_then_else,
4     clippy::ifs_same_cond,
5     clippy::items_after_statements,
6     clippy::let_and_return,
7     clippy::let_underscore_drop,
8     clippy::logic_bug,
9     clippy::match_bool,
10     clippy::never_loop,
11     clippy::redundant_closure_call,
12     clippy::redundant_pattern_matching,
13     clippy::too_many_lines,
14     clippy::unit_arg,
15     clippy::while_immutable_condition,
16     clippy::zero_ptr,
17     irrefutable_let_patterns
18 )]
19 
20 use anyhow::{anyhow, ensure, Chain, Error, Result};
21 use std::fmt::Debug;
22 use std::iter;
23 use std::marker::{PhantomData, PhantomData as P};
24 use std::ops::Add;
25 use std::ptr;
26 
27 struct S;
28 
29 impl<T> Add<T> for S {
30     type Output = bool;
add(self, rhs: T) -> Self::Output31     fn add(self, rhs: T) -> Self::Output {
32         let _ = rhs;
33         false
34     }
35 }
36 
37 trait Trait: Sized {
38     const V: usize = 0;
t(self, i: i32) -> i3239     fn t(self, i: i32) -> i32 {
40         i
41     }
42 }
43 
44 impl<T> Trait for T {}
45 
46 #[track_caller]
assert_err<T: Debug>(result: impl FnOnce() -> Result<T>, expected: &'static str)47 fn assert_err<T: Debug>(result: impl FnOnce() -> Result<T>, expected: &'static str) {
48     let actual = result().unwrap_err().to_string();
49 
50     // In general different rustc versions will format the interpolated lhs and
51     // rhs $:expr fragment with insignificant differences in whitespace or
52     // punctuation, so we check the message in full against nightly and do just
53     // a cursory test on older toolchains.
54     if rustversion::cfg!(nightly) && !cfg!(miri) {
55         assert_eq!(actual, expected);
56     } else {
57         assert_eq!(actual.contains(" vs "), expected.contains(" vs "));
58     }
59 }
60 
61 #[test]
test_recursion()62 fn test_recursion() {
63     // Must not blow the default #[recursion_limit], which is 128.
64     #[rustfmt::skip]
65     let test = || Ok(ensure!(
66         false | false | false | false | false | false | false | false | false |
67         false | false | false | false | false | false | false | false | false |
68         false | false | false | false | false | false | false | false | false |
69         false | false | false | false | false | false | false | false | false |
70         false | false | false | false | false | false | false | false | false |
71         false | false | false | false | false | false | false | false | false |
72         false | false | false | false | false | false | false | false | false
73     ));
74 
75     test().unwrap_err();
76 }
77 
78 #[test]
test_low_precedence_control_flow()79 fn test_low_precedence_control_flow() {
80     #[allow(unreachable_code)]
81     let test = || {
82         let val = loop {
83             // Break has lower precedence than the comparison operators so the
84             // expression here is `S + (break (1 == 1))`. It would be bad if the
85             // ensure macro partitioned this input into `(S + break 1) == (1)`
86             // because that means a different thing than what was written.
87             ensure!(S + break 1 == 1);
88         };
89         Ok(val)
90     };
91 
92     assert!(test().unwrap());
93 }
94 
95 #[test]
test_low_precedence_binary_operator()96 fn test_low_precedence_binary_operator() {
97     // Must not partition as `false == (true && false)`.
98     let test = || Ok(ensure!(false == true && false));
99     assert_err(test, "Condition failed: `false == true && false`");
100 
101     // But outside the root level, it is fine.
102     let test = || Ok(ensure!(while false == true && false {} < ()));
103     assert_err(
104         test,
105         "Condition failed: `while false == true && false {} < ()` (() vs ())",
106     );
107 }
108 
109 #[test]
test_closure()110 fn test_closure() {
111     // Must not partition as `(S + move) || (1 == 1)` by treating move as an
112     // identifier, nor as `(S + move || 1) == (1)` by misinterpreting the
113     // closure precedence.
114     let test = || Ok(ensure!(S + move || 1 == 1));
115     assert_err(test, "Condition failed: `S + (move || 1 == 1)`");
116 
117     let test = || Ok(ensure!(S + || 1 == 1));
118     assert_err(test, "Condition failed: `S + (|| 1 == 1)`");
119 
120     // Must not partition as `S + ((move | ()) | 1) == 1` by treating those
121     // pipes as bitwise-or.
122     let test = || Ok(ensure!(S + move |()| 1 == 1));
123     assert_err(test, "Condition failed: `S + (move |()| 1 == 1)`");
124 
125     let test = || Ok(ensure!(S + |()| 1 == 1));
126     assert_err(test, "Condition failed: `S + (|()| 1 == 1)`");
127 }
128 
129 #[test]
test_unary()130 fn test_unary() {
131     let mut x = &1;
132     let test = || Ok(ensure!(*x == 2));
133     assert_err(test, "Condition failed: `*x == 2` (1 vs 2)");
134 
135     let test = || Ok(ensure!(!x == 1));
136     assert_err(test, "Condition failed: `!x == 1` (-2 vs 1)");
137 
138     let test = || Ok(ensure!(-x == 1));
139     assert_err(test, "Condition failed: `-x == 1` (-1 vs 1)");
140 
141     let test = || Ok(ensure!(&x == &&2));
142     assert_err(test, "Condition failed: `&x == &&2` (1 vs 2)");
143 
144     let test = || Ok(ensure!(&mut x == *&&mut &2));
145     assert_err(test, "Condition failed: `&mut x == *&&mut &2` (1 vs 2)");
146 }
147 
148 #[test]
test_if()149 fn test_if() {
150     #[rustfmt::skip]
151     let test = || Ok(ensure!(if false {}.t(1) == 2));
152     assert_err(test, "Condition failed: `if false {}.t(1) == 2` (1 vs 2)");
153 
154     #[rustfmt::skip]
155     let test = || Ok(ensure!(if false {} else {}.t(1) == 2));
156     assert_err(
157         test,
158         "Condition failed: `if false {} else {}.t(1) == 2` (1 vs 2)",
159     );
160 
161     #[rustfmt::skip]
162     let test = || Ok(ensure!(if false {} else if false {}.t(1) == 2));
163     assert_err(
164         test,
165         "Condition failed: `if false {} else if false {}.t(1) == 2` (1 vs 2)",
166     );
167 
168     #[rustfmt::skip]
169     let test = || Ok(ensure!(if let 1 = 2 {}.t(1) == 2));
170     assert_err(
171         test,
172         "Condition failed: `if let 1 = 2 {}.t(1) == 2` (1 vs 2)",
173     );
174 
175     #[rustfmt::skip]
176     let test = || Ok(ensure!(if let 1 | 2 = 2 {}.t(1) == 2));
177     assert_err(
178         test,
179         "Condition failed: `if let 1 | 2 = 2 {}.t(1) == 2` (1 vs 2)",
180     );
181 
182     #[rustfmt::skip]
183     let test = || Ok(ensure!(if let | 1 | 2 = 2 {}.t(1) == 2));
184     assert_err(
185         test,
186         "Condition failed: `if let 1 | 2 = 2 {}.t(1) == 2` (1 vs 2)",
187     );
188 }
189 
190 #[test]
test_loop()191 fn test_loop() {
192     #[rustfmt::skip]
193     let test = || Ok(ensure!(1 + loop { break 1 } == 1));
194     assert_err(
195         test,
196         "Condition failed: `1 + loop { break 1 } == 1` (2 vs 1)",
197     );
198 
199     #[rustfmt::skip]
200     let test = || Ok(ensure!(1 + 'a: loop { break 'a 1 } == 1));
201     assert_err(
202         test,
203         "Condition failed: `1 + 'a: loop { break 'a 1 } == 1` (2 vs 1)",
204     );
205 
206     #[rustfmt::skip]
207     let test = || Ok(ensure!(while false {}.t(1) == 2));
208     assert_err(
209         test,
210         "Condition failed: `while false {}.t(1) == 2` (1 vs 2)",
211     );
212 
213     #[rustfmt::skip]
214     let test = || Ok(ensure!(while let None = Some(1) {}.t(1) == 2));
215     assert_err(
216         test,
217         "Condition failed: `while let None = Some(1) {}.t(1) == 2` (1 vs 2)",
218     );
219 
220     #[rustfmt::skip]
221     let test = || Ok(ensure!(for _x in iter::once(0) {}.t(1) == 2));
222     assert_err(
223         test,
224         "Condition failed: `for _x in iter::once(0) {}.t(1) == 2` (1 vs 2)",
225     );
226 
227     #[rustfmt::skip]
228     let test = || Ok(ensure!(for | _x in iter::once(0) {}.t(1) == 2));
229     assert_err(
230         test,
231         "Condition failed: `for _x in iter::once(0) {}.t(1) == 2` (1 vs 2)",
232     );
233 
234     #[rustfmt::skip]
235     let test = || Ok(ensure!(for true | false in iter::empty() {}.t(1) == 2));
236     assert_err(
237         test,
238         "Condition failed: `for true | false in iter::empty() {}.t(1) == 2` (1 vs 2)",
239     );
240 }
241 
242 #[test]
test_match()243 fn test_match() {
244     #[rustfmt::skip]
245     let test = || Ok(ensure!(match 1 == 1 { true => 1, false => 0 } == 2));
246     assert_err(
247         test,
248         "Condition failed: `match 1 == 1 { true => 1, false => 0, } == 2` (1 vs 2)",
249     );
250 }
251 
252 #[test]
test_atom()253 fn test_atom() {
254     let test = || Ok(ensure!([false, false].len() > 3));
255     assert_err(
256         test,
257         "Condition failed: `[false, false].len() > 3` (2 vs 3)",
258     );
259 
260     #[rustfmt::skip]
261     let test = || Ok(ensure!({ let x = 1; x } >= 3));
262     assert_err(test, "Condition failed: `{ let x = 1; x } >= 3` (1 vs 3)");
263 
264     let test = || Ok(ensure!(S + async { 1 } == true));
265     assert_err(
266         test,
267         "Condition failed: `S + async { 1 } == true` (false vs true)",
268     );
269 
270     let test = || Ok(ensure!(S + async move { 1 } == true));
271     assert_err(
272         test,
273         "Condition failed: `S + async move { 1 } == true` (false vs true)",
274     );
275 
276     let x = &1;
277     let test = || Ok(ensure!(S + unsafe { ptr::read(x) } == true));
278     assert_err(
279         test,
280         "Condition failed: `S + unsafe { ptr::read(x) } == true` (false vs true)",
281     );
282 }
283 
284 #[test]
test_path()285 fn test_path() {
286     let test = || Ok(ensure!(crate::S.t(1) == 2));
287     assert_err(test, "Condition failed: `crate::S.t(1) == 2` (1 vs 2)");
288 
289     let test = || Ok(ensure!(::anyhow::Error::root_cause.t(1) == 2));
290     assert_err(
291         test,
292         "Condition failed: `::anyhow::Error::root_cause.t(1) == 2` (1 vs 2)",
293     );
294 
295     let test = || Ok(ensure!(Error::msg::<&str>.t(1) == 2));
296     assert_err(
297         test,
298         "Condition failed: `Error::msg::<&str>.t(1) == 2` (1 vs 2)",
299     );
300 
301     #[rustfmt::skip]
302     let test = || Ok(ensure!(Error::msg::<&str,>.t(1) == 2));
303     assert_err(
304         test,
305         "Condition failed: `Error::msg::<&str>.t(1) == 2` (1 vs 2)",
306     );
307 
308     let test = || Ok(ensure!(Error::msg::<<str as ToOwned>::Owned>.t(1) == 2));
309     assert_err(
310         test,
311         "Condition failed: `Error::msg::<<str as ToOwned>::Owned>.t(1) == 2` (1 vs 2)",
312     );
313 
314     let test = || Ok(ensure!(Chain::<'static>::new.t(1) == 2));
315     assert_err(
316         test,
317         "Condition failed: `Chain::<'static>::new.t(1) == 2` (1 vs 2)",
318     );
319 
320     #[rustfmt::skip]
321     let test = || Ok(ensure!(Chain::<'static,>::new.t(1) == 2));
322     assert_err(
323         test,
324         "Condition failed: `Chain::<'static>::new.t(1) == 2` (1 vs 2)",
325     );
326 
327     fn f<const I: isize>() {}
328     let test = || Ok(ensure!(f::<1>() != ()));
329     assert_err(test, "Condition failed: `f::<1>() != ()` (() vs ())");
330     let test = || Ok(ensure!(f::<-1>() != ()));
331     assert_err(test, "Condition failed: `f::<-1>() != ()` (() vs ())");
332 
333     fn g<T, const I: isize>() {}
334     let test = || Ok(ensure!(g::<u8, 1>() != ()));
335     assert_err(test, "Condition failed: `g::<u8, 1>() != ()` (() vs ())");
336     let test = || Ok(ensure!(g::<u8, -1>() != ()));
337     assert_err(test, "Condition failed: `g::<u8, -1>() != ()` (() vs ())");
338 
339     #[derive(PartialOrd, PartialEq, Debug)]
340     enum E<'a, T> {
341         #[allow(dead_code)]
342         T(&'a T),
343         U,
344     }
345 
346     #[rustfmt::skip]
347     let test = || Ok(ensure!(E::U::<>>E::U::<u8>));
348     assert_err(test, "Condition failed: `E::U::<> > E::U::<u8>` (U vs U)");
349 
350     #[rustfmt::skip]
351     let test = || Ok(ensure!(E::U::<u8>>E::U));
352     assert_err(test, "Condition failed: `E::U::<u8> > E::U` (U vs U)");
353 
354     #[rustfmt::skip]
355     let test = || Ok(ensure!(E::U::<u8,>>E::U));
356     assert_err(test, "Condition failed: `E::U::<u8> > E::U` (U vs U)");
357 
358     let test = || Ok(ensure!(PhantomData::<dyn Debug + Sync> != PhantomData));
359     assert_err(
360         test,
361         "Condition failed: `PhantomData::<dyn Debug + Sync> != PhantomData` (PhantomData vs PhantomData)",
362     );
363 
364     let test = || Ok(ensure!(PhantomData::<dyn Fn() + Sync> != PhantomData));
365     assert_err(
366         test,
367         "Condition failed: `PhantomData::<dyn Fn() + Sync> != PhantomData` (PhantomData vs PhantomData)",
368     );
369 
370     #[rustfmt::skip]
371     let test = || {
372         Ok(ensure!(
373             PhantomData::<dyn Fn::() + ::std::marker::Sync> != PhantomData
374         ))
375     };
376     assert_err(
377         test,
378         "Condition failed: `PhantomData::<dyn Fn() + ::std::marker::Sync> != PhantomData` (PhantomData vs PhantomData)",
379     );
380 }
381 
382 #[test]
test_macro()383 fn test_macro() {
384     let test = || Ok(ensure!(anyhow!("...").to_string().len() <= 1));
385     assert_err(
386         test,
387         "Condition failed: `anyhow!(\"...\").to_string().len() <= 1` (3 vs 1)",
388     );
389 
390     let test = || Ok(ensure!(vec![1].len() < 1));
391     assert_err(test, "Condition failed: `vec![1].len() < 1` (1 vs 1)");
392 
393     let test = || Ok(ensure!(stringify! {} != ""));
394     assert_err(
395         test,
396         "Condition failed: `stringify! {} != \"\"` (\"\" vs \"\")",
397     );
398 }
399 
400 #[test]
test_trailer()401 fn test_trailer() {
402     let test = || Ok(ensure!((|| 1)() == 2));
403     assert_err(test, "Condition failed: `(|| 1)() == 2` (1 vs 2)");
404 
405     let test = || Ok(ensure!(b"hmm"[1] == b'c'));
406     assert_err(test, "Condition failed: `b\"hmm\"[1] == b'c'` (109 vs 99)");
407 
408     let test = || Ok(ensure!(PhantomData::<u8> {} != PhantomData));
409     assert_err(
410         test,
411         "Condition failed: `PhantomData::<u8> {} != PhantomData` (PhantomData vs PhantomData)",
412     );
413 
414     let result = Ok::<_, Error>(1);
415     let test = || Ok(ensure!(result? == 2));
416     assert_err(test, "Condition failed: `result? == 2` (1 vs 2)");
417 
418     let test = || Ok(ensure!((2, 3).1 == 2));
419     assert_err(test, "Condition failed: `(2, 3).1 == 2` (3 vs 2)");
420 
421     #[rustfmt::skip]
422     let test = || Ok(ensure!((2, (3, 4)). 1.1 == 2));
423     assert_err(test, "Condition failed: `(2, (3, 4)).1.1 == 2` (4 vs 2)");
424 
425     let err = anyhow!("");
426     let test = || Ok(ensure!(err.is::<&str>() == false));
427     assert_err(
428         test,
429         "Condition failed: `err.is::<&str>() == false` (true vs false)",
430     );
431 
432     let test = || Ok(ensure!(err.is::<<str as ToOwned>::Owned>() == true));
433     assert_err(
434         test,
435         "Condition failed: `err.is::<<str as ToOwned>::Owned>() == true` (false vs true)",
436     );
437 }
438 
439 #[test]
test_whitespace()440 fn test_whitespace() {
441     #[derive(Debug)]
442     pub struct Point {
443         pub x: i32,
444         pub y: i32,
445     }
446 
447     let point = Point { x: 0, y: 0 };
448     let test = || Ok(ensure!("" == format!("{:#?}", point)));
449     assert_err(
450         test,
451         "Condition failed: `\"\" == format!(\"{:#?}\", point)`",
452     );
453 }
454 
455 #[test]
test_too_long()456 fn test_too_long() {
457     let test = || Ok(ensure!("" == "x".repeat(10)));
458     assert_err(
459         test,
460         "Condition failed: `\"\" == \"x\".repeat(10)` (\"\" vs \"xxxxxxxxxx\")",
461     );
462 
463     let test = || Ok(ensure!("" == "x".repeat(80)));
464     assert_err(test, "Condition failed: `\"\" == \"x\".repeat(80)`");
465 }
466 
467 #[test]
test_as()468 fn test_as() {
469     let test = || Ok(ensure!('\0' as u8 > 1));
470     assert_err(test, "Condition failed: `'\\0' as u8 > 1` (0 vs 1)");
471 
472     let test = || Ok(ensure!('\0' as ::std::primitive::u8 > 1));
473     assert_err(
474         test,
475         "Condition failed: `'\\0' as ::std::primitive::u8 > 1` (0 vs 1)",
476     );
477 
478     let test = || Ok(ensure!(&[0] as &[i32] == [1]));
479     assert_err(
480         test,
481         "Condition failed: `&[0] as &[i32] == [1]` ([0] vs [1])",
482     );
483 
484     let test = || Ok(ensure!(0 as *const () as *mut _ == 1 as *mut ()));
485     assert_err(
486         test,
487         "Condition failed: `0 as *const () as *mut _ == 1 as *mut ()` (0x0 vs 0x1)",
488     );
489 
490     let s = "";
491     let test = || Ok(ensure!(s as &str != s));
492     assert_err(test, "Condition failed: `s as &str != s` (\"\" vs \"\")");
493 
494     let test = || Ok(ensure!(&s as &&str != &s));
495     assert_err(test, "Condition failed: `&s as &&str != &s` (\"\" vs \"\")");
496 
497     let test = || Ok(ensure!(s as &'static str != s));
498     assert_err(
499         test,
500         "Condition failed: `s as &'static str != s` (\"\" vs \"\")",
501     );
502 
503     let test = || Ok(ensure!(&s as &&'static str != &s));
504     assert_err(
505         test,
506         "Condition failed: `&s as &&'static str != &s` (\"\" vs \"\")",
507     );
508 
509     let m: &mut str = Default::default();
510     let test = || Ok(ensure!(m as &mut str != s));
511     assert_err(
512         test,
513         "Condition failed: `m as &mut str != s` (\"\" vs \"\")",
514     );
515 
516     let test = || Ok(ensure!(&m as &&mut str != &s));
517     assert_err(
518         test,
519         "Condition failed: `&m as &&mut str != &s` (\"\" vs \"\")",
520     );
521 
522     let test = || Ok(ensure!(&m as &&'static mut str != &s));
523     assert_err(
524         test,
525         "Condition failed: `&m as &&'static mut str != &s` (\"\" vs \"\")",
526     );
527 
528     let f = || {};
529     let test = || Ok(ensure!(f as fn() as usize * 0 != 0));
530     assert_err(
531         test,
532         "Condition failed: `f as fn() as usize * 0 != 0` (0 vs 0)",
533     );
534 
535     let test = || Ok(ensure!(f as fn() -> () as usize * 0 != 0));
536     assert_err(
537         test,
538         "Condition failed: `f as fn() -> () as usize * 0 != 0` (0 vs 0)",
539     );
540 
541     let test = || Ok(ensure!(f as for<'a> fn() as usize * 0 != 0));
542     assert_err(
543         test,
544         "Condition failed: `f as for<'a> fn() as usize * 0 != 0` (0 vs 0)",
545     );
546 
547     let test = || Ok(ensure!(f as unsafe fn() as usize * 0 != 0));
548     assert_err(
549         test,
550         "Condition failed: `f as unsafe fn() as usize * 0 != 0` (0 vs 0)",
551     );
552 
553     #[rustfmt::skip]
554     let test = || Ok(ensure!(f as extern "Rust" fn() as usize * 0 != 0));
555     assert_err(
556         test,
557         "Condition failed: `f as extern \"Rust\" fn() as usize * 0 != 0` (0 vs 0)",
558     );
559 
560     extern "C" fn extern_fn() {}
561     #[rustfmt::skip]
562     let test = || Ok(ensure!(extern_fn as extern fn() as usize * 0 != 0));
563     assert_err(
564         test,
565         "Condition failed: `extern_fn as extern fn() as usize * 0 != 0` (0 vs 0)",
566     );
567 
568     let f = || -> ! { panic!() };
569     let test = || Ok(ensure!(f as fn() -> ! as usize * 0 != 0));
570     assert_err(
571         test,
572         "Condition failed: `f as fn() -> ! as usize * 0 != 0` (0 vs 0)",
573     );
574 
575     trait EqDebug<T>: PartialEq<T> + Debug {
576         type Assoc;
577     }
578 
579     impl<S, T> EqDebug<T> for S
580     where
581         S: PartialEq<T> + Debug,
582     {
583         type Assoc = bool;
584     }
585 
586     let test = || Ok(ensure!(&0 as &dyn EqDebug<i32, Assoc = bool> != &0));
587     assert_err(
588         test,
589         "Condition failed: `&0 as &dyn EqDebug<i32, Assoc = bool> != &0` (0 vs 0)",
590     );
591 
592     let test = || {
593         Ok(ensure!(
594             PhantomData as PhantomData<<i32 as ToOwned>::Owned> != PhantomData
595         ))
596     };
597     assert_err(
598         test,
599         "Condition failed: `PhantomData as PhantomData<<i32 as ToOwned>::Owned> != PhantomData` (PhantomData vs PhantomData)",
600     );
601 
602     macro_rules! int {
603         (...) => {
604             u8
605         };
606     }
607 
608     let test = || Ok(ensure!(0 as int!(...) != 0));
609     assert_err(test, "Condition failed: `0 as int!(...) != 0` (0 vs 0)");
610 
611     let test = || Ok(ensure!(0 as int![...] != 0));
612     assert_err(test, "Condition failed: `0 as int![...] != 0` (0 vs 0)");
613 
614     let test = || Ok(ensure!(0 as int! {...} != 0));
615     assert_err(test, "Condition failed: `0 as int! { ... } != 0` (0 vs 0)");
616 }
617 
618 #[test]
test_pat()619 fn test_pat() {
620     let test = || Ok(ensure!(if let ref mut _x @ 0 = 0 { 0 } else { 1 } == 1));
621     assert_err(
622         test,
623         "Condition failed: `if let ref mut _x @ 0 = 0 { 0 } else { 1 } == 1` (0 vs 1)",
624     );
625 
626     let test = || Ok(ensure!(if let -1..=1 = 0 { 0 } else { 1 } == 1));
627     assert_err(
628         test,
629         "Condition failed: `if let -1..=1 = 0 { 0 } else { 1 } == 1` (0 vs 1)",
630     );
631 
632     let test = || Ok(ensure!(if let &0 = &0 { 0 } else { 1 } == 1));
633     assert_err(
634         test,
635         "Condition failed: `if let &0 = &0 { 0 } else { 1 } == 1` (0 vs 1)",
636     );
637 
638     let test = || Ok(ensure!(if let &&0 = &&0 { 0 } else { 1 } == 1));
639     assert_err(
640         test,
641         "Condition failed: `if let &&0 = &&0 { 0 } else { 1 } == 1` (0 vs 1)",
642     );
643 
644     let test = || Ok(ensure!(if let &mut 0 = &mut 0 { 0 } else { 1 } == 1));
645     assert_err(
646         test,
647         "Condition failed: `if let &mut 0 = &mut 0 { 0 } else { 1 } == 1` (0 vs 1)",
648     );
649 
650     let test = || Ok(ensure!(if let &&mut 0 = &&mut 0 { 0 } else { 1 } == 1));
651     assert_err(
652         test,
653         "Condition failed: `if let &&mut 0 = &&mut 0 { 0 } else { 1 } == 1` (0 vs 1)",
654     );
655 
656     let test = || Ok(ensure!(if let (0, 1) = (0, 1) { 0 } else { 1 } == 1));
657     assert_err(
658         test,
659         "Condition failed: `if let (0, 1) = (0, 1) { 0 } else { 1 } == 1` (0 vs 1)",
660     );
661 
662     let test = || Ok(ensure!(if let [0] = b"\0" { 0 } else { 1 } == 1));
663     assert_err(
664         test,
665         "Condition failed: `if let [0] = b\"\\0\" { 0 } else { 1 } == 1` (0 vs 1)",
666     );
667 
668     let p = PhantomData::<u8>;
669     let test = || Ok(ensure!(if let P::<u8> {} = p { 0 } else { 1 } == 1));
670     assert_err(
671         test,
672         "Condition failed: `if let P::<u8> {} = p { 0 } else { 1 } == 1` (0 vs 1)",
673     );
674 
675     let test = || Ok(ensure!(if let ::std::marker::PhantomData = p {} != ()));
676     assert_err(
677         test,
678         "Condition failed: `if let ::std::marker::PhantomData = p {} != ()` (() vs ())",
679     );
680 
681     let test = || Ok(ensure!(if let <S as Trait>::V = 0 { 0 } else { 1 } == 1));
682     assert_err(
683         test,
684         "Condition failed: `if let <S as Trait>::V = 0 { 0 } else { 1 } == 1` (0 vs 1)",
685     );
686 
687     let test = || Ok(ensure!(for _ in iter::once(()) {} != ()));
688     assert_err(
689         test,
690         "Condition failed: `for _ in iter::once(()) {} != ()` (() vs ())",
691     );
692 
693     let test = || Ok(ensure!(if let stringify!(x) = "x" { 0 } else { 1 } == 1));
694     assert_err(
695         test,
696         "Condition failed: `if let stringify!(x) = \"x\" { 0 } else { 1 } == 1` (0 vs 1)",
697     );
698 }
699