]> git.proxmox.com Git - rustc.git/blame - src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / hir-ty / src / consteval / tests.rs
CommitLineData
fe692bf9
FG
1use base_db::{fixture::WithFixture, FileId};
2use chalk_ir::Substitution;
353b0b11 3use hir_def::db::DefDatabase;
add651ee 4use test_utils::skip_slow_tests;
064997fb 5
353b0b11 6use crate::{
fe692bf9 7 consteval::try_const_usize, db::HirDatabase, mir::pad16, test_db::TestDB, Const, ConstScalar,
add651ee 8 Interner, MemoryMap,
353b0b11 9};
064997fb 10
353b0b11
FG
11use super::{
12 super::mir::{MirEvalError, MirLowerError},
13 ConstEvalError,
14};
064997fb 15
fe692bf9
FG
16mod intrinsics;
17
353b0b11
FG
18fn simplify(e: ConstEvalError) -> ConstEvalError {
19 match e {
add651ee 20 ConstEvalError::MirEvalError(MirEvalError::InFunction(e, _)) => {
353b0b11
FG
21 simplify(ConstEvalError::MirEvalError(*e))
22 }
23 _ => e,
24 }
25}
26
27#[track_caller]
fe692bf9
FG
28fn check_fail(ra_fixture: &str, error: impl FnOnce(ConstEvalError) -> bool) {
29 let (db, file_id) = TestDB::with_single_file(ra_fixture);
30 match eval_goal(&db, file_id) {
31 Ok(_) => panic!("Expected fail, but it succeeded"),
32 Err(e) => {
33 assert!(error(simplify(e.clone())), "Actual error was: {}", pretty_print_err(e, db))
34 }
35 }
064997fb
FG
36}
37
353b0b11 38#[track_caller]
064997fb 39fn check_number(ra_fixture: &str, answer: i128) {
add651ee
FG
40 check_answer(ra_fixture, |b, _| {
41 assert_eq!(
42 b,
43 &answer.to_le_bytes()[0..b.len()],
44 "Bytes differ. In decimal form: actual = {}, expected = {answer}",
45 i128::from_le_bytes(pad16(b, true))
46 );
47 });
48}
49
50#[track_caller]
51fn check_str(ra_fixture: &str, answer: &str) {
52 check_answer(ra_fixture, |b, mm| {
53 let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap());
54 let size = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap());
55 let Some(bytes) = mm.get(addr, size) else {
56 panic!("string data missed in the memory map");
57 };
58 assert_eq!(
59 bytes,
60 answer.as_bytes(),
61 "Bytes differ. In string form: actual = {}, expected = {answer}",
62 String::from_utf8_lossy(bytes)
63 );
64 });
65}
66
67#[track_caller]
68fn check_answer(ra_fixture: &str, check: impl FnOnce(&[u8], &MemoryMap)) {
69 let (db, file_ids) = TestDB::with_many_files(ra_fixture);
70 let file_id = *file_ids.last().unwrap();
fe692bf9
FG
71 let r = match eval_goal(&db, file_id) {
72 Ok(t) => t,
73 Err(e) => {
74 let err = pretty_print_err(e, db);
75 panic!("Error in evaluating goal: {}", err);
76 }
77 };
353b0b11
FG
78 match &r.data(Interner).value {
79 chalk_ir::ConstValue::Concrete(c) => match &c.interned {
add651ee
FG
80 ConstScalar::Bytes(b, mm) => {
81 check(b, mm);
353b0b11
FG
82 }
83 x => panic!("Expected number but found {:?}", x),
84 },
85 _ => panic!("result of const eval wasn't a concrete const"),
064997fb
FG
86 }
87}
88
fe692bf9
FG
89fn pretty_print_err(e: ConstEvalError, db: TestDB) -> String {
90 let mut err = String::new();
91 let span_formatter = |file, range| format!("{:?} {:?}", file, range);
92 match e {
93 ConstEvalError::MirLowerError(e) => e.pretty_print(&mut err, &db, span_formatter),
94 ConstEvalError::MirEvalError(e) => e.pretty_print(&mut err, &db, span_formatter),
95 }
96 .unwrap();
97 err
98}
99
100fn eval_goal(db: &TestDB, file_id: FileId) -> Result<Const, ConstEvalError> {
064997fb 101 let module_id = db.module_for_file(file_id);
fe692bf9 102 let def_map = module_id.def_map(db);
064997fb
FG
103 let scope = &def_map[module_id.local_id].scope;
104 let const_id = scope
105 .declarations()
064997fb
FG
106 .find_map(|x| match x {
107 hir_def::ModuleDefId::ConstId(x) => {
fe692bf9 108 if db.const_data(x).name.as_ref()?.display(db).to_string() == "GOAL" {
064997fb
FG
109 Some(x)
110 } else {
111 None
112 }
113 }
114 _ => None,
115 })
add651ee
FG
116 .expect("No const named GOAL found in the test");
117 db.const_eval(const_id.into(), Substitution::empty(Interner), None)
064997fb
FG
118}
119
120#[test]
121fn add() {
122 check_number(r#"const GOAL: usize = 2 + 2;"#, 4);
353b0b11
FG
123 check_number(r#"const GOAL: i32 = -2 + --5;"#, 3);
124 check_number(r#"const GOAL: i32 = 7 - 5;"#, 2);
125 check_number(r#"const GOAL: i32 = 7 + (1 - 5);"#, 3);
064997fb
FG
126}
127
128#[test]
129fn bit_op() {
130 check_number(r#"const GOAL: u8 = !0 & !(!0 >> 1)"#, 128);
131 check_number(r#"const GOAL: i8 = !0 & !(!0 >> 1)"#, 0);
353b0b11 132 check_number(r#"const GOAL: i8 = 1 << 7"#, (1i8 << 7) as i128);
fe692bf9
FG
133 check_number(r#"const GOAL: i8 = -1 << 2"#, (-1i8 << 2) as i128);
134 check_fail(r#"const GOAL: i8 = 1 << 8"#, |e| {
135 e == ConstEvalError::MirEvalError(MirEvalError::Panic("Overflow in Shl".to_string()))
136 });
add651ee 137 check_number(r#"const GOAL: i32 = 100000000i32 << 11"#, (100000000i32 << 11) as i128);
fe692bf9
FG
138}
139
140#[test]
141fn floating_point() {
142 check_number(
143 r#"const GOAL: f64 = 2.0 + 3.0 * 5.5 - 8.;"#,
144 i128::from_le_bytes(pad16(&f64::to_le_bytes(10.5), true)),
145 );
146 check_number(
147 r#"const GOAL: f32 = 2.0 + 3.0 * 5.5 - 8.;"#,
148 i128::from_le_bytes(pad16(&f32::to_le_bytes(10.5), true)),
149 );
150 check_number(
151 r#"const GOAL: f32 = -90.0 + 36.0;"#,
152 i128::from_le_bytes(pad16(&f32::to_le_bytes(-54.0), true)),
153 );
154}
155
156#[test]
157fn casts() {
158 check_number(r#"const GOAL: usize = 12 as *const i32 as usize"#, 12);
159 check_number(
160 r#"
161 //- minicore: coerce_unsized, index, slice
162 const GOAL: i32 = {
163 let a = [10, 20, 3, 15];
164 let x: &[i32] = &a;
165 let y: *const [i32] = x;
166 let z = y as *const i32;
167 unsafe { *z }
168 };
169 "#,
170 10,
171 );
172 check_number(
173 r#"
174 //- minicore: coerce_unsized, index, slice
175 const GOAL: i16 = {
176 let a = &mut 5;
177 let z = a as *mut _;
178 unsafe { *z }
179 };
180 "#,
181 5,
182 );
183 check_number(
184 r#"
185 //- minicore: coerce_unsized, index, slice
186 const GOAL: usize = {
187 let a = &[10, 20, 30, 40] as &[i32];
188 a.len()
189 };
190 "#,
191 4,
192 );
193 check_number(
194 r#"
195 //- minicore: coerce_unsized, index, slice
add651ee
FG
196 struct X {
197 unsize_field: [u8],
198 }
199
fe692bf9
FG
200 const GOAL: usize = {
201 let a = [10, 20, 3, 15];
202 let x: &[i32] = &a;
add651ee
FG
203 let x: *const [i32] = x;
204 let x = x as *const [u8]; // slice fat pointer cast don't touch metadata
205 let x = x as *const str;
206 let x = x as *const X;
207 let x = x as *const [i16];
208 let x = x as *const X;
209 let x = x as *const [u8];
210 let w = unsafe { &*x };
fe692bf9
FG
211 w.len()
212 };
213 "#,
214 4,
215 );
216 check_number(r#"const GOAL: i32 = -12i8 as i32"#, -12);
217}
218
219#[test]
220fn raw_pointer_equality() {
221 check_number(
222 r#"
223 //- minicore: copy, eq
224 const GOAL: bool = {
225 let a = 2;
226 let p1 = a as *const i32;
227 let p2 = a as *const i32;
228 p1 == p2
229 };
230 "#,
231 1,
232 );
064997fb
FG
233}
234
add651ee
FG
235#[test]
236fn alignment() {
237 check_answer(
238 r#"
239//- minicore: transmute
240use core::mem::transmute;
241const GOAL: usize = {
242 let x: i64 = 2;
243 transmute(&x)
244}
245 "#,
246 |b, _| assert_eq!(b[0] % 8, 0),
247 );
248 check_answer(
249 r#"
250//- minicore: transmute
251use core::mem::transmute;
252static X: i64 = 12;
253const GOAL: usize = transmute(&X);
254 "#,
255 |b, _| assert_eq!(b[0] % 8, 0),
256 );
257}
258
064997fb
FG
259#[test]
260fn locals() {
261 check_number(
262 r#"
263 const GOAL: usize = {
264 let a = 3 + 2;
265 let b = a * a;
266 b
267 };
268 "#,
269 25,
270 );
271}
272
353b0b11
FG
273#[test]
274fn references() {
275 check_number(
276 r#"
277 const GOAL: usize = {
278 let x = 3;
279 let y = &mut x;
280 *y = 5;
281 x
282 };
283 "#,
284 5,
285 );
286 check_number(
287 r#"
288 struct Foo(i32);
289 impl Foo {
290 fn method(&mut self, x: i32) {
291 self.0 = 2 * self.0 + x;
292 }
293 }
294 const GOAL: i32 = {
295 let mut x = Foo(3);
296 x.method(5);
297 x.0
298 };
299 "#,
300 11,
301 );
302}
303
304#[test]
305fn reference_autoderef() {
306 check_number(
307 r#"
308 const GOAL: usize = {
309 let x = 3;
310 let y = &mut x;
311 let y: &mut usize = &mut y;
312 *y = 5;
313 x
314 };
315 "#,
316 5,
317 );
318 check_number(
319 r#"
320 const GOAL: usize = {
321 let x = 3;
322 let y = &&&&&&&x;
323 let z: &usize = &y;
324 *z
325 };
326 "#,
327 3,
328 );
329 check_number(
330 r#"
331 struct Foo<T> { x: T }
332 impl<T> Foo<T> {
333 fn foo(&mut self) -> T { self.x }
334 }
335 fn f(i: &mut &mut Foo<Foo<i32>>) -> i32 {
336 ((**i).x).foo()
337 }
338 fn g(i: Foo<Foo<i32>>) -> i32 {
339 i.x.foo()
340 }
341 const GOAL: i32 = f(&mut &mut Foo { x: Foo { x: 3 } }) + g(Foo { x: Foo { x: 5 } });
342 "#,
343 8,
344 );
345}
346
347#[test]
348fn overloaded_deref() {
fe692bf9 349 check_number(
353b0b11
FG
350 r#"
351 //- minicore: deref_mut
352 struct Foo;
353
354 impl core::ops::Deref for Foo {
355 type Target = i32;
356 fn deref(&self) -> &i32 {
357 &5
358 }
359 }
360
361 const GOAL: i32 = {
362 let x = Foo;
363 let y = &*x;
364 *y + *x
365 };
366 "#,
fe692bf9 367 10,
353b0b11
FG
368 );
369}
370
371#[test]
372fn overloaded_deref_autoref() {
373 check_number(
374 r#"
375 //- minicore: deref_mut
376 struct Foo;
377 struct Bar;
378
379 impl core::ops::Deref for Foo {
380 type Target = Bar;
381 fn deref(&self) -> &Bar {
382 &Bar
383 }
384 }
385
386 impl Bar {
387 fn method(&self) -> i32 {
388 5
389 }
390 }
391
392 const GOAL: i32 = Foo.method();
393 "#,
394 5,
395 );
396}
397
fe692bf9
FG
398#[test]
399fn overloaded_index() {
400 check_number(
401 r#"
402 //- minicore: index
403 struct Foo;
404
405 impl core::ops::Index<usize> for Foo {
406 type Output = i32;
407 fn index(&self, index: usize) -> &i32 {
408 if index == 7 {
409 &700
410 } else {
411 &1000
412 }
413 }
414 }
415
416 impl core::ops::IndexMut<usize> for Foo {
417 fn index_mut(&mut self, index: usize) -> &mut i32 {
418 if index == 7 {
419 &mut 7
420 } else {
421 &mut 10
422 }
423 }
424 }
425
426 const GOAL: i32 = {
427 (Foo[2]) + (Foo[7]) + (*&Foo[2]) + (*&Foo[7]) + (*&mut Foo[2]) + (*&mut Foo[7])
428 };
429 "#,
430 3417,
431 );
432}
433
434#[test]
435fn overloaded_binop() {
436 check_number(
437 r#"
438 //- minicore: add
439 enum Color {
440 Red,
441 Green,
442 Yellow,
443 }
444
445 use Color::*;
446
447 impl core::ops::Add for Color {
448 type Output = Color;
449 fn add(self, rhs: Color) -> Self::Output {
450 Yellow
451 }
452 }
453
454 impl core::ops::AddAssign for Color {
455 fn add_assign(&mut self, rhs: Color) {
456 *self = Red;
457 }
458 }
459
460 const GOAL: bool = {
461 let x = Red + Green;
462 let mut y = Green;
463 y += x;
464 x == Yellow && y == Red && Red + Green == Yellow && Red + Red == Yellow && Yellow + Green == Yellow
465 };
466 "#,
467 1,
468 );
469 check_number(
470 r#"
471 //- minicore: add
472 impl core::ops::Add for usize {
473 type Output = usize;
474 fn add(self, rhs: usize) -> Self::Output {
475 self + rhs
476 }
477 }
478
479 impl core::ops::AddAssign for usize {
480 fn add_assign(&mut self, rhs: usize) {
481 *self += rhs;
482 }
483 }
484
485 #[lang = "shl"]
486 pub trait Shl<Rhs = Self> {
487 type Output;
488
489 fn shl(self, rhs: Rhs) -> Self::Output;
490 }
491
492 impl Shl<u8> for usize {
493 type Output = usize;
494
495 fn shl(self, rhs: u8) -> Self::Output {
496 self << rhs
497 }
498 }
499
500 const GOAL: usize = {
501 let mut x = 10;
502 x += 20;
503 2 + 2 + (x << 1u8)
504 };"#,
505 64,
506 );
507}
508
353b0b11
FG
509#[test]
510fn function_call() {
511 check_number(
512 r#"
513 const fn f(x: usize) -> usize {
514 2 * x + 5
515 }
516 const GOAL: usize = f(3);
517 "#,
518 11,
519 );
520 check_number(
521 r#"
522 const fn add(x: usize, y: usize) -> usize {
523 x + y
524 }
525 const GOAL: usize = add(add(1, 2), add(3, add(4, 5)));
526 "#,
527 15,
528 );
529}
530
353b0b11
FG
531#[test]
532fn trait_basic() {
533 check_number(
534 r#"
535 trait Foo {
536 fn f(&self) -> u8;
537 }
538
539 impl Foo for u8 {
540 fn f(&self) -> u8 {
541 *self + 33
542 }
543 }
544
545 const GOAL: u8 = {
546 let x = 3;
547 Foo::f(&x)
548 };
549 "#,
550 36,
551 );
552}
553
554#[test]
555fn trait_method() {
556 check_number(
557 r#"
558 trait Foo {
559 fn f(&self) -> u8;
560 }
561
562 impl Foo for u8 {
563 fn f(&self) -> u8 {
564 *self + 33
565 }
566 }
567
568 const GOAL: u8 = {
569 let x = 3;
570 x.f()
571 };
572 "#,
573 36,
574 );
575}
576
fe692bf9
FG
577#[test]
578fn trait_method_inside_block() {
579 check_number(
580 r#"
581trait Twait {
582 fn a(&self) -> i32;
583}
584
585fn outer() -> impl Twait {
586 struct Stwuct;
587
588 impl Twait for Stwuct {
589 fn a(&self) -> i32 {
590 5
591 }
592 }
593 fn f() -> impl Twait {
594 let s = Stwuct;
595 s
596 }
597 f()
598}
599
600const GOAL: i32 = outer().a();
601 "#,
602 5,
603 );
604}
605
353b0b11
FG
606#[test]
607fn generic_fn() {
608 check_number(
609 r#"
610 trait Foo {
611 fn f(&self) -> u8;
612 }
613
614 impl Foo for () {
615 fn f(&self) -> u8 {
616 0
617 }
618 }
619
620 struct Succ<S>(S);
621
622 impl<T: Foo> Foo for Succ<T> {
623 fn f(&self) -> u8 {
624 self.0.f() + 1
625 }
626 }
627
628 const GOAL: u8 = Succ(Succ(())).f();
629 "#,
630 2,
631 );
632 check_number(
633 r#"
634 trait Foo {
635 fn f(&self) -> u8;
636 }
637
638 impl Foo for u8 {
639 fn f(&self) -> u8 {
640 *self + 33
641 }
642 }
643
644 fn foof<T: Foo>(x: T, y: T) -> u8 {
645 x.f() + y.f()
646 }
647
648 const GOAL: u8 = foof(2, 5);
649 "#,
650 73,
651 );
652 check_number(
653 r#"
654 fn bar<A, B>(a: A, b: B) -> B {
655 b
656 }
657 const GOAL: u8 = bar("hello", 12);
658 "#,
659 12,
660 );
fe692bf9
FG
661 check_number(
662 r#"
663 const fn y<T>(b: T) -> (T, ) {
664 let alloc = b;
665 (alloc, )
666 }
667 const GOAL: u8 = y(2).0;
668 "#,
669 2,
670 );
353b0b11
FG
671 check_number(
672 r#"
673 //- minicore: coerce_unsized, index, slice
674 fn bar<A, B>(a: A, b: B) -> B {
675 b
676 }
677 fn foo<T>(x: [T; 2]) -> T {
678 bar(x[0], x[1])
679 }
680
681 const GOAL: u8 = foo([2, 5]);
682 "#,
683 5,
684 );
685}
686
687#[test]
688fn impl_trait() {
689 check_number(
690 r#"
691 trait Foo {
692 fn f(&self) -> u8;
693 }
694
695 impl Foo for u8 {
696 fn f(&self) -> u8 {
697 *self + 33
698 }
699 }
700
701 fn foof(x: impl Foo, y: impl Foo) -> impl Foo {
702 x.f() + y.f()
703 }
704
705 const GOAL: u8 = foof(2, 5).f();
706 "#,
707 106,
708 );
709 check_number(
710 r#"
711 struct Foo<T>(T, T, (T, T));
712 trait S {
713 fn sum(&self) -> i64;
714 }
715 impl S for i64 {
716 fn sum(&self) -> i64 {
717 *self
718 }
719 }
720 impl<T: S> S for Foo<T> {
721 fn sum(&self) -> i64 {
722 self.0.sum() + self.1.sum() + self.2 .0.sum() + self.2 .1.sum()
723 }
724 }
725
726 fn foo() -> Foo<impl S> {
727 Foo(
728 Foo(1i64, 2, (3, 4)),
729 Foo(5, 6, (7, 8)),
730 (
731 Foo(9, 10, (11, 12)),
732 Foo(13, 14, (15, 16)),
733 ),
734 )
735 }
736 const GOAL: i64 = foo().sum();
737 "#,
738 136,
739 );
740}
741
742#[test]
743fn ifs() {
744 check_number(
745 r#"
746 const fn f(b: bool) -> u8 {
747 if b { 1 } else { 10 }
748 }
749
750 const GOAL: u8 = f(true) + f(true) + f(false);
751 "#,
752 12,
753 );
754 check_number(
755 r#"
756 const fn max(a: i32, b: i32) -> i32 {
757 if a < b { b } else { a }
758 }
759
760 const GOAL: i32 = max(max(1, max(10, 3)), 0-122);
761 "#,
762 10,
763 );
764
765 check_number(
766 r#"
767 const fn max(a: &i32, b: &i32) -> &i32 {
768 if *a < *b { b } else { a }
769 }
770
771 const GOAL: i32 = *max(max(&1, max(&10, &3)), &5);
772 "#,
773 10,
774 );
775}
776
777#[test]
778fn loops() {
779 check_number(
780 r#"
781 const GOAL: u8 = {
782 let mut x = 0;
783 loop {
784 x = x + 1;
785 while true {
786 break;
787 }
788 x = x + 1;
789 if x == 2 {
790 continue;
791 }
792 break;
793 }
794 x
795 };
796 "#,
797 4,
798 );
fe692bf9
FG
799 check_number(
800 r#"
801 const GOAL: u8 = {
802 let mut x = 0;
803 loop {
804 x = x + 1;
805 if x == 5 {
806 break x + 2;
807 }
808 }
809 };
810 "#,
811 7,
812 );
813 check_number(
814 r#"
815 const GOAL: u8 = {
816 'a: loop {
817 let x = 'b: loop {
818 let x = 'c: loop {
819 let x = 'd: loop {
820 let x = 'e: loop {
821 break 'd 1;
822 };
823 break 2 + x;
824 };
825 break 3 + x;
826 };
827 break 'a 4 + x;
828 };
829 break 5 + x;
830 }
831 };
832 "#,
833 8,
834 );
835 check_number(
836 r#"
837 //- minicore: add
838 const GOAL: u8 = {
839 let mut x = 0;
840 'a: loop {
841 'b: loop {
842 'c: while x < 20 {
843 'd: while x < 5 {
844 'e: loop {
845 x += 1;
846 continue 'c;
847 };
848 };
849 x += 1;
850 };
851 break 'a;
852 };
853 }
854 x
855 };
856 "#,
857 20,
858 );
353b0b11
FG
859}
860
861#[test]
862fn for_loops() {
863 check_number(
864 r#"
865 //- minicore: iterator
866
867 struct Range {
868 start: u8,
869 end: u8,
870 }
871
872 impl Iterator for Range {
873 type Item = u8;
874 fn next(&mut self) -> Option<u8> {
875 if self.start >= self.end {
876 None
877 } else {
878 let r = self.start;
879 self.start = self.start + 1;
880 Some(r)
881 }
882 }
883 }
884
885 const GOAL: u8 = {
886 let mut sum = 0;
887 let ar = Range { start: 1, end: 11 };
888 for i in ar {
889 sum = sum + i;
890 }
891 sum
892 };
893 "#,
894 55,
895 );
896}
897
fe692bf9
FG
898#[test]
899fn ranges() {
900 check_number(
901 r#"
902 //- minicore: range
903 const GOAL: i32 = (1..2).start + (20..10).end + (100..=200).start + (2000..=1000).end
904 + (10000..).start + (..100000).end + (..=1000000).end;
905 "#,
906 1111111,
907 );
908}
909
353b0b11
FG
910#[test]
911fn recursion() {
912 check_number(
913 r#"
914 const fn fact(k: i32) -> i32 {
915 if k > 0 { fact(k - 1) * k } else { 1 }
916 }
917
918 const GOAL: i32 = fact(5);
919 "#,
920 120,
921 );
922}
923
924#[test]
925fn structs() {
926 check_number(
927 r#"
928 struct Point {
929 x: i32,
930 y: i32,
931 }
932
933 const GOAL: i32 = {
934 let p = Point { x: 5, y: 2 };
935 let y = 1;
936 let x = 3;
937 let q = Point { y, x };
938 p.x + p.y + p.x + q.y + q.y + q.x
939 };
940 "#,
941 17,
942 );
fe692bf9
FG
943 check_number(
944 r#"
945 struct Point {
946 x: i32,
947 y: i32,
948 }
949
950 const GOAL: i32 = {
951 let p = Point { x: 5, y: 2 };
952 let p2 = Point { x: 3, ..p };
953 p.x * 1000 + p.y * 100 + p2.x * 10 + p2.y
954 };
955 "#,
956 5232,
957 );
958 check_number(
959 r#"
960 struct Point {
961 x: i32,
962 y: i32,
963 }
964
965 const GOAL: i32 = {
966 let p = Point { x: 5, y: 2 };
967 let Point { x, y } = p;
968 let Point { x: x2, .. } = p;
969 let Point { y: y2, .. } = p;
970 x * 1000 + y * 100 + x2 * 10 + y2
971 };
972 "#,
973 5252,
974 );
353b0b11
FG
975}
976
977#[test]
978fn unions() {
979 check_number(
980 r#"
981 union U {
982 f1: i64,
983 f2: (i32, i32),
984 }
985
986 const GOAL: i32 = {
987 let p = U { f1: 0x0123ABCD0123DCBA };
988 let p = unsafe { p.f2 };
989 p.0 + p.1 + p.1
990 };
991 "#,
992 0x0123ABCD * 2 + 0x0123DCBA,
993 );
994}
995
996#[test]
997fn tuples() {
998 check_number(
999 r#"
1000 const GOAL: u8 = {
1001 let a = (10, 20, 3, 15);
1002 a.1
1003 };
1004 "#,
1005 20,
1006 );
1007 check_number(
1008 r#"
1009 const GOAL: u8 = {
1010 let mut a = (10, 20, 3, 15);
1011 a.1 = 2;
1012 a.0 + a.1 + a.2 + a.3
1013 };
1014 "#,
1015 30,
1016 );
1017 check_number(
1018 r#"
fe692bf9
FG
1019 struct TupleLike(i32, i64, u8, u16);
1020 const GOAL: i64 = {
353b0b11 1021 let a = TupleLike(10, 20, 3, 15);
fe692bf9
FG
1022 let TupleLike(b, .., c) = a;
1023 a.1 * 100 + b as i64 + c as i64
353b0b11
FG
1024 };
1025 "#,
fe692bf9 1026 2025,
353b0b11
FG
1027 );
1028 check_number(
1029 r#"
1030 const GOAL: u8 = {
1031 match (&(2 + 2), &4) {
1032 (left_val, right_val) => {
1033 if !(*left_val == *right_val) {
1034 2
1035 } else {
1036 5
1037 }
1038 }
1039 }
1040 };
1041 "#,
1042 5,
1043 );
1044}
1045
1046#[test]
1047fn path_pattern_matching() {
1048 check_number(
1049 r#"
1050 enum Season {
1051 Spring,
1052 Summer,
1053 Fall,
1054 Winter,
1055 }
1056
1057 use Season::*;
1058
fe692bf9
FG
1059 const MY_SEASON: Season = Summer;
1060
1061 impl Season {
1062 const FALL: Season = Fall;
1063 }
1064
353b0b11
FG
1065 const fn f(x: Season) -> i32 {
1066 match x {
1067 Spring => 1,
fe692bf9
FG
1068 MY_SEASON => 2,
1069 Season::FALL => 3,
353b0b11
FG
1070 Winter => 4,
1071 }
1072 }
1073 const GOAL: i32 = f(Spring) + 10 * f(Summer) + 100 * f(Fall) + 1000 * f(Winter);
1074 "#,
1075 4321,
1076 );
1077}
1078
1079#[test]
fe692bf9 1080fn pattern_matching_literal() {
353b0b11
FG
1081 check_number(
1082 r#"
fe692bf9 1083 const fn f(x: i32) -> i32 {
353b0b11 1084 match x {
fe692bf9
FG
1085 -1 => 1,
1086 1 => 10,
1087 _ => 100,
353b0b11
FG
1088 }
1089 }
fe692bf9 1090 const GOAL: i32 = f(-1) + f(1) + f(0) + f(-5);
353b0b11 1091 "#,
fe692bf9 1092 211,
353b0b11 1093 );
353b0b11
FG
1094 check_number(
1095 r#"
fe692bf9
FG
1096 const fn f(x: &str) -> i32 {
1097 match x {
1098 "f" => 1,
1099 "foo" => 10,
1100 "" => 100,
1101 "bar" => 1000,
1102 _ => 10000,
1103 }
353b0b11 1104 }
fe692bf9 1105 const GOAL: i32 = f("f") + f("foo") * 2 + f("") * 3 + f("bar") * 4;
353b0b11 1106 "#,
fe692bf9 1107 4321,
353b0b11 1108 );
fe692bf9
FG
1109}
1110
1111#[test]
1112fn pattern_matching_range() {
353b0b11
FG
1113 check_number(
1114 r#"
fe692bf9
FG
1115 pub const L: i32 = 6;
1116 mod x {
1117 pub const R: i32 = 100;
353b0b11 1118 }
fe692bf9
FG
1119 const fn f(x: i32) -> i32 {
1120 match x {
1121 -1..=5 => x * 10,
1122 L..=x::R => x * 100,
1123 _ => x,
1124 }
353b0b11 1125 }
fe692bf9
FG
1126 const GOAL: i32 = f(-1) + f(2) + f(100) + f(-2) + f(1000);
1127 "#,
1128 11008,
1129 );
1130}
1131
1132#[test]
1133fn pattern_matching_slice() {
1134 check_number(
1135 r#"
1136 //- minicore: slice, index, coerce_unsized, copy
1137 const fn f(x: &[usize]) -> usize {
1138 match x {
1139 [a, b @ .., c, d] => *a + b.len() + *c + *d,
1140 }
1141 }
1142 const GOAL: usize = f(&[10, 20, 3, 15, 1000, 60, 16]);
1143 "#,
1144 10 + 4 + 60 + 16,
1145 );
1146 check_number(
1147 r#"
1148 //- minicore: slice, index, coerce_unsized, copy
1149 const fn f(x: &[usize]) -> usize {
1150 match x {
1151 [] => 0,
1152 [a] => *a,
1153 &[a, b] => a + b,
1154 [a, b @ .., c, d] => *a + b.len() + *c + *d,
1155 }
1156 }
1157 const GOAL: usize = f(&[]) + f(&[10]) + f(&[100, 100])
1158 + f(&[1000, 1000, 1000]) + f(&[10000, 57, 34, 46, 10000, 10000]);
1159 "#,
1160 33213,
1161 );
1162}
1163
1164#[test]
1165fn pattern_matching_ergonomics() {
1166 check_number(
1167 r#"
1168 const fn f(x: &(u8, u8)) -> u8 {
1169 match x {
1170 (a, b) => *a + *b
1171 }
1172 }
1173 const GOAL: u8 = f(&(2, 3));
1174 "#,
1175 5,
1176 );
1177 check_number(
1178 r#"
1179 const GOAL: u8 = {
1180 let a = &(2, 3);
1181 let &(x, y) = a;
1182 x + y
1183 };
1184 "#,
1185 5,
1186 );
1187}
1188
add651ee
FG
1189#[test]
1190fn destructing_assignment() {
1191 check_number(
1192 r#"
1193 //- minicore: add
1194 const fn f(i: &mut u8) -> &mut u8 {
1195 *i += 1;
1196 i
1197 }
1198 const GOAL: u8 = {
1199 let mut i = 4;
1200 _ = f(&mut i);
1201 i
1202 };
1203 "#,
1204 5,
1205 );
781aab86
FG
1206 check_number(
1207 r#"
1208 const GOAL: u8 = {
1209 let (mut a, mut b) = (2, 5);
1210 (a, b) = (b, a);
1211 a * 10 + b
1212 };
1213 "#,
1214 52,
1215 );
1216 check_number(
1217 r#"
1218 struct Point { x: i32, y: i32 }
1219 const GOAL: i32 = {
1220 let mut p = Point { x: 5, y: 6 };
1221 (p.x, _) = (p.y, p.x);
1222 p.x * 10 + p.y
1223 };
1224 "#,
1225 66,
1226 );
add651ee
FG
1227}
1228
fe692bf9
FG
1229#[test]
1230fn let_else() {
1231 check_number(
1232 r#"
1233 const fn f(x: &(u8, u8)) -> u8 {
1234 let (a, b) = x;
1235 *a + *b
1236 }
1237 const GOAL: u8 = f(&(2, 3));
1238 "#,
1239 5,
1240 );
1241 check_number(
1242 r#"
1243 enum SingleVariant {
1244 Var(u8, u8),
1245 }
1246 const fn f(x: &&&&&SingleVariant) -> u8 {
1247 let SingleVariant::Var(a, b) = x;
1248 *a + *b
1249 }
1250 const GOAL: u8 = f(&&&&&SingleVariant::Var(2, 3));
353b0b11
FG
1251 "#,
1252 5,
1253 );
1254 check_number(
1255 r#"
1256 //- minicore: option
1257 const fn f(x: Option<i32>) -> i32 {
1258 let Some(x) = x else { return 10 };
1259 2 * x
1260 }
1261 const GOAL: i32 = f(Some(1000)) + f(None);
1262 "#,
1263 2010,
1264 );
1265}
1266
1267#[test]
1268fn function_param_patterns() {
1269 check_number(
1270 r#"
1271 const fn f((a, b): &(u8, u8)) -> u8 {
1272 *a + *b
1273 }
1274 const GOAL: u8 = f(&(2, 3));
1275 "#,
1276 5,
1277 );
1278 check_number(
1279 r#"
1280 const fn f(c @ (a, b): &(u8, u8)) -> u8 {
1281 *a + *b + c.0 + (*c).1
1282 }
1283 const GOAL: u8 = f(&(2, 3));
1284 "#,
1285 10,
1286 );
1287 check_number(
1288 r#"
1289 const fn f(ref a: u8) -> u8 {
1290 *a
1291 }
1292 const GOAL: u8 = f(2);
1293 "#,
1294 2,
1295 );
1296 check_number(
1297 r#"
1298 struct Foo(u8);
1299 impl Foo {
1300 const fn f(&self, (a, b): &(u8, u8)) -> u8 {
1301 self.0 + *a + *b
1302 }
1303 }
1304 const GOAL: u8 = Foo(4).f(&(2, 3));
1305 "#,
1306 9,
1307 );
1308}
1309
fe692bf9
FG
1310#[test]
1311fn match_guards() {
1312 check_number(
1313 r#"
1314 //- minicore: option
1315 fn f(x: Option<i32>) -> i32 {
1316 match x {
1317 y if let Some(42) = y => 42000,
1318 Some(y) => y,
1319 None => 10
1320 }
1321 }
1322 const GOAL: i32 = f(Some(42)) + f(Some(2)) + f(None);
1323 "#,
1324 42012,
1325 );
1326}
1327
1328#[test]
1329fn result_layout_niche_optimization() {
1330 check_number(
1331 r#"
1332 //- minicore: option, result
1333 const GOAL: i32 = match Some(2).ok_or(Some(2)) {
1334 Ok(x) => x,
1335 Err(_) => 1000,
1336 };
1337 "#,
1338 2,
1339 );
1340 check_number(
1341 r#"
1342 //- minicore: result
1343 pub enum AlignmentEnum64 {
1344 _Align1Shl0 = 1 << 0,
1345 _Align1Shl1 = 1 << 1,
1346 _Align1Shl2 = 1 << 2,
1347 _Align1Shl3 = 1 << 3,
1348 _Align1Shl4 = 1 << 4,
1349 _Align1Shl5 = 1 << 5,
1350 }
1351 const GOAL: Result<AlignmentEnum64, ()> = {
1352 let align = Err(());
1353 align
1354 };
1355 "#,
1356 0, // It is 0 since result is niche encoded and 1 is valid for `AlignmentEnum64`
1357 );
1358 check_number(
1359 r#"
1360 //- minicore: result
1361 pub enum AlignmentEnum64 {
1362 _Align1Shl0 = 1 << 0,
1363 _Align1Shl1 = 1 << 1,
1364 _Align1Shl2 = 1 << 2,
1365 _Align1Shl3 = 1 << 3,
1366 _Align1Shl4 = 1 << 4,
1367 _Align1Shl5 = 1 << 5,
1368 }
1369 const GOAL: i32 = {
1370 let align = Ok::<_, ()>(AlignmentEnum64::_Align1Shl0);
1371 match align {
1372 Ok(_) => 2,
1373 Err(_) => 1,
1374 }
1375 };
1376 "#,
1377 2,
1378 );
1379}
1380
353b0b11
FG
1381#[test]
1382fn options() {
1383 check_number(
1384 r#"
1385 //- minicore: option
1386 const GOAL: u8 = {
1387 let x = Some(2);
1388 match x {
1389 Some(y) => 2 * y,
1390 _ => 10,
1391 }
1392 };
1393 "#,
fe692bf9
FG
1394 4,
1395 );
1396 check_number(
1397 r#"
1398 //- minicore: option
1399 fn f(x: Option<Option<i32>>) -> i32 {
1400 if let Some(y) = x && let Some(z) = y {
1401 z
1402 } else if let Some(y) = x {
1403 1
1404 } else {
1405 0
1406 }
1407 }
1408 const GOAL: i32 = f(Some(Some(10))) + f(Some(None)) + f(None);
1409 "#,
1410 11,
1411 );
1412 check_number(
1413 r#"
1414 //- minicore: option
1415 const GOAL: u8 = {
1416 let x = None;
1417 match x {
1418 Some(y) => 2 * y,
1419 _ => 10,
1420 }
1421 };
1422 "#,
1423 10,
1424 );
1425 check_number(
1426 r#"
1427 //- minicore: option
1428 const GOAL: Option<&u8> = None;
1429 "#,
1430 0,
1431 );
1432}
1433
1434#[test]
1435fn from_trait() {
1436 check_number(
1437 r#"
1438 //- minicore: from
1439 struct E1(i32);
1440 struct E2(i32);
1441
1442 impl From<E1> for E2 {
1443 fn from(E1(x): E1) -> Self {
1444 E2(1000 * x)
1445 }
1446 }
1447 const GOAL: i32 = {
1448 let x: E2 = E1(2).into();
1449 x.0
1450 };
1451 "#,
1452 2000,
1453 );
1454}
1455
781aab86
FG
1456#[test]
1457fn closure_clone() {
1458 check_number(
1459 r#"
1460//- minicore: clone, fn
1461struct S(u8);
1462
1463impl Clone for S(u8) {
1464 fn clone(&self) -> S {
1465 S(self.0 + 5)
1466 }
1467}
1468
1469const GOAL: u8 = {
1470 let s = S(3);
1471 let cl = move || s;
1472 let cl = cl.clone();
1473 cl().0
1474}
1475 "#,
1476 8,
1477 );
1478}
1479
fe692bf9
FG
1480#[test]
1481fn builtin_derive_macro() {
1482 check_number(
1483 r#"
1484 //- minicore: clone, derive, builtin_impls
1485 #[derive(Clone)]
1486 enum Z {
1487 Foo(Y),
1488 Bar,
1489 }
1490 #[derive(Clone)]
1491 struct X(i32, Z, i64)
1492 #[derive(Clone)]
1493 struct Y {
1494 field1: i32,
add651ee 1495 field2: ((i32, u8), i64),
fe692bf9
FG
1496 }
1497
1498 const GOAL: u8 = {
add651ee 1499 let x = X(2, Z::Foo(Y { field1: 4, field2: ((32, 5), 12) }), 8);
fe692bf9
FG
1500 let x = x.clone();
1501 let Z::Foo(t) = x.1;
add651ee 1502 t.field2.0 .1
fe692bf9
FG
1503 };
1504 "#,
1505 5,
1506 );
1507 check_number(
1508 r#"
1509 //- minicore: default, derive, builtin_impls
1510 #[derive(Default)]
1511 struct X(i32, Y, i64)
1512 #[derive(Default)]
1513 struct Y {
1514 field1: i32,
1515 field2: u8,
1516 }
1517
1518 const GOAL: u8 = {
1519 let x = X::default();
1520 x.1.field2
1521 };
1522 "#,
1523 0,
1524 );
1525}
1526
1527#[test]
1528fn try_operator() {
1529 check_number(
1530 r#"
1531 //- minicore: option, try
1532 const fn f(x: Option<i32>, y: Option<i32>) -> Option<i32> {
1533 Some(x? * y?)
1534 }
1535 const fn g(x: Option<i32>, y: Option<i32>) -> i32 {
1536 match f(x, y) {
1537 Some(k) => k,
1538 None => 5,
1539 }
1540 }
1541 const GOAL: i32 = g(Some(10), Some(20)) + g(Some(30), None) + g(None, Some(40)) + g(None, None);
1542 "#,
1543 215,
1544 );
1545 check_number(
1546 r#"
1547 //- minicore: result, try, from
1548 struct E1(i32);
1549 struct E2(i32);
1550
1551 impl From<E1> for E2 {
1552 fn from(E1(x): E1) -> Self {
1553 E2(1000 * x)
1554 }
1555 }
1556
1557 const fn f(x: Result<i32, E1>) -> Result<i32, E2> {
1558 Ok(x? * 10)
1559 }
1560 const fn g(x: Result<i32, E1>) -> i32 {
1561 match f(x) {
1562 Ok(k) => 7 * k,
1563 Err(E2(k)) => 5 * k,
1564 }
1565 }
1566 const GOAL: i32 = g(Ok(2)) + g(Err(E1(3)));
1567 "#,
1568 15140,
1569 );
1570}
1571
1572#[test]
1573fn try_block() {
1574 check_number(
1575 r#"
1576 //- minicore: option, try
1577 const fn g(x: Option<i32>, y: Option<i32>) -> i32 {
1578 let r = try { x? * y? };
1579 match r {
1580 Some(k) => k,
1581 None => 5,
1582 }
1583 }
1584 const GOAL: i32 = g(Some(10), Some(20)) + g(Some(30), None) + g(None, Some(40)) + g(None, None);
1585 "#,
1586 215,
1587 );
1588}
1589
1590#[test]
1591fn closures() {
1592 check_number(
1593 r#"
1594 //- minicore: fn, copy
1595 const GOAL: i32 = {
1596 let y = 5;
1597 let c = |x| x + y;
1598 c(2)
1599 };
1600 "#,
1601 7,
1602 );
1603 check_number(
1604 r#"
1605 //- minicore: fn, copy
1606 const GOAL: i32 = {
1607 let y = 5;
1608 let c = |(a, b): &(i32, i32)| *a + *b + y;
1609 c(&(2, 3))
1610 };
1611 "#,
1612 10,
1613 );
1614 check_number(
1615 r#"
1616 //- minicore: fn, copy
1617 const GOAL: i32 = {
1618 let mut y = 5;
1619 let c = |x| {
1620 y = y + x;
1621 };
1622 c(2);
1623 c(3);
1624 y
1625 };
1626 "#,
1627 10,
1628 );
1629 check_number(
1630 r#"
1631 //- minicore: fn, copy
1632 const GOAL: i32 = {
1633 let c: fn(i32) -> i32 = |x| 2 * x;
1634 c(2) + c(10)
1635 };
1636 "#,
1637 24,
1638 );
1639 check_number(
1640 r#"
1641 //- minicore: fn, copy
1642 struct X(i32);
1643 impl X {
1644 fn mult(&mut self, n: i32) {
1645 self.0 = self.0 * n
1646 }
1647 }
1648 const GOAL: i32 = {
1649 let x = X(1);
1650 let c = || {
1651 x.mult(2);
1652 || {
1653 x.mult(3);
1654 || {
1655 || {
1656 x.mult(4);
1657 || {
1658 x.mult(x.0);
1659 || {
1660 x.0
1661 }
1662 }
1663 }
1664 }
1665 }
1666 };
1667 let r = c()()()()()();
1668 r + x.0
1669 };
1670 "#,
1671 24 * 24 * 2,
1672 );
1673}
1674
add651ee
FG
1675#[test]
1676fn manual_fn_trait_impl() {
1677 check_number(
1678 r#"
1679//- minicore: fn, copy
1680struct S(i32);
1681
1682impl FnOnce<(i32, i32)> for S {
1683 type Output = i32;
1684
1685 extern "rust-call" fn call_once(self, arg: (i32, i32)) -> i32 {
1686 arg.0 + arg.1 + self.0
1687 }
1688}
1689
1690const GOAL: i32 = {
1691 let s = S(1);
1692 s(2, 3)
1693};
1694"#,
1695 6,
1696 );
1697}
1698
1699#[test]
1700fn closure_capture_unsized_type() {
1701 check_number(
1702 r#"
1703 //- minicore: fn, copy, slice, index, coerce_unsized
1704 fn f<T: A>(x: &<T as A>::Ty) -> &<T as A>::Ty {
1705 let c = || &*x;
1706 c()
1707 }
1708
1709 trait A {
1710 type Ty;
1711 }
1712
1713 impl A for i32 {
1714 type Ty = [u8];
1715 }
1716
1717 const GOAL: u8 = {
1718 let k: &[u8] = &[1, 2, 3];
1719 let k = f::<i32>(k);
1720 k[0] + k[1] + k[2]
1721 }
1722 "#,
1723 6,
1724 );
1725}
1726
fe692bf9
FG
1727#[test]
1728fn closure_and_impl_fn() {
1729 check_number(
1730 r#"
1731 //- minicore: fn, copy
1732 fn closure_wrapper<F: FnOnce() -> i32>(c: F) -> impl FnOnce() -> F {
1733 || c
1734 }
1735
1736 const GOAL: i32 = {
1737 let y = 5;
1738 let c = closure_wrapper(|| y);
1739 c()()
1740 };
1741 "#,
1742 5,
1743 );
1744 check_number(
1745 r#"
1746 //- minicore: fn, copy
1747 fn f<T, F: Fn() -> T>(t: F) -> impl Fn() -> T {
1748 move || t()
1749 }
1750
1751 const GOAL: i32 = f(|| 2)();
1752 "#,
1753 2,
1754 );
1755}
1756
1757#[test]
1758fn or_pattern() {
1759 check_number(
1760 r#"
1761 const GOAL: u8 = {
1762 let (a | a) = 2;
1763 a
1764 };
1765 "#,
1766 2,
1767 );
1768 check_number(
1769 r#"
1770 //- minicore: option
1771 const fn f(x: Option<i32>) -> i32 {
1772 let (Some(a) | Some(a)) = x else { return 2; };
1773 a
1774 }
1775 const GOAL: i32 = f(Some(10)) + f(None);
1776 "#,
1777 12,
1778 );
1779 check_number(
1780 r#"
1781 //- minicore: option
1782 const fn f(x: Option<i32>, y: Option<i32>) -> i32 {
1783 match (x, y) {
1784 (Some(x), Some(y)) => x * y,
1785 (Some(a), _) | (_, Some(a)) => a,
1786 _ => 10,
1787 }
1788 }
1789 const GOAL: i32 = f(Some(10), Some(20)) + f(Some(30), None) + f(None, Some(40)) + f(None, None);
1790 "#,
1791 280,
1792 );
1793}
1794
1795#[test]
1796fn function_pointer_in_constants() {
1797 check_number(
1798 r#"
1799 struct Foo {
1800 f: fn(u8) -> u8,
1801 }
1802 const FOO: Foo = Foo { f: add2 };
1803 fn add2(x: u8) -> u8 {
1804 x + 2
1805 }
1806 const GOAL: u8 = (FOO.f)(3);
1807 "#,
1808 5,
1809 );
1810}
1811
add651ee
FG
1812#[test]
1813fn function_pointer_and_niche_optimization() {
1814 check_number(
1815 r#"
1816 //- minicore: option
1817 const GOAL: i32 = {
1818 let f: fn(i32) -> i32 = |x| x + 2;
1819 let init = Some(f);
1820 match init {
1821 Some(t) => t(3),
1822 None => 222,
1823 }
1824 };
1825 "#,
1826 5,
1827 );
1828}
1829
fe692bf9
FG
1830#[test]
1831fn function_pointer() {
1832 check_number(
1833 r#"
1834 fn add2(x: u8) -> u8 {
1835 x + 2
1836 }
1837 const GOAL: u8 = {
1838 let plus2 = add2;
1839 plus2(3)
1840 };
1841 "#,
1842 5,
1843 );
1844 check_number(
1845 r#"
1846 fn add2(x: u8) -> u8 {
1847 x + 2
1848 }
1849 const GOAL: u8 = {
1850 let plus2: fn(u8) -> u8 = add2;
1851 plus2(3)
1852 };
1853 "#,
1854 5,
1855 );
add651ee
FG
1856 check_number(
1857 r#"
1858 fn add2(x: u8) -> u8 {
1859 x + 2
1860 }
1861 const GOAL: u8 = {
1862 let plus2 = add2 as fn(u8) -> u8;
1863 plus2(3)
1864 };
1865 "#,
1866 5,
1867 );
fe692bf9
FG
1868 check_number(
1869 r#"
1870 //- minicore: coerce_unsized, index, slice
1871 fn add2(x: u8) -> u8 {
1872 x + 2
1873 }
1874 fn mult3(x: u8) -> u8 {
1875 x * 3
1876 }
1877 const GOAL: u8 = {
1878 let x = [add2, mult3];
1879 x[0](1) + x[1](5)
1880 };
1881 "#,
1882 18,
1883 );
1884}
1885
1886#[test]
1887fn enum_variant_as_function() {
1888 check_number(
1889 r#"
1890 //- minicore: option
1891 const GOAL: u8 = {
1892 let f = Some;
1893 f(3).unwrap_or(2)
1894 };
1895 "#,
1896 3,
1897 );
1898 check_number(
1899 r#"
1900 //- minicore: option
1901 const GOAL: u8 = {
1902 let f: fn(u8) -> Option<u8> = Some;
1903 f(3).unwrap_or(2)
1904 };
1905 "#,
1906 3,
1907 );
1908 check_number(
1909 r#"
1910 //- minicore: coerce_unsized, index, slice
1911 enum Foo {
1912 Add2(u8),
1913 Mult3(u8),
1914 }
1915 use Foo::*;
1916 const fn f(x: Foo) -> u8 {
1917 match x {
1918 Add2(x) => x + 2,
1919 Mult3(x) => x * 3,
1920 }
1921 }
1922 const GOAL: u8 = {
1923 let x = [Add2, Mult3];
1924 f(x[0](1)) + f(x[1](5))
1925 };
1926 "#,
1927 18,
1928 );
1929}
1930
1931#[test]
1932fn function_traits() {
1933 check_number(
1934 r#"
1935 //- minicore: fn
1936 fn add2(x: u8) -> u8 {
1937 x + 2
1938 }
1939 fn call(f: impl Fn(u8) -> u8, x: u8) -> u8 {
1940 f(x)
1941 }
1942 fn call_mut(mut f: impl FnMut(u8) -> u8, x: u8) -> u8 {
1943 f(x)
1944 }
1945 fn call_once(f: impl FnOnce(u8) -> u8, x: u8) -> u8 {
1946 f(x)
1947 }
1948 const GOAL: u8 = call(add2, 3) + call_mut(add2, 3) + call_once(add2, 3);
1949 "#,
1950 15,
353b0b11
FG
1951 );
1952 check_number(
1953 r#"
fe692bf9
FG
1954 //- minicore: coerce_unsized, fn
1955 fn add2(x: u8) -> u8 {
1956 x + 2
353b0b11 1957 }
fe692bf9
FG
1958 fn call(f: &dyn Fn(u8) -> u8, x: u8) -> u8 {
1959 f(x)
1960 }
1961 fn call_mut(f: &mut dyn FnMut(u8) -> u8, x: u8) -> u8 {
1962 f(x)
1963 }
1964 const GOAL: u8 = call(&add2, 3) + call_mut(&mut add2, 3);
353b0b11 1965 "#,
fe692bf9 1966 10,
353b0b11
FG
1967 );
1968 check_number(
1969 r#"
fe692bf9
FG
1970 //- minicore: fn
1971 fn add2(x: u8) -> u8 {
1972 x + 2
1973 }
1974 fn call(f: impl Fn(u8) -> u8, x: u8) -> u8 {
1975 f(x)
1976 }
1977 fn call_mut(mut f: impl FnMut(u8) -> u8, x: u8) -> u8 {
1978 f(x)
1979 }
1980 fn call_once(f: impl FnOnce(u8) -> u8, x: u8) -> u8 {
1981 f(x)
1982 }
353b0b11 1983 const GOAL: u8 = {
fe692bf9
FG
1984 let add2: fn(u8) -> u8 = add2;
1985 call(add2, 3) + call_mut(add2, 3) + call_once(add2, 3)
353b0b11
FG
1986 };
1987 "#,
fe692bf9 1988 15,
353b0b11
FG
1989 );
1990 check_number(
1991 r#"
fe692bf9
FG
1992 //- minicore: fn
1993 fn add2(x: u8) -> u8 {
1994 x + 2
1995 }
1996 fn call(f: &&&&&impl Fn(u8) -> u8, x: u8) -> u8 {
1997 f(x)
1998 }
1999 const GOAL: u8 = call(&&&&&add2, 3);
353b0b11 2000 "#,
fe692bf9 2001 5,
353b0b11
FG
2002 );
2003}
2004
2005#[test]
fe692bf9 2006fn dyn_trait() {
353b0b11
FG
2007 check_number(
2008 r#"
fe692bf9
FG
2009 //- minicore: coerce_unsized, index, slice
2010 trait Foo {
2011 fn foo(&self) -> u8 { 10 }
2012 }
2013 struct S1;
2014 struct S2;
2015 struct S3;
2016 impl Foo for S1 {
2017 fn foo(&self) -> u8 { 1 }
2018 }
2019 impl Foo for S2 {
2020 fn foo(&self) -> u8 { 2 }
2021 }
2022 impl Foo for S3 {}
353b0b11 2023 const GOAL: u8 = {
fe692bf9
FG
2024 let x: &[&dyn Foo] = &[&S1, &S2, &S3];
2025 x[0].foo() + x[1].foo() + x[2].foo()
353b0b11
FG
2026 };
2027 "#,
fe692bf9 2028 13,
353b0b11
FG
2029 );
2030 check_number(
2031 r#"
fe692bf9
FG
2032 //- minicore: coerce_unsized, index, slice
2033 trait Foo {
2034 fn foo(&self) -> i32 { 10 }
353b0b11 2035 }
fe692bf9
FG
2036 trait Bar {
2037 fn bar(&self) -> i32 { 20 }
2038 }
2039
2040 struct S;
2041 impl Foo for S {
2042 fn foo(&self) -> i32 { 200 }
2043 }
2044 impl Bar for dyn Foo {
2045 fn bar(&self) -> i32 { 700 }
2046 }
2047 const GOAL: i32 = {
2048 let x: &dyn Foo = &S;
2049 x.bar() + x.foo()
2050 };
353b0b11 2051 "#,
fe692bf9 2052 900,
353b0b11 2053 );
add651ee
FG
2054 check_number(
2055 r#"
2056 //- minicore: coerce_unsized, index, slice
2057 trait A {
2058 fn x(&self) -> i32;
2059 }
2060
2061 trait B: A {}
2062
2063 impl A for i32 {
2064 fn x(&self) -> i32 {
2065 5
2066 }
2067 }
2068
2069 impl B for i32 {
2070
2071 }
2072
2073 const fn f(x: &dyn B) -> i32 {
2074 x.x()
2075 }
2076
2077 const GOAL: i32 = f(&2i32);
2078 "#,
2079 5,
2080 );
2081}
2082
2083#[test]
2084fn coerce_unsized() {
2085 check_number(
2086 r#"
2087//- minicore: coerce_unsized, deref_mut, slice, index, transmute, non_null
2088use core::ops::{Deref, DerefMut, CoerceUnsized};
2089use core::{marker::Unsize, mem::transmute, ptr::NonNull};
2090
2091struct ArcInner<T: ?Sized> {
2092 strong: usize,
2093 weak: usize,
2094 data: T,
2095}
2096
2097pub struct Arc<T: ?Sized> {
2098 inner: NonNull<ArcInner<T>>,
2099}
2100
2101impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
2102
2103const GOAL: usize = {
2104 let x = transmute::<usize, Arc<[i32; 3]>>(12);
2105 let y: Arc<[i32]> = x;
2106 let z = transmute::<Arc<[i32]>, (usize, usize)>(y);
2107 z.1
2108};
2109
2110 "#,
2111 3,
2112 );
fe692bf9
FG
2113}
2114
2115#[test]
2116fn boxes() {
353b0b11
FG
2117 check_number(
2118 r#"
fe692bf9
FG
2119//- minicore: coerce_unsized, deref_mut, slice
2120use core::ops::{Deref, DerefMut};
2121use core::{marker::Unsize, ops::CoerceUnsized};
2122
2123#[lang = "owned_box"]
2124pub struct Box<T: ?Sized> {
2125 inner: *mut T,
2126}
2127impl<T> Box<T> {
2128 fn new(t: T) -> Self {
2129 #[rustc_box]
2130 Box::new(t)
353b0b11 2131 }
fe692bf9
FG
2132}
2133
2134impl<T: ?Sized> Deref for Box<T> {
2135 type Target = T;
2136
2137 fn deref(&self) -> &T {
2138 &**self
2139 }
2140}
2141
2142impl<T: ?Sized> DerefMut for Box<T> {
2143 fn deref_mut(&mut self) -> &mut T {
2144 &mut **self
2145 }
2146}
2147
2148impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
2149
2150const GOAL: usize = {
2151 let x = Box::new(5);
2152 let y: Box<[i32]> = Box::new([1, 2, 3]);
2153 *x + y.len()
2154};
2155"#,
2156 8,
353b0b11
FG
2157 );
2158}
2159
2160#[test]
2161fn array_and_index() {
2162 check_number(
2163 r#"
2164 //- minicore: coerce_unsized, index, slice
2165 const GOAL: u8 = {
2166 let a = [10, 20, 3, 15];
2167 let x: &[u8] = &a;
2168 x[1]
2169 };
2170 "#,
2171 20,
2172 );
2173 check_number(
2174 r#"
2175 //- minicore: coerce_unsized, index, slice
2176 const GOAL: usize = [1, 2, 3][2];"#,
2177 3,
2178 );
2179 check_number(
2180 r#"
2181 //- minicore: coerce_unsized, index, slice
2182 const GOAL: usize = { let a = [1, 2, 3]; let x: &[i32] = &a; x.len() };"#,
2183 3,
2184 );
2185 check_number(
2186 r#"
2187 //- minicore: coerce_unsized, index, slice
fe692bf9
FG
2188 const GOAL: usize = {
2189 let a = [1, 2, 3];
2190 let x: &[i32] = &a;
2191 let y = &*x;
2192 y.len()
2193 };"#,
2194 3,
2195 );
2196 check_number(
2197 r#"
2198 //- minicore: coerce_unsized, index, slice
353b0b11
FG
2199 const GOAL: usize = [1, 2, 3, 4, 5].len();"#,
2200 5,
2201 );
fe692bf9
FG
2202 check_number(
2203 r#"
2204 //- minicore: coerce_unsized, index, slice
2205 const GOAL: [u16; 5] = [1, 2, 3, 4, 5];"#,
2206 1 + (2 << 16) + (3 << 32) + (4 << 48) + (5 << 64),
2207 );
2208 check_number(
2209 r#"
2210 //- minicore: coerce_unsized, index, slice
2211 const GOAL: [u16; 5] = [12; 5];"#,
2212 12 + (12 << 16) + (12 << 32) + (12 << 48) + (12 << 64),
2213 );
2214 check_number(
2215 r#"
2216 //- minicore: coerce_unsized, index, slice
2217 const LEN: usize = 4;
2218 const GOAL: u16 = {
2219 let x = [7; LEN];
2220 x[2]
2221 }"#,
2222 7,
2223 );
353b0b11
FG
2224}
2225
add651ee
FG
2226#[test]
2227fn string() {
2228 check_str(
2229 r#"
2230 //- minicore: coerce_unsized, index, slice
2231 const GOAL: &str = "hello";
2232 "#,
2233 "hello",
2234 );
2235}
2236
353b0b11
FG
2237#[test]
2238fn byte_string() {
2239 check_number(
2240 r#"
2241 //- minicore: coerce_unsized, index, slice
2242 const GOAL: u8 = {
2243 let a = b"hello";
2244 let x: &[u8] = a;
2245 x[0]
2246 };
2247 "#,
2248 104,
2249 );
2250}
2251
fe692bf9
FG
2252#[test]
2253fn c_string() {
2254 check_number(
2255 r#"
2256//- minicore: index, slice
2257#[lang = "CStr"]
2258pub struct CStr {
2259 inner: [u8]
2260}
2261const GOAL: u8 = {
2262 let a = c"hello";
2263 a.inner[0]
2264};
2265 "#,
2266 104,
2267 );
2268 check_number(
2269 r#"
2270//- minicore: index, slice
2271#[lang = "CStr"]
2272pub struct CStr {
2273 inner: [u8]
2274}
2275const GOAL: u8 = {
2276 let a = c"hello";
2277 a.inner[6]
2278};
2279 "#,
2280 0,
2281 );
2282}
2283
064997fb
FG
2284#[test]
2285fn consts() {
2286 check_number(
2287 r#"
2288 const F1: i32 = 1;
2289 const F3: i32 = 3 * F2;
2290 const F2: i32 = 2 * F1;
2291 const GOAL: i32 = F3;
2292 "#,
2293 6,
2294 );
add651ee
FG
2295
2296 check_number(
2297 r#"
2298 const F1: i32 = 2147483647;
2299 const F2: i32 = F1 - 25;
2300 const GOAL: i32 = F2;
2301 "#,
2302 2147483622,
2303 );
2304
2305 check_number(
2306 r#"
2307 const F1: i32 = -2147483648;
2308 const F2: i32 = F1 + 18;
2309 const GOAL: i32 = F2;
2310 "#,
2311 -2147483630,
2312 );
2313
2314 check_number(
2315 r#"
2316 const F1: i32 = 10;
2317 const F2: i32 = F1 - 20;
2318 const GOAL: i32 = F2;
2319 "#,
2320 -10,
2321 );
2322
2323 check_number(
2324 r#"
2325 const F1: i32 = 25;
2326 const F2: i32 = F1 - 25;
2327 const GOAL: i32 = F2;
2328 "#,
2329 0,
2330 );
2331
2332 check_number(
2333 r#"
2334 const A: i32 = -2147483648;
2335 const GOAL: bool = A > 0;
2336 "#,
2337 0,
2338 );
2339
2340 check_number(
2341 r#"
2342 const GOAL: i64 = (-2147483648_i32) as i64;
2343 "#,
2344 -2147483648,
2345 );
064997fb
FG
2346}
2347
fe692bf9
FG
2348#[test]
2349fn statics() {
2350 check_number(
2351 r#"
2352 //- minicore: cell
2353 use core::cell::Cell;
2354 fn f() -> i32 {
2355 static S: Cell<i32> = Cell::new(10);
2356 S.set(S.get() + 1);
2357 S.get()
2358 }
2359 const GOAL: i32 = f() + f() + f();
2360 "#,
2361 36,
2362 );
2363}
2364
2365#[test]
2366fn extern_weak_statics() {
2367 check_number(
2368 r#"
2369 extern "C" {
2370 #[linkage = "extern_weak"]
2371 static __dso_handle: *mut u8;
2372 }
2373 const GOAL: usize = __dso_handle as usize;
2374 "#,
2375 0,
2376 );
2377}
2378
2379#[test]
2380fn from_ne_bytes() {
2381 check_number(
2382 r#"
2383//- minicore: int_impl
2384const GOAL: u32 = u32::from_ne_bytes([44, 1, 0, 0]);
2385 "#,
2386 300,
2387 );
2388}
2389
2b03887a
FG
2390#[test]
2391fn enums() {
2392 check_number(
2393 r#"
2394 enum E {
2395 F1 = 1,
353b0b11
FG
2396 F2 = 2 * E::F1 as isize, // Rustc expects an isize here
2397 F3 = 3 * E::F2 as isize,
2b03887a 2398 }
353b0b11 2399 const GOAL: u8 = E::F3 as u8;
2b03887a
FG
2400 "#,
2401 6,
2402 );
2403 check_number(
2404 r#"
2405 enum E { F1 = 1, F2, }
353b0b11 2406 const GOAL: u8 = E::F2 as u8;
2b03887a
FG
2407 "#,
2408 2,
2409 );
2410 check_number(
2411 r#"
2412 enum E { F1, }
353b0b11 2413 const GOAL: u8 = E::F1 as u8;
2b03887a
FG
2414 "#,
2415 0,
2416 );
fe692bf9 2417 let (db, file_id) = TestDB::with_single_file(
2b03887a 2418 r#"
353b0b11 2419 enum E { A = 1, B }
2b03887a
FG
2420 const GOAL: E = E::A;
2421 "#,
fe692bf9
FG
2422 );
2423 let r = eval_goal(&db, file_id).unwrap();
2424 assert_eq!(try_const_usize(&db, &r), Some(1));
2b03887a
FG
2425}
2426
064997fb
FG
2427#[test]
2428fn const_loop() {
2429 check_fail(
2430 r#"
2431 const F1: i32 = 1 * F3;
2432 const F3: i32 = 3 * F2;
2433 const F2: i32 = 2 * F1;
2434 const GOAL: i32 = F3;
2435 "#,
fe692bf9 2436 |e| e == ConstEvalError::MirLowerError(MirLowerError::Loop),
353b0b11
FG
2437 );
2438}
2439
2440#[test]
2441fn const_transfer_memory() {
2442 check_number(
2443 r#"
781aab86 2444 //- minicore: slice, index, coerce_unsized, option
add651ee
FG
2445 const A1: &i32 = &1;
2446 const A2: &i32 = &10;
2447 const A3: [&i32; 3] = [&1, &2, &100];
781aab86
FG
2448 const A4: (i32, &i32, Option<&i32>) = (1, &1000, Some(&10000));
2449 const GOAL: i32 = *A1 + *A2 + *A3[2] + *A4.1 + *A4.2.unwrap_or(&5);
353b0b11 2450 "#,
781aab86 2451 11111,
064997fb
FG
2452 );
2453}
2454
fe692bf9
FG
2455#[test]
2456fn anonymous_const_block() {
2457 check_number(
2458 r#"
2459 extern "rust-intrinsic" {
2460 pub fn size_of<T>() -> usize;
2461 }
2462
2463 const fn f<T>() -> usize {
2464 let r = const { size_of::<T>() };
2465 r
2466 }
2467
2468 const GOAL: usize = {
2469 let x = const { 2 + const { 3 } };
2470 let y = f::<i32>();
2471 x + y
2472 };
2473 "#,
2474 9,
2475 );
2476}
2477
064997fb
FG
2478#[test]
2479fn const_impl_assoc() {
2480 check_number(
2481 r#"
2482 struct U5;
2483 impl U5 {
2484 const VAL: usize = 5;
2485 }
fe692bf9 2486 const GOAL: usize = U5::VAL + <U5>::VAL;
064997fb 2487 "#,
fe692bf9 2488 10,
064997fb
FG
2489 );
2490}
2491
2492#[test]
353b0b11
FG
2493fn const_generic_subst_fn() {
2494 check_number(
2495 r#"
2496 const fn f<const A: usize>(x: usize) -> usize {
2497 A * x + 5
2498 }
2499 const GOAL: usize = f::<2>(3);
2500 "#,
2501 11,
2502 );
fe692bf9
FG
2503 check_number(
2504 r#"
2505 fn f<const N: usize>(x: [i32; N]) -> usize {
2506 N
2507 }
2508
2509 trait ArrayExt {
2510 fn f(self) -> usize;
2511 }
2512
2513 impl<T, const N: usize> ArrayExt for [T; N] {
2514 fn g(self) -> usize {
2515 f(self)
2516 }
2517 }
2518
2519 const GOAL: usize = f([1, 2, 5]);
2520 "#,
2521 3,
2522 );
2523}
2524
2525#[test]
2526fn layout_of_type_with_associated_type_field_defined_inside_body() {
2527 check_number(
2528 r#"
2529trait Tr {
2530 type Ty;
2531}
2532
2533struct St<T: Tr>(T::Ty);
2534
2535const GOAL: i64 = {
2536 // if we move `St2` out of body, the test will fail, as we don't see the impl anymore. That
2537 // case will probably be rejected by rustc in some later edition, but we should support this
2538 // case.
2539 struct St2;
2540
2541 impl Tr for St2 {
2542 type Ty = i64;
2543 }
2544
2545 struct Goal(St<St2>);
2546
2547 let x = Goal(St(5));
2548 x.0.0
2549};
2550"#,
2551 5,
2552 );
353b0b11
FG
2553}
2554
2555#[test]
2556fn const_generic_subst_assoc_const_impl() {
fe692bf9 2557 check_number(
064997fb
FG
2558 r#"
2559 struct Adder<const N: usize, const M: usize>;
2560 impl<const N: usize, const M: usize> Adder<N, M> {
2561 const VAL: usize = N + M;
2562 }
2563 const GOAL: usize = Adder::<2, 3>::VAL;
2564 "#,
fe692bf9
FG
2565 5,
2566 );
2567}
2568
2569#[test]
2570fn associated_types() {
2571 check_number(
2572 r#"
2573 trait Tr {
2574 type Item;
2575 fn get_item(&self) -> Self::Item;
2576 }
2577
2578 struct X(i32);
2579 struct Y(i32);
2580
2581 impl Tr for X {
2582 type Item = Y;
2583 fn get_item(&self) -> Self::Item {
2584 Y(self.0 + 2)
2585 }
2586 }
2587
2588 fn my_get_item<T: Tr>(x: T) -> <T as Tr>::Item {
2589 x.get_item()
2590 }
2591
2592 const GOAL: i32 = my_get_item(X(3)).0;
2593 "#,
2594 5,
064997fb
FG
2595 );
2596}
2597
2598#[test]
2599fn const_trait_assoc() {
fe692bf9 2600 check_number(
064997fb
FG
2601 r#"
2602 struct U0;
2603 trait ToConst {
2604 const VAL: usize;
2605 }
2606 impl ToConst for U0 {
2607 const VAL: usize = 0;
2608 }
fe692bf9
FG
2609 impl ToConst for i32 {
2610 const VAL: usize = 32;
2611 }
2612 const GOAL: usize = U0::VAL + i32::VAL;
2613 "#,
2614 32,
2615 );
add651ee
FG
2616 check_number(
2617 r#"
2618 //- /a/lib.rs crate:a
2619 pub trait ToConst {
2620 const VAL: usize;
2621 }
2622 pub const fn to_const<T: ToConst>() -> usize {
2623 T::VAL
2624 }
2625 //- /main.rs crate:main deps:a
2626 use a::{ToConst, to_const};
2627 struct U0;
2628 impl ToConst for U0 {
2629 const VAL: usize = 5;
2630 }
2631 const GOAL: usize = to_const::<U0>();
2632 "#,
2633 5,
2634 );
2635 check_number(
2636 r#"
2637 //- minicore: size_of, fn
2638 //- /a/lib.rs crate:a
2639 use core::mem::size_of;
2640 pub struct S<T>(T);
2641 impl<T> S<T> {
2642 pub const X: usize = {
2643 let k: T;
2644 let f = || core::mem::size_of::<T>();
2645 f()
2646 };
2647 }
2648 //- /main.rs crate:main deps:a
2649 use a::{S};
2650 trait Tr {
2651 type Ty;
2652 }
2653 impl Tr for i32 {
2654 type Ty = u64;
2655 }
2656 struct K<T: Tr>(<T as Tr>::Ty);
2657 const GOAL: usize = S::<K<i32>>::X;
2658 "#,
2659 8,
2660 );
fe692bf9
FG
2661 check_number(
2662 r#"
2663 struct S<T>(*mut T);
2664
2665 trait MySized: Sized {
2666 const SIZE: S<Self> = S(1 as *mut Self);
2667 }
2668
2669 impl MySized for i32 {
2670 const SIZE: S<i32> = S(10 as *mut i32);
2671 }
2672
2673 impl MySized for i64 {
2674 }
2675
2676 const fn f<T: MySized>() -> usize {
2677 T::SIZE.0 as usize
2678 }
2679
2680 const GOAL: usize = f::<i32>() + f::<i64>() * 2;
2681 "#,
2682 12,
2683 );
2684}
2685
353b0b11
FG
2686#[test]
2687fn exec_limits() {
add651ee
FG
2688 if skip_slow_tests() {
2689 return;
2690 }
2691
353b0b11
FG
2692 check_fail(
2693 r#"
2694 const GOAL: usize = loop {};
2695 "#,
fe692bf9 2696 |e| e == ConstEvalError::MirEvalError(MirEvalError::ExecutionLimitExceeded),
353b0b11
FG
2697 );
2698 check_fail(
2699 r#"
2700 const fn f(x: i32) -> i32 {
2701 f(x + 1)
2702 }
2703 const GOAL: i32 = f(0);
2704 "#,
add651ee 2705 |e| e == ConstEvalError::MirEvalError(MirEvalError::ExecutionLimitExceeded),
353b0b11
FG
2706 );
2707 // Reasonable code should still work
2708 check_number(
2709 r#"
2710 const fn nth_odd(n: i32) -> i32 {
2711 2 * n - 1
2712 }
2713 const fn f(n: i32) -> i32 {
2714 let sum = 0;
2715 let i = 0;
2716 while i < n {
2717 i = i + 1;
2718 sum = sum + nth_odd(i);
2719 }
2720 sum
2721 }
add651ee 2722 const GOAL: i32 = f(1000);
353b0b11 2723 "#,
add651ee
FG
2724 1000 * 1000,
2725 );
2726}
2727
2728#[test]
2729fn memory_limit() {
2730 check_fail(
2731 r#"
2732 extern "Rust" {
2733 #[rustc_allocator]
2734 fn __rust_alloc(size: usize, align: usize) -> *mut u8;
2735 }
2736
2737 const GOAL: u8 = unsafe {
2738 __rust_alloc(30_000_000_000, 1); // 30GB
2739 2
2740 };
2741 "#,
2742 |e| {
2743 e == ConstEvalError::MirEvalError(MirEvalError::Panic(
2744 "Memory allocation of 30000000000 bytes failed".to_string(),
2745 ))
2746 },
353b0b11
FG
2747 );
2748}
2749
2750#[test]
2751fn type_error() {
fe692bf9 2752 check_fail(
353b0b11
FG
2753 r#"
2754 const GOAL: u8 = {
2755 let x: u16 = 2;
2756 let y: (u8, u8) = x;
2757 y.0
2758 };
2759 "#,
fe692bf9
FG
2760 |e| matches!(e, ConstEvalError::MirLowerError(MirLowerError::TypeMismatch(_))),
2761 );
2762}
2763
add651ee
FG
2764#[test]
2765fn unsized_field() {
2766 check_number(
2767 r#"
2768 //- minicore: coerce_unsized, index, slice, transmute
2769 use core::mem::transmute;
2770
2771 struct Slice([usize]);
2772 struct Slice2(Slice);
2773
2774 impl Slice2 {
2775 fn as_inner(&self) -> &Slice {
2776 &self.0
2777 }
2778
2779 fn as_bytes(&self) -> &[usize] {
2780 &self.as_inner().0
2781 }
2782 }
2783
2784 const GOAL: usize = unsafe {
2785 let x: &[usize] = &[1, 2, 3];
2786 let x: &Slice2 = transmute(x);
2787 let x = x.as_bytes();
2788 x[0] + x[1] + x[2] + x.len() * 100
2789 };
2790 "#,
2791 306,
2792 );
2793}
2794
fe692bf9
FG
2795#[test]
2796fn unsized_local() {
2797 check_fail(
2798 r#"
2799 //- minicore: coerce_unsized, index, slice
2800 const fn x() -> SomeUnknownTypeThatDereferenceToSlice {
2801 SomeUnknownTypeThatDereferenceToSlice
2802 }
2803
2804 const GOAL: u16 = {
2805 let y = x();
2806 let z: &[u16] = &y;
2807 z[1]
2808 };
2809 "#,
2810 |e| matches!(e, ConstEvalError::MirLowerError(MirLowerError::UnsizedTemporary(_))),
064997fb
FG
2811 );
2812}