]> git.proxmox.com Git - rustc.git/blame - src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
New upstream version 1.73.0+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 );
1206}
1207
fe692bf9
FG
1208#[test]
1209fn let_else() {
1210 check_number(
1211 r#"
1212 const fn f(x: &(u8, u8)) -> u8 {
1213 let (a, b) = x;
1214 *a + *b
1215 }
1216 const GOAL: u8 = f(&(2, 3));
1217 "#,
1218 5,
1219 );
1220 check_number(
1221 r#"
1222 enum SingleVariant {
1223 Var(u8, u8),
1224 }
1225 const fn f(x: &&&&&SingleVariant) -> u8 {
1226 let SingleVariant::Var(a, b) = x;
1227 *a + *b
1228 }
1229 const GOAL: u8 = f(&&&&&SingleVariant::Var(2, 3));
353b0b11
FG
1230 "#,
1231 5,
1232 );
1233 check_number(
1234 r#"
1235 //- minicore: option
1236 const fn f(x: Option<i32>) -> i32 {
1237 let Some(x) = x else { return 10 };
1238 2 * x
1239 }
1240 const GOAL: i32 = f(Some(1000)) + f(None);
1241 "#,
1242 2010,
1243 );
1244}
1245
1246#[test]
1247fn function_param_patterns() {
1248 check_number(
1249 r#"
1250 const fn f((a, b): &(u8, u8)) -> u8 {
1251 *a + *b
1252 }
1253 const GOAL: u8 = f(&(2, 3));
1254 "#,
1255 5,
1256 );
1257 check_number(
1258 r#"
1259 const fn f(c @ (a, b): &(u8, u8)) -> u8 {
1260 *a + *b + c.0 + (*c).1
1261 }
1262 const GOAL: u8 = f(&(2, 3));
1263 "#,
1264 10,
1265 );
1266 check_number(
1267 r#"
1268 const fn f(ref a: u8) -> u8 {
1269 *a
1270 }
1271 const GOAL: u8 = f(2);
1272 "#,
1273 2,
1274 );
1275 check_number(
1276 r#"
1277 struct Foo(u8);
1278 impl Foo {
1279 const fn f(&self, (a, b): &(u8, u8)) -> u8 {
1280 self.0 + *a + *b
1281 }
1282 }
1283 const GOAL: u8 = Foo(4).f(&(2, 3));
1284 "#,
1285 9,
1286 );
1287}
1288
fe692bf9
FG
1289#[test]
1290fn match_guards() {
1291 check_number(
1292 r#"
1293 //- minicore: option
1294 fn f(x: Option<i32>) -> i32 {
1295 match x {
1296 y if let Some(42) = y => 42000,
1297 Some(y) => y,
1298 None => 10
1299 }
1300 }
1301 const GOAL: i32 = f(Some(42)) + f(Some(2)) + f(None);
1302 "#,
1303 42012,
1304 );
1305}
1306
1307#[test]
1308fn result_layout_niche_optimization() {
1309 check_number(
1310 r#"
1311 //- minicore: option, result
1312 const GOAL: i32 = match Some(2).ok_or(Some(2)) {
1313 Ok(x) => x,
1314 Err(_) => 1000,
1315 };
1316 "#,
1317 2,
1318 );
1319 check_number(
1320 r#"
1321 //- minicore: result
1322 pub enum AlignmentEnum64 {
1323 _Align1Shl0 = 1 << 0,
1324 _Align1Shl1 = 1 << 1,
1325 _Align1Shl2 = 1 << 2,
1326 _Align1Shl3 = 1 << 3,
1327 _Align1Shl4 = 1 << 4,
1328 _Align1Shl5 = 1 << 5,
1329 }
1330 const GOAL: Result<AlignmentEnum64, ()> = {
1331 let align = Err(());
1332 align
1333 };
1334 "#,
1335 0, // It is 0 since result is niche encoded and 1 is valid for `AlignmentEnum64`
1336 );
1337 check_number(
1338 r#"
1339 //- minicore: result
1340 pub enum AlignmentEnum64 {
1341 _Align1Shl0 = 1 << 0,
1342 _Align1Shl1 = 1 << 1,
1343 _Align1Shl2 = 1 << 2,
1344 _Align1Shl3 = 1 << 3,
1345 _Align1Shl4 = 1 << 4,
1346 _Align1Shl5 = 1 << 5,
1347 }
1348 const GOAL: i32 = {
1349 let align = Ok::<_, ()>(AlignmentEnum64::_Align1Shl0);
1350 match align {
1351 Ok(_) => 2,
1352 Err(_) => 1,
1353 }
1354 };
1355 "#,
1356 2,
1357 );
1358}
1359
353b0b11
FG
1360#[test]
1361fn options() {
1362 check_number(
1363 r#"
1364 //- minicore: option
1365 const GOAL: u8 = {
1366 let x = Some(2);
1367 match x {
1368 Some(y) => 2 * y,
1369 _ => 10,
1370 }
1371 };
1372 "#,
fe692bf9
FG
1373 4,
1374 );
1375 check_number(
1376 r#"
1377 //- minicore: option
1378 fn f(x: Option<Option<i32>>) -> i32 {
1379 if let Some(y) = x && let Some(z) = y {
1380 z
1381 } else if let Some(y) = x {
1382 1
1383 } else {
1384 0
1385 }
1386 }
1387 const GOAL: i32 = f(Some(Some(10))) + f(Some(None)) + f(None);
1388 "#,
1389 11,
1390 );
1391 check_number(
1392 r#"
1393 //- minicore: option
1394 const GOAL: u8 = {
1395 let x = None;
1396 match x {
1397 Some(y) => 2 * y,
1398 _ => 10,
1399 }
1400 };
1401 "#,
1402 10,
1403 );
1404 check_number(
1405 r#"
1406 //- minicore: option
1407 const GOAL: Option<&u8> = None;
1408 "#,
1409 0,
1410 );
1411}
1412
1413#[test]
1414fn from_trait() {
1415 check_number(
1416 r#"
1417 //- minicore: from
1418 struct E1(i32);
1419 struct E2(i32);
1420
1421 impl From<E1> for E2 {
1422 fn from(E1(x): E1) -> Self {
1423 E2(1000 * x)
1424 }
1425 }
1426 const GOAL: i32 = {
1427 let x: E2 = E1(2).into();
1428 x.0
1429 };
1430 "#,
1431 2000,
1432 );
1433}
1434
1435#[test]
1436fn builtin_derive_macro() {
1437 check_number(
1438 r#"
1439 //- minicore: clone, derive, builtin_impls
1440 #[derive(Clone)]
1441 enum Z {
1442 Foo(Y),
1443 Bar,
1444 }
1445 #[derive(Clone)]
1446 struct X(i32, Z, i64)
1447 #[derive(Clone)]
1448 struct Y {
1449 field1: i32,
add651ee 1450 field2: ((i32, u8), i64),
fe692bf9
FG
1451 }
1452
1453 const GOAL: u8 = {
add651ee 1454 let x = X(2, Z::Foo(Y { field1: 4, field2: ((32, 5), 12) }), 8);
fe692bf9
FG
1455 let x = x.clone();
1456 let Z::Foo(t) = x.1;
add651ee 1457 t.field2.0 .1
fe692bf9
FG
1458 };
1459 "#,
1460 5,
1461 );
1462 check_number(
1463 r#"
1464 //- minicore: default, derive, builtin_impls
1465 #[derive(Default)]
1466 struct X(i32, Y, i64)
1467 #[derive(Default)]
1468 struct Y {
1469 field1: i32,
1470 field2: u8,
1471 }
1472
1473 const GOAL: u8 = {
1474 let x = X::default();
1475 x.1.field2
1476 };
1477 "#,
1478 0,
1479 );
1480}
1481
1482#[test]
1483fn try_operator() {
1484 check_number(
1485 r#"
1486 //- minicore: option, try
1487 const fn f(x: Option<i32>, y: Option<i32>) -> Option<i32> {
1488 Some(x? * y?)
1489 }
1490 const fn g(x: Option<i32>, y: Option<i32>) -> i32 {
1491 match f(x, y) {
1492 Some(k) => k,
1493 None => 5,
1494 }
1495 }
1496 const GOAL: i32 = g(Some(10), Some(20)) + g(Some(30), None) + g(None, Some(40)) + g(None, None);
1497 "#,
1498 215,
1499 );
1500 check_number(
1501 r#"
1502 //- minicore: result, try, from
1503 struct E1(i32);
1504 struct E2(i32);
1505
1506 impl From<E1> for E2 {
1507 fn from(E1(x): E1) -> Self {
1508 E2(1000 * x)
1509 }
1510 }
1511
1512 const fn f(x: Result<i32, E1>) -> Result<i32, E2> {
1513 Ok(x? * 10)
1514 }
1515 const fn g(x: Result<i32, E1>) -> i32 {
1516 match f(x) {
1517 Ok(k) => 7 * k,
1518 Err(E2(k)) => 5 * k,
1519 }
1520 }
1521 const GOAL: i32 = g(Ok(2)) + g(Err(E1(3)));
1522 "#,
1523 15140,
1524 );
1525}
1526
1527#[test]
1528fn try_block() {
1529 check_number(
1530 r#"
1531 //- minicore: option, try
1532 const fn g(x: Option<i32>, y: Option<i32>) -> i32 {
1533 let r = try { x? * y? };
1534 match r {
1535 Some(k) => k,
1536 None => 5,
1537 }
1538 }
1539 const GOAL: i32 = g(Some(10), Some(20)) + g(Some(30), None) + g(None, Some(40)) + g(None, None);
1540 "#,
1541 215,
1542 );
1543}
1544
1545#[test]
1546fn closures() {
1547 check_number(
1548 r#"
1549 //- minicore: fn, copy
1550 const GOAL: i32 = {
1551 let y = 5;
1552 let c = |x| x + y;
1553 c(2)
1554 };
1555 "#,
1556 7,
1557 );
1558 check_number(
1559 r#"
1560 //- minicore: fn, copy
1561 const GOAL: i32 = {
1562 let y = 5;
1563 let c = |(a, b): &(i32, i32)| *a + *b + y;
1564 c(&(2, 3))
1565 };
1566 "#,
1567 10,
1568 );
1569 check_number(
1570 r#"
1571 //- minicore: fn, copy
1572 const GOAL: i32 = {
1573 let mut y = 5;
1574 let c = |x| {
1575 y = y + x;
1576 };
1577 c(2);
1578 c(3);
1579 y
1580 };
1581 "#,
1582 10,
1583 );
1584 check_number(
1585 r#"
1586 //- minicore: fn, copy
1587 const GOAL: i32 = {
1588 let c: fn(i32) -> i32 = |x| 2 * x;
1589 c(2) + c(10)
1590 };
1591 "#,
1592 24,
1593 );
1594 check_number(
1595 r#"
1596 //- minicore: fn, copy
1597 struct X(i32);
1598 impl X {
1599 fn mult(&mut self, n: i32) {
1600 self.0 = self.0 * n
1601 }
1602 }
1603 const GOAL: i32 = {
1604 let x = X(1);
1605 let c = || {
1606 x.mult(2);
1607 || {
1608 x.mult(3);
1609 || {
1610 || {
1611 x.mult(4);
1612 || {
1613 x.mult(x.0);
1614 || {
1615 x.0
1616 }
1617 }
1618 }
1619 }
1620 }
1621 };
1622 let r = c()()()()()();
1623 r + x.0
1624 };
1625 "#,
1626 24 * 24 * 2,
1627 );
1628}
1629
add651ee
FG
1630#[test]
1631fn manual_fn_trait_impl() {
1632 check_number(
1633 r#"
1634//- minicore: fn, copy
1635struct S(i32);
1636
1637impl FnOnce<(i32, i32)> for S {
1638 type Output = i32;
1639
1640 extern "rust-call" fn call_once(self, arg: (i32, i32)) -> i32 {
1641 arg.0 + arg.1 + self.0
1642 }
1643}
1644
1645const GOAL: i32 = {
1646 let s = S(1);
1647 s(2, 3)
1648};
1649"#,
1650 6,
1651 );
1652}
1653
1654#[test]
1655fn closure_capture_unsized_type() {
1656 check_number(
1657 r#"
1658 //- minicore: fn, copy, slice, index, coerce_unsized
1659 fn f<T: A>(x: &<T as A>::Ty) -> &<T as A>::Ty {
1660 let c = || &*x;
1661 c()
1662 }
1663
1664 trait A {
1665 type Ty;
1666 }
1667
1668 impl A for i32 {
1669 type Ty = [u8];
1670 }
1671
1672 const GOAL: u8 = {
1673 let k: &[u8] = &[1, 2, 3];
1674 let k = f::<i32>(k);
1675 k[0] + k[1] + k[2]
1676 }
1677 "#,
1678 6,
1679 );
1680}
1681
fe692bf9
FG
1682#[test]
1683fn closure_and_impl_fn() {
1684 check_number(
1685 r#"
1686 //- minicore: fn, copy
1687 fn closure_wrapper<F: FnOnce() -> i32>(c: F) -> impl FnOnce() -> F {
1688 || c
1689 }
1690
1691 const GOAL: i32 = {
1692 let y = 5;
1693 let c = closure_wrapper(|| y);
1694 c()()
1695 };
1696 "#,
1697 5,
1698 );
1699 check_number(
1700 r#"
1701 //- minicore: fn, copy
1702 fn f<T, F: Fn() -> T>(t: F) -> impl Fn() -> T {
1703 move || t()
1704 }
1705
1706 const GOAL: i32 = f(|| 2)();
1707 "#,
1708 2,
1709 );
1710}
1711
1712#[test]
1713fn or_pattern() {
1714 check_number(
1715 r#"
1716 const GOAL: u8 = {
1717 let (a | a) = 2;
1718 a
1719 };
1720 "#,
1721 2,
1722 );
1723 check_number(
1724 r#"
1725 //- minicore: option
1726 const fn f(x: Option<i32>) -> i32 {
1727 let (Some(a) | Some(a)) = x else { return 2; };
1728 a
1729 }
1730 const GOAL: i32 = f(Some(10)) + f(None);
1731 "#,
1732 12,
1733 );
1734 check_number(
1735 r#"
1736 //- minicore: option
1737 const fn f(x: Option<i32>, y: Option<i32>) -> i32 {
1738 match (x, y) {
1739 (Some(x), Some(y)) => x * y,
1740 (Some(a), _) | (_, Some(a)) => a,
1741 _ => 10,
1742 }
1743 }
1744 const GOAL: i32 = f(Some(10), Some(20)) + f(Some(30), None) + f(None, Some(40)) + f(None, None);
1745 "#,
1746 280,
1747 );
1748}
1749
1750#[test]
1751fn function_pointer_in_constants() {
1752 check_number(
1753 r#"
1754 struct Foo {
1755 f: fn(u8) -> u8,
1756 }
1757 const FOO: Foo = Foo { f: add2 };
1758 fn add2(x: u8) -> u8 {
1759 x + 2
1760 }
1761 const GOAL: u8 = (FOO.f)(3);
1762 "#,
1763 5,
1764 );
1765}
1766
add651ee
FG
1767#[test]
1768fn function_pointer_and_niche_optimization() {
1769 check_number(
1770 r#"
1771 //- minicore: option
1772 const GOAL: i32 = {
1773 let f: fn(i32) -> i32 = |x| x + 2;
1774 let init = Some(f);
1775 match init {
1776 Some(t) => t(3),
1777 None => 222,
1778 }
1779 };
1780 "#,
1781 5,
1782 );
1783}
1784
fe692bf9
FG
1785#[test]
1786fn function_pointer() {
1787 check_number(
1788 r#"
1789 fn add2(x: u8) -> u8 {
1790 x + 2
1791 }
1792 const GOAL: u8 = {
1793 let plus2 = add2;
1794 plus2(3)
1795 };
1796 "#,
1797 5,
1798 );
1799 check_number(
1800 r#"
1801 fn add2(x: u8) -> u8 {
1802 x + 2
1803 }
1804 const GOAL: u8 = {
1805 let plus2: fn(u8) -> u8 = add2;
1806 plus2(3)
1807 };
1808 "#,
1809 5,
1810 );
add651ee
FG
1811 check_number(
1812 r#"
1813 fn add2(x: u8) -> u8 {
1814 x + 2
1815 }
1816 const GOAL: u8 = {
1817 let plus2 = add2 as fn(u8) -> u8;
1818 plus2(3)
1819 };
1820 "#,
1821 5,
1822 );
fe692bf9
FG
1823 check_number(
1824 r#"
1825 //- minicore: coerce_unsized, index, slice
1826 fn add2(x: u8) -> u8 {
1827 x + 2
1828 }
1829 fn mult3(x: u8) -> u8 {
1830 x * 3
1831 }
1832 const GOAL: u8 = {
1833 let x = [add2, mult3];
1834 x[0](1) + x[1](5)
1835 };
1836 "#,
1837 18,
1838 );
1839}
1840
1841#[test]
1842fn enum_variant_as_function() {
1843 check_number(
1844 r#"
1845 //- minicore: option
1846 const GOAL: u8 = {
1847 let f = Some;
1848 f(3).unwrap_or(2)
1849 };
1850 "#,
1851 3,
1852 );
1853 check_number(
1854 r#"
1855 //- minicore: option
1856 const GOAL: u8 = {
1857 let f: fn(u8) -> Option<u8> = Some;
1858 f(3).unwrap_or(2)
1859 };
1860 "#,
1861 3,
1862 );
1863 check_number(
1864 r#"
1865 //- minicore: coerce_unsized, index, slice
1866 enum Foo {
1867 Add2(u8),
1868 Mult3(u8),
1869 }
1870 use Foo::*;
1871 const fn f(x: Foo) -> u8 {
1872 match x {
1873 Add2(x) => x + 2,
1874 Mult3(x) => x * 3,
1875 }
1876 }
1877 const GOAL: u8 = {
1878 let x = [Add2, Mult3];
1879 f(x[0](1)) + f(x[1](5))
1880 };
1881 "#,
1882 18,
1883 );
1884}
1885
1886#[test]
1887fn function_traits() {
1888 check_number(
1889 r#"
1890 //- minicore: fn
1891 fn add2(x: u8) -> u8 {
1892 x + 2
1893 }
1894 fn call(f: impl Fn(u8) -> u8, x: u8) -> u8 {
1895 f(x)
1896 }
1897 fn call_mut(mut f: impl FnMut(u8) -> u8, x: u8) -> u8 {
1898 f(x)
1899 }
1900 fn call_once(f: impl FnOnce(u8) -> u8, x: u8) -> u8 {
1901 f(x)
1902 }
1903 const GOAL: u8 = call(add2, 3) + call_mut(add2, 3) + call_once(add2, 3);
1904 "#,
1905 15,
353b0b11
FG
1906 );
1907 check_number(
1908 r#"
fe692bf9
FG
1909 //- minicore: coerce_unsized, fn
1910 fn add2(x: u8) -> u8 {
1911 x + 2
353b0b11 1912 }
fe692bf9
FG
1913 fn call(f: &dyn Fn(u8) -> u8, x: u8) -> u8 {
1914 f(x)
1915 }
1916 fn call_mut(f: &mut dyn FnMut(u8) -> u8, x: u8) -> u8 {
1917 f(x)
1918 }
1919 const GOAL: u8 = call(&add2, 3) + call_mut(&mut add2, 3);
353b0b11 1920 "#,
fe692bf9 1921 10,
353b0b11
FG
1922 );
1923 check_number(
1924 r#"
fe692bf9
FG
1925 //- minicore: fn
1926 fn add2(x: u8) -> u8 {
1927 x + 2
1928 }
1929 fn call(f: impl Fn(u8) -> u8, x: u8) -> u8 {
1930 f(x)
1931 }
1932 fn call_mut(mut f: impl FnMut(u8) -> u8, x: u8) -> u8 {
1933 f(x)
1934 }
1935 fn call_once(f: impl FnOnce(u8) -> u8, x: u8) -> u8 {
1936 f(x)
1937 }
353b0b11 1938 const GOAL: u8 = {
fe692bf9
FG
1939 let add2: fn(u8) -> u8 = add2;
1940 call(add2, 3) + call_mut(add2, 3) + call_once(add2, 3)
353b0b11
FG
1941 };
1942 "#,
fe692bf9 1943 15,
353b0b11
FG
1944 );
1945 check_number(
1946 r#"
fe692bf9
FG
1947 //- minicore: fn
1948 fn add2(x: u8) -> u8 {
1949 x + 2
1950 }
1951 fn call(f: &&&&&impl Fn(u8) -> u8, x: u8) -> u8 {
1952 f(x)
1953 }
1954 const GOAL: u8 = call(&&&&&add2, 3);
353b0b11 1955 "#,
fe692bf9 1956 5,
353b0b11
FG
1957 );
1958}
1959
1960#[test]
fe692bf9 1961fn dyn_trait() {
353b0b11
FG
1962 check_number(
1963 r#"
fe692bf9
FG
1964 //- minicore: coerce_unsized, index, slice
1965 trait Foo {
1966 fn foo(&self) -> u8 { 10 }
1967 }
1968 struct S1;
1969 struct S2;
1970 struct S3;
1971 impl Foo for S1 {
1972 fn foo(&self) -> u8 { 1 }
1973 }
1974 impl Foo for S2 {
1975 fn foo(&self) -> u8 { 2 }
1976 }
1977 impl Foo for S3 {}
353b0b11 1978 const GOAL: u8 = {
fe692bf9
FG
1979 let x: &[&dyn Foo] = &[&S1, &S2, &S3];
1980 x[0].foo() + x[1].foo() + x[2].foo()
353b0b11
FG
1981 };
1982 "#,
fe692bf9 1983 13,
353b0b11
FG
1984 );
1985 check_number(
1986 r#"
fe692bf9
FG
1987 //- minicore: coerce_unsized, index, slice
1988 trait Foo {
1989 fn foo(&self) -> i32 { 10 }
353b0b11 1990 }
fe692bf9
FG
1991 trait Bar {
1992 fn bar(&self) -> i32 { 20 }
1993 }
1994
1995 struct S;
1996 impl Foo for S {
1997 fn foo(&self) -> i32 { 200 }
1998 }
1999 impl Bar for dyn Foo {
2000 fn bar(&self) -> i32 { 700 }
2001 }
2002 const GOAL: i32 = {
2003 let x: &dyn Foo = &S;
2004 x.bar() + x.foo()
2005 };
353b0b11 2006 "#,
fe692bf9 2007 900,
353b0b11 2008 );
add651ee
FG
2009 check_number(
2010 r#"
2011 //- minicore: coerce_unsized, index, slice
2012 trait A {
2013 fn x(&self) -> i32;
2014 }
2015
2016 trait B: A {}
2017
2018 impl A for i32 {
2019 fn x(&self) -> i32 {
2020 5
2021 }
2022 }
2023
2024 impl B for i32 {
2025
2026 }
2027
2028 const fn f(x: &dyn B) -> i32 {
2029 x.x()
2030 }
2031
2032 const GOAL: i32 = f(&2i32);
2033 "#,
2034 5,
2035 );
2036}
2037
2038#[test]
2039fn coerce_unsized() {
2040 check_number(
2041 r#"
2042//- minicore: coerce_unsized, deref_mut, slice, index, transmute, non_null
2043use core::ops::{Deref, DerefMut, CoerceUnsized};
2044use core::{marker::Unsize, mem::transmute, ptr::NonNull};
2045
2046struct ArcInner<T: ?Sized> {
2047 strong: usize,
2048 weak: usize,
2049 data: T,
2050}
2051
2052pub struct Arc<T: ?Sized> {
2053 inner: NonNull<ArcInner<T>>,
2054}
2055
2056impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
2057
2058const GOAL: usize = {
2059 let x = transmute::<usize, Arc<[i32; 3]>>(12);
2060 let y: Arc<[i32]> = x;
2061 let z = transmute::<Arc<[i32]>, (usize, usize)>(y);
2062 z.1
2063};
2064
2065 "#,
2066 3,
2067 );
fe692bf9
FG
2068}
2069
2070#[test]
2071fn boxes() {
353b0b11
FG
2072 check_number(
2073 r#"
fe692bf9
FG
2074//- minicore: coerce_unsized, deref_mut, slice
2075use core::ops::{Deref, DerefMut};
2076use core::{marker::Unsize, ops::CoerceUnsized};
2077
2078#[lang = "owned_box"]
2079pub struct Box<T: ?Sized> {
2080 inner: *mut T,
2081}
2082impl<T> Box<T> {
2083 fn new(t: T) -> Self {
2084 #[rustc_box]
2085 Box::new(t)
353b0b11 2086 }
fe692bf9
FG
2087}
2088
2089impl<T: ?Sized> Deref for Box<T> {
2090 type Target = T;
2091
2092 fn deref(&self) -> &T {
2093 &**self
2094 }
2095}
2096
2097impl<T: ?Sized> DerefMut for Box<T> {
2098 fn deref_mut(&mut self) -> &mut T {
2099 &mut **self
2100 }
2101}
2102
2103impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
2104
2105const GOAL: usize = {
2106 let x = Box::new(5);
2107 let y: Box<[i32]> = Box::new([1, 2, 3]);
2108 *x + y.len()
2109};
2110"#,
2111 8,
353b0b11
FG
2112 );
2113}
2114
2115#[test]
2116fn array_and_index() {
2117 check_number(
2118 r#"
2119 //- minicore: coerce_unsized, index, slice
2120 const GOAL: u8 = {
2121 let a = [10, 20, 3, 15];
2122 let x: &[u8] = &a;
2123 x[1]
2124 };
2125 "#,
2126 20,
2127 );
2128 check_number(
2129 r#"
2130 //- minicore: coerce_unsized, index, slice
2131 const GOAL: usize = [1, 2, 3][2];"#,
2132 3,
2133 );
2134 check_number(
2135 r#"
2136 //- minicore: coerce_unsized, index, slice
2137 const GOAL: usize = { let a = [1, 2, 3]; let x: &[i32] = &a; x.len() };"#,
2138 3,
2139 );
2140 check_number(
2141 r#"
2142 //- minicore: coerce_unsized, index, slice
fe692bf9
FG
2143 const GOAL: usize = {
2144 let a = [1, 2, 3];
2145 let x: &[i32] = &a;
2146 let y = &*x;
2147 y.len()
2148 };"#,
2149 3,
2150 );
2151 check_number(
2152 r#"
2153 //- minicore: coerce_unsized, index, slice
353b0b11
FG
2154 const GOAL: usize = [1, 2, 3, 4, 5].len();"#,
2155 5,
2156 );
fe692bf9
FG
2157 check_number(
2158 r#"
2159 //- minicore: coerce_unsized, index, slice
2160 const GOAL: [u16; 5] = [1, 2, 3, 4, 5];"#,
2161 1 + (2 << 16) + (3 << 32) + (4 << 48) + (5 << 64),
2162 );
2163 check_number(
2164 r#"
2165 //- minicore: coerce_unsized, index, slice
2166 const GOAL: [u16; 5] = [12; 5];"#,
2167 12 + (12 << 16) + (12 << 32) + (12 << 48) + (12 << 64),
2168 );
2169 check_number(
2170 r#"
2171 //- minicore: coerce_unsized, index, slice
2172 const LEN: usize = 4;
2173 const GOAL: u16 = {
2174 let x = [7; LEN];
2175 x[2]
2176 }"#,
2177 7,
2178 );
353b0b11
FG
2179}
2180
add651ee
FG
2181#[test]
2182fn string() {
2183 check_str(
2184 r#"
2185 //- minicore: coerce_unsized, index, slice
2186 const GOAL: &str = "hello";
2187 "#,
2188 "hello",
2189 );
2190}
2191
353b0b11
FG
2192#[test]
2193fn byte_string() {
2194 check_number(
2195 r#"
2196 //- minicore: coerce_unsized, index, slice
2197 const GOAL: u8 = {
2198 let a = b"hello";
2199 let x: &[u8] = a;
2200 x[0]
2201 };
2202 "#,
2203 104,
2204 );
2205}
2206
fe692bf9
FG
2207#[test]
2208fn c_string() {
2209 check_number(
2210 r#"
2211//- minicore: index, slice
2212#[lang = "CStr"]
2213pub struct CStr {
2214 inner: [u8]
2215}
2216const GOAL: u8 = {
2217 let a = c"hello";
2218 a.inner[0]
2219};
2220 "#,
2221 104,
2222 );
2223 check_number(
2224 r#"
2225//- minicore: index, slice
2226#[lang = "CStr"]
2227pub struct CStr {
2228 inner: [u8]
2229}
2230const GOAL: u8 = {
2231 let a = c"hello";
2232 a.inner[6]
2233};
2234 "#,
2235 0,
2236 );
2237}
2238
064997fb
FG
2239#[test]
2240fn consts() {
2241 check_number(
2242 r#"
2243 const F1: i32 = 1;
2244 const F3: i32 = 3 * F2;
2245 const F2: i32 = 2 * F1;
2246 const GOAL: i32 = F3;
2247 "#,
2248 6,
2249 );
add651ee
FG
2250
2251 check_number(
2252 r#"
2253 const F1: i32 = 2147483647;
2254 const F2: i32 = F1 - 25;
2255 const GOAL: i32 = F2;
2256 "#,
2257 2147483622,
2258 );
2259
2260 check_number(
2261 r#"
2262 const F1: i32 = -2147483648;
2263 const F2: i32 = F1 + 18;
2264 const GOAL: i32 = F2;
2265 "#,
2266 -2147483630,
2267 );
2268
2269 check_number(
2270 r#"
2271 const F1: i32 = 10;
2272 const F2: i32 = F1 - 20;
2273 const GOAL: i32 = F2;
2274 "#,
2275 -10,
2276 );
2277
2278 check_number(
2279 r#"
2280 const F1: i32 = 25;
2281 const F2: i32 = F1 - 25;
2282 const GOAL: i32 = F2;
2283 "#,
2284 0,
2285 );
2286
2287 check_number(
2288 r#"
2289 const A: i32 = -2147483648;
2290 const GOAL: bool = A > 0;
2291 "#,
2292 0,
2293 );
2294
2295 check_number(
2296 r#"
2297 const GOAL: i64 = (-2147483648_i32) as i64;
2298 "#,
2299 -2147483648,
2300 );
064997fb
FG
2301}
2302
fe692bf9
FG
2303#[test]
2304fn statics() {
2305 check_number(
2306 r#"
2307 //- minicore: cell
2308 use core::cell::Cell;
2309 fn f() -> i32 {
2310 static S: Cell<i32> = Cell::new(10);
2311 S.set(S.get() + 1);
2312 S.get()
2313 }
2314 const GOAL: i32 = f() + f() + f();
2315 "#,
2316 36,
2317 );
2318}
2319
2320#[test]
2321fn extern_weak_statics() {
2322 check_number(
2323 r#"
2324 extern "C" {
2325 #[linkage = "extern_weak"]
2326 static __dso_handle: *mut u8;
2327 }
2328 const GOAL: usize = __dso_handle as usize;
2329 "#,
2330 0,
2331 );
2332}
2333
2334#[test]
2335fn from_ne_bytes() {
2336 check_number(
2337 r#"
2338//- minicore: int_impl
2339const GOAL: u32 = u32::from_ne_bytes([44, 1, 0, 0]);
2340 "#,
2341 300,
2342 );
2343}
2344
2b03887a
FG
2345#[test]
2346fn enums() {
2347 check_number(
2348 r#"
2349 enum E {
2350 F1 = 1,
353b0b11
FG
2351 F2 = 2 * E::F1 as isize, // Rustc expects an isize here
2352 F3 = 3 * E::F2 as isize,
2b03887a 2353 }
353b0b11 2354 const GOAL: u8 = E::F3 as u8;
2b03887a
FG
2355 "#,
2356 6,
2357 );
2358 check_number(
2359 r#"
2360 enum E { F1 = 1, F2, }
353b0b11 2361 const GOAL: u8 = E::F2 as u8;
2b03887a
FG
2362 "#,
2363 2,
2364 );
2365 check_number(
2366 r#"
2367 enum E { F1, }
353b0b11 2368 const GOAL: u8 = E::F1 as u8;
2b03887a
FG
2369 "#,
2370 0,
2371 );
fe692bf9 2372 let (db, file_id) = TestDB::with_single_file(
2b03887a 2373 r#"
353b0b11 2374 enum E { A = 1, B }
2b03887a
FG
2375 const GOAL: E = E::A;
2376 "#,
fe692bf9
FG
2377 );
2378 let r = eval_goal(&db, file_id).unwrap();
2379 assert_eq!(try_const_usize(&db, &r), Some(1));
2b03887a
FG
2380}
2381
064997fb
FG
2382#[test]
2383fn const_loop() {
2384 check_fail(
2385 r#"
2386 const F1: i32 = 1 * F3;
2387 const F3: i32 = 3 * F2;
2388 const F2: i32 = 2 * F1;
2389 const GOAL: i32 = F3;
2390 "#,
fe692bf9 2391 |e| e == ConstEvalError::MirLowerError(MirLowerError::Loop),
353b0b11
FG
2392 );
2393}
2394
2395#[test]
2396fn const_transfer_memory() {
2397 check_number(
2398 r#"
add651ee
FG
2399 //- minicore: slice, index, coerce_unsized
2400 const A1: &i32 = &1;
2401 const A2: &i32 = &10;
2402 const A3: [&i32; 3] = [&1, &2, &100];
2403 const A4: (i32, &i32) = (1, &1000);
2404 const GOAL: i32 = *A1 + *A2 + *A3[2] + *A4.1;
353b0b11 2405 "#,
add651ee 2406 1111,
064997fb
FG
2407 );
2408}
2409
fe692bf9
FG
2410#[test]
2411fn anonymous_const_block() {
2412 check_number(
2413 r#"
2414 extern "rust-intrinsic" {
2415 pub fn size_of<T>() -> usize;
2416 }
2417
2418 const fn f<T>() -> usize {
2419 let r = const { size_of::<T>() };
2420 r
2421 }
2422
2423 const GOAL: usize = {
2424 let x = const { 2 + const { 3 } };
2425 let y = f::<i32>();
2426 x + y
2427 };
2428 "#,
2429 9,
2430 );
2431}
2432
064997fb
FG
2433#[test]
2434fn const_impl_assoc() {
2435 check_number(
2436 r#"
2437 struct U5;
2438 impl U5 {
2439 const VAL: usize = 5;
2440 }
fe692bf9 2441 const GOAL: usize = U5::VAL + <U5>::VAL;
064997fb 2442 "#,
fe692bf9 2443 10,
064997fb
FG
2444 );
2445}
2446
2447#[test]
353b0b11
FG
2448fn const_generic_subst_fn() {
2449 check_number(
2450 r#"
2451 const fn f<const A: usize>(x: usize) -> usize {
2452 A * x + 5
2453 }
2454 const GOAL: usize = f::<2>(3);
2455 "#,
2456 11,
2457 );
fe692bf9
FG
2458 check_number(
2459 r#"
2460 fn f<const N: usize>(x: [i32; N]) -> usize {
2461 N
2462 }
2463
2464 trait ArrayExt {
2465 fn f(self) -> usize;
2466 }
2467
2468 impl<T, const N: usize> ArrayExt for [T; N] {
2469 fn g(self) -> usize {
2470 f(self)
2471 }
2472 }
2473
2474 const GOAL: usize = f([1, 2, 5]);
2475 "#,
2476 3,
2477 );
2478}
2479
2480#[test]
2481fn layout_of_type_with_associated_type_field_defined_inside_body() {
2482 check_number(
2483 r#"
2484trait Tr {
2485 type Ty;
2486}
2487
2488struct St<T: Tr>(T::Ty);
2489
2490const GOAL: i64 = {
2491 // if we move `St2` out of body, the test will fail, as we don't see the impl anymore. That
2492 // case will probably be rejected by rustc in some later edition, but we should support this
2493 // case.
2494 struct St2;
2495
2496 impl Tr for St2 {
2497 type Ty = i64;
2498 }
2499
2500 struct Goal(St<St2>);
2501
2502 let x = Goal(St(5));
2503 x.0.0
2504};
2505"#,
2506 5,
2507 );
353b0b11
FG
2508}
2509
2510#[test]
2511fn const_generic_subst_assoc_const_impl() {
fe692bf9 2512 check_number(
064997fb
FG
2513 r#"
2514 struct Adder<const N: usize, const M: usize>;
2515 impl<const N: usize, const M: usize> Adder<N, M> {
2516 const VAL: usize = N + M;
2517 }
2518 const GOAL: usize = Adder::<2, 3>::VAL;
2519 "#,
fe692bf9
FG
2520 5,
2521 );
2522}
2523
2524#[test]
2525fn associated_types() {
2526 check_number(
2527 r#"
2528 trait Tr {
2529 type Item;
2530 fn get_item(&self) -> Self::Item;
2531 }
2532
2533 struct X(i32);
2534 struct Y(i32);
2535
2536 impl Tr for X {
2537 type Item = Y;
2538 fn get_item(&self) -> Self::Item {
2539 Y(self.0 + 2)
2540 }
2541 }
2542
2543 fn my_get_item<T: Tr>(x: T) -> <T as Tr>::Item {
2544 x.get_item()
2545 }
2546
2547 const GOAL: i32 = my_get_item(X(3)).0;
2548 "#,
2549 5,
064997fb
FG
2550 );
2551}
2552
2553#[test]
2554fn const_trait_assoc() {
fe692bf9 2555 check_number(
064997fb
FG
2556 r#"
2557 struct U0;
2558 trait ToConst {
2559 const VAL: usize;
2560 }
2561 impl ToConst for U0 {
2562 const VAL: usize = 0;
2563 }
fe692bf9
FG
2564 impl ToConst for i32 {
2565 const VAL: usize = 32;
2566 }
2567 const GOAL: usize = U0::VAL + i32::VAL;
2568 "#,
2569 32,
2570 );
add651ee
FG
2571 check_number(
2572 r#"
2573 //- /a/lib.rs crate:a
2574 pub trait ToConst {
2575 const VAL: usize;
2576 }
2577 pub const fn to_const<T: ToConst>() -> usize {
2578 T::VAL
2579 }
2580 //- /main.rs crate:main deps:a
2581 use a::{ToConst, to_const};
2582 struct U0;
2583 impl ToConst for U0 {
2584 const VAL: usize = 5;
2585 }
2586 const GOAL: usize = to_const::<U0>();
2587 "#,
2588 5,
2589 );
2590 check_number(
2591 r#"
2592 //- minicore: size_of, fn
2593 //- /a/lib.rs crate:a
2594 use core::mem::size_of;
2595 pub struct S<T>(T);
2596 impl<T> S<T> {
2597 pub const X: usize = {
2598 let k: T;
2599 let f = || core::mem::size_of::<T>();
2600 f()
2601 };
2602 }
2603 //- /main.rs crate:main deps:a
2604 use a::{S};
2605 trait Tr {
2606 type Ty;
2607 }
2608 impl Tr for i32 {
2609 type Ty = u64;
2610 }
2611 struct K<T: Tr>(<T as Tr>::Ty);
2612 const GOAL: usize = S::<K<i32>>::X;
2613 "#,
2614 8,
2615 );
fe692bf9
FG
2616 check_number(
2617 r#"
2618 struct S<T>(*mut T);
2619
2620 trait MySized: Sized {
2621 const SIZE: S<Self> = S(1 as *mut Self);
2622 }
2623
2624 impl MySized for i32 {
2625 const SIZE: S<i32> = S(10 as *mut i32);
2626 }
2627
2628 impl MySized for i64 {
2629 }
2630
2631 const fn f<T: MySized>() -> usize {
2632 T::SIZE.0 as usize
2633 }
2634
2635 const GOAL: usize = f::<i32>() + f::<i64>() * 2;
2636 "#,
2637 12,
2638 );
2639}
2640
353b0b11
FG
2641#[test]
2642fn exec_limits() {
add651ee
FG
2643 if skip_slow_tests() {
2644 return;
2645 }
2646
353b0b11
FG
2647 check_fail(
2648 r#"
2649 const GOAL: usize = loop {};
2650 "#,
fe692bf9 2651 |e| e == ConstEvalError::MirEvalError(MirEvalError::ExecutionLimitExceeded),
353b0b11
FG
2652 );
2653 check_fail(
2654 r#"
2655 const fn f(x: i32) -> i32 {
2656 f(x + 1)
2657 }
2658 const GOAL: i32 = f(0);
2659 "#,
add651ee 2660 |e| e == ConstEvalError::MirEvalError(MirEvalError::ExecutionLimitExceeded),
353b0b11
FG
2661 );
2662 // Reasonable code should still work
2663 check_number(
2664 r#"
2665 const fn nth_odd(n: i32) -> i32 {
2666 2 * n - 1
2667 }
2668 const fn f(n: i32) -> i32 {
2669 let sum = 0;
2670 let i = 0;
2671 while i < n {
2672 i = i + 1;
2673 sum = sum + nth_odd(i);
2674 }
2675 sum
2676 }
add651ee 2677 const GOAL: i32 = f(1000);
353b0b11 2678 "#,
add651ee
FG
2679 1000 * 1000,
2680 );
2681}
2682
2683#[test]
2684fn memory_limit() {
2685 check_fail(
2686 r#"
2687 extern "Rust" {
2688 #[rustc_allocator]
2689 fn __rust_alloc(size: usize, align: usize) -> *mut u8;
2690 }
2691
2692 const GOAL: u8 = unsafe {
2693 __rust_alloc(30_000_000_000, 1); // 30GB
2694 2
2695 };
2696 "#,
2697 |e| {
2698 e == ConstEvalError::MirEvalError(MirEvalError::Panic(
2699 "Memory allocation of 30000000000 bytes failed".to_string(),
2700 ))
2701 },
353b0b11
FG
2702 );
2703}
2704
2705#[test]
2706fn type_error() {
fe692bf9 2707 check_fail(
353b0b11
FG
2708 r#"
2709 const GOAL: u8 = {
2710 let x: u16 = 2;
2711 let y: (u8, u8) = x;
2712 y.0
2713 };
2714 "#,
fe692bf9
FG
2715 |e| matches!(e, ConstEvalError::MirLowerError(MirLowerError::TypeMismatch(_))),
2716 );
2717}
2718
add651ee
FG
2719#[test]
2720fn unsized_field() {
2721 check_number(
2722 r#"
2723 //- minicore: coerce_unsized, index, slice, transmute
2724 use core::mem::transmute;
2725
2726 struct Slice([usize]);
2727 struct Slice2(Slice);
2728
2729 impl Slice2 {
2730 fn as_inner(&self) -> &Slice {
2731 &self.0
2732 }
2733
2734 fn as_bytes(&self) -> &[usize] {
2735 &self.as_inner().0
2736 }
2737 }
2738
2739 const GOAL: usize = unsafe {
2740 let x: &[usize] = &[1, 2, 3];
2741 let x: &Slice2 = transmute(x);
2742 let x = x.as_bytes();
2743 x[0] + x[1] + x[2] + x.len() * 100
2744 };
2745 "#,
2746 306,
2747 );
2748}
2749
fe692bf9
FG
2750#[test]
2751fn unsized_local() {
2752 check_fail(
2753 r#"
2754 //- minicore: coerce_unsized, index, slice
2755 const fn x() -> SomeUnknownTypeThatDereferenceToSlice {
2756 SomeUnknownTypeThatDereferenceToSlice
2757 }
2758
2759 const GOAL: u16 = {
2760 let y = x();
2761 let z: &[u16] = &y;
2762 z[1]
2763 };
2764 "#,
2765 |e| matches!(e, ConstEvalError::MirLowerError(MirLowerError::UnsizedTemporary(_))),
064997fb
FG
2766 );
2767}