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