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::match_bool,
9     clippy::never_loop,
10     clippy::redundant_closure_call,
11     clippy::redundant_pattern_matching,
12     clippy::too_many_lines,
13     clippy::unit_arg,
14     clippy::while_immutable_condition,
15     clippy::zero_ptr
16 )]
17 
18 use anyhow::{anyhow, ensure, Chain, Error, Result};
19 use std::fmt::Debug;
20 use std::iter;
21 use std::marker::{PhantomData, PhantomData as P};
22 use std::ops::Add;
23 use std::ptr;
24 
25 struct S;
26 
27 impl<T> Add<T> for S {
28     type Output = bool;
add(self, rhs: T) -> Self::Output29     fn add(self, rhs: T) -> Self::Output {
30         let _ = rhs;
31         false
32     }
33 }
34 
35 trait Trait: Sized {
36     const V: usize = 0;
t(self, i: i32) -> i3237     fn t(self, i: i32) -> i32 {
38         i
39     }
40 }
41 
42 impl<T> Trait for T {}
43 
44 #[track_caller]
assert_err<T: Debug>(result: impl FnOnce() -> Result<T>, expected: &'static str)45 fn assert_err<T: Debug>(result: impl FnOnce() -> Result<T>, expected: &'static str) {
46     let actual = result().unwrap_err().to_string();
47 
48     let mut accepted_alternatives = expected.split('\n');
49     let expected = accepted_alternatives.next_back().unwrap();
50     if accepted_alternatives.any(|alternative| actual == alternative) {
51         return;
52     }
53 
54     assert_eq!(actual, expected);
55 }
56 
57 #[test]
test_recursion()58 fn test_recursion() {
59     // Must not blow the default #[recursion_limit], which is 128.
60     #[rustfmt::skip]
61     let test = || Ok(ensure!(
62         false | false | false | false | false | false | false | false | false |
63         false | false | false | false | false | false | false | false | false |
64         false | false | false | false | false | false | false | false | false |
65         false | false | false | false | false | false | false | false | false |
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     ));
70 
71     test().unwrap_err();
72 }
73 
74 #[test]
test_low_precedence_control_flow()75 fn test_low_precedence_control_flow() {
76     #[allow(unreachable_code)]
77     let test = || {
78         let val = loop {
79             // Break has lower precedence than the comparison operators so the
80             // expression here is `S + (break (1 == 1))`. It would be bad if the
81             // ensure macro partitioned this input into `(S + break 1) == (1)`
82             // because that means a different thing than what was written.
83             ensure!(S + break 1 == 1);
84         };
85         Ok(val)
86     };
87 
88     assert!(test().unwrap());
89 }
90 
91 #[test]
test_low_precedence_binary_operator()92 fn test_low_precedence_binary_operator() {
93     // Must not partition as `false == (true && false)`.
94     let test = || Ok(ensure!(false == true && false));
95     assert_err(test, "Condition failed: `false == true && false`");
96 
97     // But outside the root level, it is fine.
98     let test = || Ok(ensure!(while false == true && false {} < ()));
99     assert_err(
100         test,
101         "Condition failed: `while false == true && false { } < ()` (() vs ())",
102     );
103 }
104 
105 #[test]
test_closure()106 fn test_closure() {
107     // Must not partition as `(S + move) || (1 == 1)` by treating move as an
108     // identifier, nor as `(S + move || 1) == (1)` by misinterpreting the
109     // closure precedence.
110     let test = || Ok(ensure!(S + move || 1 == 1));
111     assert_err(test, "Condition failed: `S + (move || 1 == 1)`");
112 
113     let test = || Ok(ensure!(S + || 1 == 1));
114     assert_err(test, "Condition failed: `S + (|| 1 == 1)`");
115 
116     // Must not partition as `S + ((move | ()) | 1) == 1` by treating those
117     // pipes as bitwise-or.
118     let test = || Ok(ensure!(S + move |()| 1 == 1));
119     assert_err(test, "Condition failed: `S + (move |()| 1 == 1)`");
120 
121     let test = || Ok(ensure!(S + |()| 1 == 1));
122     assert_err(test, "Condition failed: `S + (|()| 1 == 1)`");
123 }
124 
125 #[test]
test_unary()126 fn test_unary() {
127     let mut x = &1;
128     let test = || Ok(ensure!(*x == 2));
129     assert_err(test, "Condition failed: `*x == 2` (1 vs 2)");
130 
131     let test = || Ok(ensure!(!x == 1));
132     assert_err(test, "Condition failed: `!x == 1` (-2 vs 1)");
133 
134     let test = || Ok(ensure!(-x == 1));
135     assert_err(test, "Condition failed: `-x == 1` (-1 vs 1)");
136 
137     let test = || Ok(ensure!(&x == &&2));
138     assert_err(test, "Condition failed: `&x == &&2` (1 vs 2)");
139 
140     let test = || Ok(ensure!(&mut x == *&&mut &2));
141     assert_err(test, "Condition failed: `&mut x == *&&mut &2` (1 vs 2)");
142 }
143 
144 #[test]
test_if()145 fn test_if() {
146     #[rustfmt::skip]
147     let test = || Ok(ensure!(if false {}.t(1) == 2));
148     assert_err(test, "Condition failed: `if false { }.t(1) == 2` (1 vs 2)");
149 
150     #[rustfmt::skip]
151     let test = || Ok(ensure!(if false {} else {}.t(1) == 2));
152     assert_err(
153         test,
154         "Condition failed: `if false { } else { }.t(1) == 2` (1 vs 2)",
155     );
156 
157     #[rustfmt::skip]
158     let test = || Ok(ensure!(if false {} else if false {}.t(1) == 2));
159     assert_err(
160         test,
161         "Condition failed: `if false { } else if false { }.t(1) == 2` (1 vs 2)",
162     );
163 
164     #[rustfmt::skip]
165     let test = || Ok(ensure!(if let 1 = 2 {}.t(1) == 2));
166     assert_err(
167         test,
168         "Condition failed: `if let 1 = 2 { }.t(1) == 2` (1 vs 2)",
169     );
170 
171     #[rustfmt::skip]
172     let test = || Ok(ensure!(if let 1 | 2 = 2 {}.t(1) == 2));
173     assert_err(
174         test,
175         "Condition failed: `if let 1 | 2 = 2 { }.t(1) == 2` (1 vs 2)",
176     );
177 
178     #[rustfmt::skip]
179     let test = || Ok(ensure!(if let | 1 | 2 = 2 {}.t(1) == 2));
180     assert_err(
181         test,
182         "Condition failed: `if let 1 | 2 = 2 { }.t(1) == 2` (1 vs 2)",
183     );
184 }
185 
186 #[test]
test_loop()187 fn test_loop() {
188     #[rustfmt::skip]
189     let test = || Ok(ensure!(1 + loop { break 1 } == 1));
190     assert_err(
191         test,
192         // 1.54 puts a double space after loop
193         "Condition failed: `1 + loop  { break 1  } == 1` (2 vs 1)\n\
194          Condition failed: `1 + loop { break 1  } == 1` (2 vs 1)",
195     );
196 
197     #[rustfmt::skip]
198     let test = || Ok(ensure!(1 + 'a: loop { break 'a 1 } == 1));
199     assert_err(
200         test,
201         // 1.54 puts a double space after loop
202         "Condition failed: `1 + 'a: loop  { break 'a 1  } == 1` (2 vs 1)\n\
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     #[derive(PartialOrd, PartialEq, Debug)]
328     enum E<'a, T> {
329         #[allow(dead_code)]
330         T(&'a T),
331         U,
332     }
333 
334     #[rustfmt::skip]
335     let test = || Ok(ensure!(E::U::<>>E::U::<u8>));
336     assert_err(test, "Condition failed: `E::U::<> > E::U::<u8>` (U vs U)");
337 
338     #[rustfmt::skip]
339     let test = || Ok(ensure!(E::U::<u8>>E::U));
340     assert_err(test, "Condition failed: `E::U::<u8> > E::U` (U vs U)");
341 
342     #[rustfmt::skip]
343     let test = || Ok(ensure!(E::U::<u8,>>E::U));
344     assert_err(test, "Condition failed: `E::U::<u8> > E::U` (U vs U)");
345 
346     let test = || Ok(ensure!(PhantomData::<dyn Debug + Sync> != PhantomData));
347     assert_err(
348         test,
349         "Condition failed: `PhantomData::<dyn Debug + Sync> != PhantomData` (PhantomData vs PhantomData)",
350     );
351 
352     let test = || Ok(ensure!(PhantomData::<dyn Fn() + Sync> != PhantomData));
353     assert_err(
354         test,
355         "Condition failed: `PhantomData::<dyn Fn() + Sync> != PhantomData` (PhantomData vs PhantomData)",
356     );
357 
358     #[rustfmt::skip]
359     let test = || {
360         Ok(ensure!(
361             PhantomData::<dyn Fn::() + ::std::marker::Sync> != PhantomData
362         ))
363     };
364     assert_err(
365         test,
366         "Condition failed: `PhantomData::<dyn Fn() + ::std::marker::Sync> != PhantomData` (PhantomData vs PhantomData)",
367     );
368 }
369 
370 #[test]
test_macro()371 fn test_macro() {
372     let test = || Ok(ensure!(anyhow!("...").to_string().len() <= 1));
373     assert_err(
374         test,
375         "Condition failed: `anyhow!(\"...\").to_string().len() <= 1` (3 vs 1)",
376     );
377 
378     let test = || Ok(ensure!(vec![1].len() < 1));
379     assert_err(test, "Condition failed: `vec![1].len() < 1` (1 vs 1)");
380 
381     let test = || Ok(ensure!(stringify! {} != ""));
382     assert_err(
383         test,
384         "Condition failed: `stringify! { } != \"\"` (\"\" vs \"\")",
385     );
386 }
387 
388 #[test]
test_trailer()389 fn test_trailer() {
390     let test = || Ok(ensure!((|| 1)() == 2));
391     assert_err(test, "Condition failed: `(|| 1)() == 2` (1 vs 2)");
392 
393     let test = || Ok(ensure!(b"hmm"[1] == b'c'));
394     assert_err(test, "Condition failed: `b\"hmm\"[1] == b'c'` (109 vs 99)");
395 
396     let test = || Ok(ensure!(PhantomData::<u8> {} != PhantomData));
397     assert_err(
398         test,
399         "Condition failed: `PhantomData::<u8>{} != PhantomData` (PhantomData vs PhantomData)",
400     );
401 
402     let result = Ok::<_, Error>(1);
403     let test = || Ok(ensure!(result? == 2));
404     assert_err(test, "Condition failed: `result? == 2` (1 vs 2)");
405 
406     let test = || Ok(ensure!((2, 3).1 == 2));
407     assert_err(test, "Condition failed: `(2, 3).1 == 2` (3 vs 2)");
408 
409     #[rustfmt::skip]
410     let test = || Ok(ensure!((2, (3, 4)). 1.1 == 2));
411     assert_err(test, "Condition failed: `(2, (3, 4)).1.1 == 2` (4 vs 2)");
412 
413     let err = anyhow!("");
414     let test = || Ok(ensure!(err.is::<&str>() == false));
415     assert_err(
416         test,
417         "Condition failed: `err.is::<&str>() == false` (true vs false)",
418     );
419 
420     let test = || Ok(ensure!(err.is::<<str as ToOwned>::Owned>() == true));
421     assert_err(
422         test,
423         "Condition failed: `err.is::<<str as ToOwned>::Owned>() == true` (false vs true)",
424     );
425 }
426 
427 #[test]
test_whitespace()428 fn test_whitespace() {
429     #[derive(Debug)]
430     pub struct Point {
431         pub x: i32,
432         pub y: i32,
433     }
434 
435     let point = Point { x: 0, y: 0 };
436     let test = || Ok(ensure!("" == format!("{:#?}", point)));
437     assert_err(
438         test,
439         "Condition failed: `\"\" == format!(\"{:#?}\", point)`",
440     );
441 }
442 
443 #[test]
test_too_long()444 fn test_too_long() {
445     let test = || Ok(ensure!("" == "x".repeat(10)));
446     assert_err(
447         test,
448         "Condition failed: `\"\" == \"x\".repeat(10)` (\"\" vs \"xxxxxxxxxx\")",
449     );
450 
451     let test = || Ok(ensure!("" == "x".repeat(80)));
452     assert_err(test, "Condition failed: `\"\" == \"x\".repeat(80)`");
453 }
454 
455 #[test]
test_as()456 fn test_as() {
457     let test = || Ok(ensure!('\0' as u8 > 1));
458     assert_err(test, "Condition failed: `'\\0' as u8 > 1` (0 vs 1)");
459 
460     let test = || Ok(ensure!('\0' as ::std::primitive::u8 > 1));
461     assert_err(
462         test,
463         "Condition failed: `'\\0' as ::std::primitive::u8 > 1` (0 vs 1)",
464     );
465 
466     let test = || Ok(ensure!(&[0] as &[i32] == [1]));
467     assert_err(
468         test,
469         "Condition failed: `&[0] as &[i32] == [1]` ([0] vs [1])",
470     );
471 
472     let test = || Ok(ensure!(0 as *const () as *mut _ == 1 as *mut ()));
473     assert_err(
474         test,
475         "Condition failed: `0 as *const () as *mut _ == 1 as *mut ()` (0x0 vs 0x1)",
476     );
477 
478     let s = "";
479     let test = || Ok(ensure!(s as &str != s));
480     assert_err(test, "Condition failed: `s as &str != s` (\"\" vs \"\")");
481 
482     let test = || Ok(ensure!(&s as &&str != &s));
483     assert_err(test, "Condition failed: `&s as &&str != &s` (\"\" vs \"\")");
484 
485     let test = || Ok(ensure!(s as &'static str != s));
486     assert_err(
487         test,
488         "Condition failed: `s as &'static str != s` (\"\" vs \"\")",
489     );
490 
491     let test = || Ok(ensure!(&s as &&'static str != &s));
492     assert_err(
493         test,
494         "Condition failed: `&s as &&'static str != &s` (\"\" vs \"\")",
495     );
496 
497     let m: &mut str = Default::default();
498     let test = || Ok(ensure!(m as &mut str != s));
499     assert_err(
500         test,
501         "Condition failed: `m as &mut str != s` (\"\" vs \"\")",
502     );
503 
504     let test = || Ok(ensure!(&m as &&mut str != &s));
505     assert_err(
506         test,
507         "Condition failed: `&m as &&mut str != &s` (\"\" vs \"\")",
508     );
509 
510     let test = || Ok(ensure!(&m as &&'static mut str != &s));
511     assert_err(
512         test,
513         "Condition failed: `&m as &&'static mut str != &s` (\"\" vs \"\")",
514     );
515 
516     let f = || {};
517     let test = || Ok(ensure!(f as fn() as usize * 0 != 0));
518     assert_err(
519         test,
520         "Condition failed: `f as fn() as usize * 0 != 0` (0 vs 0)",
521     );
522 
523     let test = || Ok(ensure!(f as fn() -> () as usize * 0 != 0));
524     assert_err(
525         test,
526         "Condition failed: `f as fn() -> () as usize * 0 != 0` (0 vs 0)",
527     );
528 
529     let test = || Ok(ensure!(f as for<'a> fn() as usize * 0 != 0));
530     assert_err(
531         test,
532         "Condition failed: `f as for<'a>fn() as usize * 0 != 0` (0 vs 0)",
533     );
534 
535     let test = || Ok(ensure!(f as unsafe fn() as usize * 0 != 0));
536     assert_err(
537         test,
538         "Condition failed: `f as unsafe fn() as usize * 0 != 0` (0 vs 0)",
539     );
540 
541     #[rustfmt::skip]
542     let test = || Ok(ensure!(f as extern "Rust" fn() as usize * 0 != 0));
543     assert_err(
544         test,
545         "Condition failed: `f as extern \"Rust\" fn() as usize * 0 != 0` (0 vs 0)",
546     );
547 
548     extern "C" fn extern_fn() {}
549     #[rustfmt::skip]
550     let test = || Ok(ensure!(extern_fn as extern fn() as usize * 0 != 0));
551     assert_err(
552         test,
553         "Condition failed: `extern_fn as extern fn() as usize * 0 != 0` (0 vs 0)",
554     );
555 
556     let f = || -> ! { panic!() };
557     let test = || Ok(ensure!(f as fn() -> ! as usize * 0 != 0));
558     assert_err(
559         test,
560         "Condition failed: `f as fn() -> ! as usize * 0 != 0` (0 vs 0)",
561     );
562 
563     trait EqDebug<T>: PartialEq<T> + Debug {
564         type Assoc;
565     }
566 
567     impl<S, T> EqDebug<T> for S
568     where
569         S: PartialEq<T> + Debug,
570     {
571         type Assoc = bool;
572     }
573 
574     let test = || Ok(ensure!(&0 as &dyn EqDebug<i32, Assoc = bool> != &0));
575     assert_err(
576         test,
577         "Condition failed: `&0 as &dyn EqDebug<i32, Assoc = bool> != &0` (0 vs 0)",
578     );
579 
580     let test = || {
581         Ok(ensure!(
582             PhantomData as PhantomData<<i32 as ToOwned>::Owned> != PhantomData
583         ))
584     };
585     assert_err(
586         test,
587         "Condition failed: `PhantomData as PhantomData<<i32 as ToOwned>::Owned> != PhantomData` (PhantomData vs PhantomData)",
588     );
589 
590     macro_rules! int {
591         (...) => {
592             u8
593         };
594     }
595 
596     let test = || Ok(ensure!(0 as int!(...) != 0));
597     assert_err(test, "Condition failed: `0 as int!(...) != 0` (0 vs 0)");
598 
599     let test = || Ok(ensure!(0 as int![...] != 0));
600     assert_err(test, "Condition failed: `0 as int![...] != 0` (0 vs 0)");
601 
602     let test = || Ok(ensure!(0 as int! {...} != 0));
603     assert_err(test, "Condition failed: `0 as int! { ... } != 0` (0 vs 0)");
604 }
605 
606 #[test]
test_pat()607 fn test_pat() {
608     let test = || Ok(ensure!(if let ref mut _x @ 0 = 0 { 0 } else { 1 } == 1));
609     assert_err(
610         test,
611         "Condition failed: `if let ref mut _x @ 0 = 0 { 0 } else { 1 } == 1` (0 vs 1)",
612     );
613 
614     let test = || Ok(ensure!(if let -1..=1 = 0 { 0 } else { 1 } == 1));
615     assert_err(
616         test,
617         "Condition failed: `if let -1 ..=1 = 0 { 0 } else { 1 } == 1` (0 vs 1)",
618     );
619 
620     let test = || Ok(ensure!(if let &0 = &0 { 0 } else { 1 } == 1));
621     assert_err(
622         test,
623         "Condition failed: `if let &0 = &0 { 0 } else { 1 } == 1` (0 vs 1)",
624     );
625 
626     let test = || Ok(ensure!(if let &&0 = &&0 { 0 } else { 1 } == 1));
627     assert_err(
628         test,
629         "Condition failed: `if let &&0 = &&0 { 0 } else { 1 } == 1` (0 vs 1)",
630     );
631 
632     let test = || Ok(ensure!(if let &mut 0 = &mut 0 { 0 } else { 1 } == 1));
633     assert_err(
634         test,
635         "Condition failed: `if let &mut 0 = &mut 0 { 0 } else { 1 } == 1` (0 vs 1)",
636     );
637 
638     let test = || Ok(ensure!(if let &&mut 0 = &&mut 0 { 0 } else { 1 } == 1));
639     assert_err(
640         test,
641         "Condition failed: `if let &&mut 0 = &&mut 0 { 0 } else { 1 } == 1` (0 vs 1)",
642     );
643 
644     let test = || Ok(ensure!(if let (0, 1) = (0, 1) { 0 } else { 1 } == 1));
645     assert_err(
646         test,
647         "Condition failed: `if let (0, 1) = (0, 1) { 0 } else { 1 } == 1` (0 vs 1)",
648     );
649 
650     let test = || Ok(ensure!(if let [0] = b"\0" { 0 } else { 1 } == 1));
651     assert_err(
652         test,
653         "Condition failed: `if let [0] = b\"\\0\" { 0 } else { 1 } == 1` (0 vs 1)",
654     );
655 
656     let p = PhantomData::<u8>;
657     let test = || Ok(ensure!(if let P::<u8> {} = p { 0 } else { 1 } == 1));
658     assert_err(
659         test,
660         "Condition failed: `if let P::<u8> {  } = p { 0 } else { 1 } == 1` (0 vs 1)",
661     );
662 
663     let test = || Ok(ensure!(if let ::std::marker::PhantomData = p {} != ()));
664     assert_err(
665         test,
666         "Condition failed: `if let ::std::marker::PhantomData = p { } != ()` (() vs ())",
667     );
668 
669     let test = || Ok(ensure!(if let <S as Trait>::V = 0 { 0 } else { 1 } == 1));
670     assert_err(
671         test,
672         "Condition failed: `if let <S as Trait>::V = 0 { 0 } else { 1 } == 1` (0 vs 1)",
673     );
674 
675     let test = || Ok(ensure!(for _ in iter::once(()) {} != ()));
676     assert_err(
677         test,
678         "Condition failed: `for _ in iter::once(()) { } != ()` (() vs ())",
679     );
680 
681     let test = || Ok(ensure!(if let stringify!(x) = "x" { 0 } else { 1 } == 1));
682     assert_err(
683         test,
684         "Condition failed: `if let stringify!(x) = \"x\" { 0 } else { 1 } == 1` (0 vs 1)",
685     );
686 }
687