1 use base_db
::{fixture::WithFixture, FileId}
;
2 use chalk_ir
::Substitution
;
3 use hir_def
::db
::DefDatabase
;
4 use test_utils
::skip_slow_tests
;
7 consteval
::try_const_usize
, db
::HirDatabase
, mir
::pad16
, test_db
::TestDB
, Const
, ConstScalar
,
12 super::mir
::{MirEvalError, MirLowerError}
,
18 fn simplify(e
: ConstEvalError
) -> ConstEvalError
{
20 ConstEvalError
::MirEvalError(MirEvalError
::InFunction(e
, _
)) => {
21 simplify(ConstEvalError
::MirEvalError(*e
))
28 fn 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"),
33 assert
!(error(simplify(e
.clone())), "Actual error was: {}", pretty_print_err(e
, db
))
39 fn check_number(ra_fixture
: &str, answer
: i128
) {
40 check_answer(ra_fixture
, |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))
51 fn 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");
61 "Bytes differ. In string form: actual = {}, expected = {answer}",
62 String
::from_utf8_lossy(bytes
)
68 fn 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();
71 let r
= match eval_goal(&db
, file_id
) {
74 let err
= pretty_print_err(e
, db
);
75 panic
!("Error in evaluating goal: {}", err
);
78 match &r
.data(Interner
).value
{
79 chalk_ir
::ConstValue
::Concrete(c
) => match &c
.interned
{
80 ConstScalar
::Bytes(b
, mm
) => {
83 x
=> panic
!("Expected number but found {:?}", x
),
85 _
=> panic
!("result of const eval wasn't a concrete const"),
89 fn pretty_print_err(e
: ConstEvalError
, db
: TestDB
) -> String
{
90 let mut err
= String
::new();
91 let span_formatter
= |file
, range
| format
!("{:?} {:?}", file
, range
);
93 ConstEvalError
::MirLowerError(e
) => e
.pretty_print(&mut err
, &db
, span_formatter
),
94 ConstEvalError
::MirEvalError(e
) => e
.pretty_print(&mut err
, &db
, span_formatter
),
100 fn eval_goal(db
: &TestDB
, file_id
: FileId
) -> Result
<Const
, ConstEvalError
> {
101 let module_id
= db
.module_for_file(file_id
);
102 let def_map
= module_id
.def_map(db
);
103 let scope
= &def_map
[module_id
.local_id
].scope
;
106 .find_map(|x
| match x
{
107 hir_def
::ModuleDefId
::ConstId(x
) => {
108 if db
.const_data(x
).name
.as_ref()?
.display(db
).to_string() == "GOAL" {
116 .expect("No const named GOAL found in the test");
117 db
.const_eval(const_id
.into(), Substitution
::empty(Interner
), None
)
122 check_number(r
#"const GOAL: usize = 2 + 2;"#, 4);
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);
130 check_number(r
#"const GOAL: u8 = !0 & !(!0 >> 1)"#, 128);
131 check_number(r
#"const GOAL: i8 = !0 & !(!0 >> 1)"#, 0);
132 check_number(r
#"const GOAL: i8 = 1 << 7"#, (1i8 << 7) as i128);
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()))
137 check_number(r
#"const GOAL: i32 = 100000000i32 << 11"#, (100000000i32 << 11) as i128);
141 fn floating_point() {
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)),
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)),
151 r
#"const GOAL: f32 = -90.0 + 36.0;"#,
152 i128
::from_le_bytes(pad16(&f32::to_le_bytes(-54.0), true)),
158 check_number(r
#"const GOAL: usize = 12 as *const i32 as usize"#, 12);
161 //- minicore: coerce_unsized, index, slice
163 let a = [10, 20, 3, 15];
165 let y: *const [i32] = x;
166 let z = y as *const i32;
174 //- minicore: coerce_unsized, index, slice
185 //- minicore: coerce_unsized, index, slice
186 const GOAL: usize = {
187 let a = &[10, 20, 30, 40] as &[i32];
195 //- minicore: coerce_unsized, index, slice
200 const GOAL: usize = {
201 let a = [10, 20, 3, 15];
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 };
216 check_number(r
#"const GOAL: i32 = -12i8 as i32"#, -12);
220 fn raw_pointer_equality() {
223 //- minicore: copy, eq
226 let p1 = a as *const i32;
227 let p2 = a as *const i32;
239 //- minicore: transmute
240 use core::mem::transmute;
241 const GOAL: usize = {
246 |b
, _
| assert_eq
!(b
[0] % 8, 0),
250 //- minicore: transmute
251 use core::mem::transmute;
253 const GOAL: usize = transmute(&X);
255 |b
, _
| assert_eq
!(b
[0] % 8, 0),
263 const GOAL: usize = {
277 const GOAL: usize = {
290 fn method(&mut self, x: i32) {
291 self.0 = 2 * self.0 + x;
305 fn reference_autoderef() {
308 const GOAL: usize = {
311 let y: &mut usize = &mut y;
320 const GOAL: usize = {
331 struct Foo<T> { x: T }
333 fn foo(&mut self) -> T { self.x }
335 fn f(i: &mut &mut Foo<Foo<i32>>) -> i32 {
338 fn g(i: Foo<Foo<i32>>) -> i32 {
341 const GOAL: i32 = f(&mut &mut Foo { x: Foo { x: 3 } }) + g(Foo { x: Foo { x: 5 } });
348 fn overloaded_deref() {
351 //- minicore: deref_mut
354 impl core::ops::Deref for Foo {
356 fn deref(&self) -> &i32 {
372 fn overloaded_deref_autoref() {
375 //- minicore: deref_mut
379 impl core::ops::Deref for Foo {
381 fn deref(&self) -> &Bar {
387 fn method(&self) -> i32 {
392 const GOAL: i32 = Foo.method();
399 fn overloaded_index() {
405 impl core::ops::Index<usize> for Foo {
407 fn index(&self, index: usize) -> &i32 {
416 impl core::ops::IndexMut<usize> for Foo {
417 fn index_mut(&mut self, index: usize) -> &mut i32 {
427 (Foo[2]) + (Foo[7]) + (*&Foo[2]) + (*&Foo[7]) + (*&mut Foo[2]) + (*&mut Foo[7])
435 fn overloaded_binop() {
447 impl core::ops::Add for Color {
449 fn add(self, rhs: Color) -> Self::Output {
454 impl core::ops::AddAssign for Color {
455 fn add_assign(&mut self, rhs: Color) {
464 x == Yellow && y == Red && Red + Green == Yellow && Red + Red == Yellow && Yellow + Green == Yellow
472 impl core::ops::Add for usize {
474 fn add(self, rhs: usize) -> Self::Output {
479 impl core::ops::AddAssign for usize {
480 fn add_assign(&mut self, rhs: usize) {
486 pub trait Shl<Rhs = Self> {
489 fn shl(self, rhs: Rhs) -> Self::Output;
492 impl Shl<u8> for usize {
495 fn shl(self, rhs: u8) -> Self::Output {
500 const GOAL: usize = {
513 const fn f(x: usize) -> usize {
516 const GOAL: usize = f(3);
522 const fn add(x: usize, y: usize) -> usize {
525 const GOAL: usize = add(add(1, 2), add(3, add(4, 5)));
578 fn trait_method_inside_block() {
585 fn outer() -> impl Twait {
588 impl Twait for Stwuct {
593 fn f() -> impl Twait {
600 const GOAL: i32 = outer().a();
622 impl<T: Foo> Foo for Succ<T> {
628 const GOAL: u8 = Succ(Succ(())).f();
644 fn foof<T: Foo>(x: T, y: T) -> u8 {
648 const GOAL: u8 = foof(2, 5);
654 fn bar<A, B>(a: A, b: B) -> B {
657 const GOAL: u8 = bar("hello", 12);
663 const fn y<T>(b: T) -> (T, ) {
667 const GOAL: u8 = y(2).0;
673 //- minicore: coerce_unsized, index, slice
674 fn bar<A, B>(a: A, b: B) -> B {
677 fn foo<T>(x: [T; 2]) -> T {
681 const GOAL: u8 = foo([2, 5]);
701 fn foof(x: impl Foo, y: impl Foo) -> impl Foo {
705 const GOAL: u8 = foof(2, 5).f();
711 struct Foo<T>(T, T, (T, T));
713 fn sum(&self) -> i64;
716 fn sum(&self) -> i64 {
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()
726 fn foo() -> Foo<impl S> {
728 Foo(1i64, 2, (3, 4)),
731 Foo(9, 10, (11, 12)),
732 Foo(13, 14, (15, 16)),
736 const GOAL: i64 = foo().sum();
746 const fn f(b: bool) -> u8 {
747 if b { 1 } else { 10 }
750 const GOAL: u8 = f(true) + f(true) + f(false);
756 const fn max(a: i32, b: i32) -> i32 {
757 if a < b { b } else { a }
760 const GOAL: i32 = max(max(1, max(10, 3)), 0-122);
767 const fn max(a: &i32, b: &i32) -> &i32 {
768 if *a < *b { b } else { a }
771 const GOAL: i32 = *max(max(&1, max(&10, &3)), &5);
865 //- minicore: iterator
872 impl Iterator for Range {
874 fn next(&mut self) -> Option<u8> {
875 if self.start >= self.end {
879 self.start = self.start + 1;
887 let ar = Range { start: 1, end: 11 };
903 const GOAL: i32 = (1..2).start + (20..10).end + (100..=200).start + (2000..=1000).end
904 + (10000..).start + (..100000).end + (..=1000000).end;
914 const fn fact(k: i32) -> i32 {
915 if k > 0 { fact(k - 1) * k } else { 1 }
918 const GOAL: i32 = fact(5);
934 let p = Point { x: 5, y: 2 };
937 let q = Point { y, x };
938 p.x + p.y + p.x + q.y + q.y + q.x
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
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
987 let p = U { f1: 0x0123ABCD0123DCBA };
988 let p = unsafe { p.f2 };
992 0x0123ABCD * 2 + 0x0123DCBA,
1001 let a = (10, 20, 3, 15);
1010 let mut a = (10, 20, 3, 15);
1012 a.0 + a.1 + a.2 + a.3
1019 struct TupleLike(i32, i64, u8, u16);
1021 let a = TupleLike(10, 20, 3, 15);
1022 let TupleLike(b, .., c) = a;
1023 a.1 * 100 + b as i64 + c as i64
1031 match (&(2 + 2), &4) {
1032 (left_val, right_val) => {
1033 if !(*left_val == *right_val) {
1047 fn path_pattern_matching() {
1059 const MY_SEASON: Season = Summer;
1062 const FALL: Season = Fall;
1065 const fn f(x: Season) -> i32 {
1073 const GOAL: i32 = f(Spring) + 10 * f(Summer) + 100 * f(Fall) + 1000 * f(Winter);
1080 fn pattern_matching_literal() {
1083 const fn f(x: i32) -> i32 {
1090 const GOAL: i32 = f(-1) + f(1) + f(0) + f(-5);
1096 const fn f(x: &str) -> i32 {
1105 const GOAL: i32 = f("f") + f("foo") * 2 + f("") * 3 + f("bar") * 4;
1112 fn pattern_matching_range() {
1115 pub const L: i32 = 6;
1117 pub const R: i32 = 100;
1119 const fn f(x: i32) -> i32 {
1122 L..=x::R => x * 100,
1126 const GOAL: i32 = f(-1) + f(2) + f(100) + f(-2) + f(1000);
1133 fn pattern_matching_slice() {
1136 //- minicore: slice, index, coerce_unsized, copy
1137 const fn f(x: &[usize]) -> usize {
1139 [a, b @ .., c, d] => *a + b.len() + *c + *d,
1142 const GOAL: usize = f(&[10, 20, 3, 15, 1000, 60, 16]);
1148 //- minicore: slice, index, coerce_unsized, copy
1149 const fn f(x: &[usize]) -> usize {
1154 [a, b @ .., c, d] => *a + b.len() + *c + *d,
1157 const GOAL: usize = f(&[]) + f(&[10]) + f(&[100, 100])
1158 + f(&[1000, 1000, 1000]) + f(&[10000, 57, 34, 46, 10000, 10000]);
1165 fn pattern_matching_ergonomics() {
1168 const fn f(x: &(u8, u8)) -> u8 {
1173 const GOAL: u8 = f(&(2, 3));
1190 fn destructing_assignment() {
1194 const fn f(i: &mut u8) -> &mut u8 {
1209 let (mut a, mut b) = (2, 5);
1218 struct Point { x: i32, y: i32 }
1220 let mut p = Point { x: 5, y: 6 };
1221 (p.x, _) = (p.y, p.x);
1233 const fn f(x: &(u8, u8)) -> u8 {
1237 const GOAL: u8 = f(&(2, 3));
1243 enum SingleVariant {
1246 const fn f(x: &&&&&SingleVariant) -> u8 {
1247 let SingleVariant::Var(a, b) = x;
1250 const GOAL: u8 = f(&&&&&SingleVariant::Var(2, 3));
1256 //- minicore: option
1257 const fn f(x: Option<i32>) -> i32 {
1258 let Some(x) = x else { return 10 };
1261 const GOAL: i32 = f(Some(1000)) + f(None);
1268 fn function_param_patterns() {
1271 const fn f((a, b): &(u8, u8)) -> u8 {
1274 const GOAL: u8 = f(&(2, 3));
1280 const fn f(c @ (a, b): &(u8, u8)) -> u8 {
1281 *a + *b + c.0 + (*c).1
1283 const GOAL: u8 = f(&(2, 3));
1289 const fn f(ref a: u8) -> u8 {
1292 const GOAL: u8 = f(2);
1300 const fn f(&self, (a, b): &(u8, u8)) -> u8 {
1304 const GOAL: u8 = Foo(4).f(&(2, 3));
1314 //- minicore: option
1315 fn f(x: Option<i32>) -> i32 {
1317 y if let Some(42) = y => 42000,
1322 const GOAL: i32 = f(Some(42)) + f(Some(2)) + f(None);
1329 fn result_layout_niche_optimization() {
1332 //- minicore: option, result
1333 const GOAL: i32 = match Some(2).ok_or(Some(2)) {
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,
1351 const GOAL: Result<AlignmentEnum64, ()> = {
1352 let align = Err(());
1356 0, // It is 0 since result is niche encoded and 1 is valid for `AlignmentEnum64`
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,
1370 let align = Ok::<_, ()>(AlignmentEnum64::_Align1Shl0);
1385 //- minicore: option
1398 //- minicore: option
1399 fn f(x: Option<Option<i32>>) -> i32 {
1400 if let Some(y) = x && let Some(z) = y {
1402 } else if let Some(y) = x {
1408 const GOAL: i32 = f(Some(Some(10))) + f(Some(None)) + f(None);
1414 //- minicore: option
1427 //- minicore: option
1428 const GOAL: Option<&u8> = None;
1442 impl From<E1> for E2 {
1443 fn from(E1(x): E1) -> Self {
1448 let x: E2 = E1(2).into();
1457 fn closure_clone() {
1460 //- minicore: clone, fn
1463 impl Clone for S(u8) {
1464 fn clone(&self) -> S {
1472 let cl = cl.clone();
1481 fn builtin_derive_macro() {
1484 //- minicore: clone, derive, builtin_impls
1491 struct X(i32, Z, i64)
1495 field2: ((i32, u8), i64),
1499 let x = X(2, Z::Foo(Y { field1: 4, field2: ((32, 5), 12) }), 8);
1501 let Z::Foo(t) = x.1;
1509 //- minicore: default, derive, builtin_impls
1511 struct X(i32, Y, i64)
1519 let x = X::default();
1531 //- minicore: option, try
1532 const fn f(x: Option<i32>, y: Option<i32>) -> Option<i32> {
1535 const fn g(x: Option<i32>, y: Option<i32>) -> i32 {
1541 const GOAL: i32 = g(Some(10), Some(20)) + g(Some(30), None) + g(None, Some(40)) + g(None, None);
1547 //- minicore: result, try, from
1551 impl From<E1> for E2 {
1552 fn from(E1(x): E1) -> Self {
1557 const fn f(x: Result<i32, E1>) -> Result<i32, E2> {
1560 const fn g(x: Result<i32, E1>) -> i32 {
1563 Err(E2(k)) => 5 * k,
1566 const GOAL: i32 = g(Ok(2)) + g(Err(E1(3)));
1576 //- minicore: option, try
1577 const fn g(x: Option<i32>, y: Option<i32>) -> i32 {
1578 let r = try { x? * y? };
1584 const GOAL: i32 = g(Some(10), Some(20)) + g(Some(30), None) + g(None, Some(40)) + g(None, None);
1594 //- minicore: fn, copy
1605 //- minicore: fn, copy
1608 let c = |(a, b): &(i32, i32)| *a + *b + y;
1616 //- minicore: fn, copy
1631 //- minicore: fn, copy
1633 let c: fn(i32) -> i32 = |x| 2 * x;
1641 //- minicore: fn, copy
1644 fn mult(&mut self, n: i32) {
1667 let r = c()()()()()();
1676 fn manual_fn_trait_impl() {
1679 //- minicore: fn, copy
1682 impl FnOnce<(i32, i32)> for S {
1685 extern "rust-call" fn call_once(self, arg: (i32, i32)) -> i32 {
1686 arg.0 + arg.1 + self.0
1700 fn closure_capture_unsized_type() {
1703 //- minicore: fn, copy, slice, index, coerce_unsized
1704 fn f<T: A>(x: &<T as A>::Ty) -> &<T as A>::Ty {
1718 let k: &[u8] = &[1, 2, 3];
1719 let k = f::<i32>(k);
1728 fn closure_and_impl_fn() {
1731 //- minicore: fn, copy
1732 fn closure_wrapper<F: FnOnce() -> i32>(c: F) -> impl FnOnce() -> F {
1738 let c = closure_wrapper(|| y);
1746 //- minicore: fn, copy
1747 fn f<T, F: Fn() -> T>(t: F) -> impl Fn() -> T {
1751 const GOAL: i32 = f(|| 2)();
1770 //- minicore: option
1771 const fn f(x: Option<i32>) -> i32 {
1772 let (Some(a) | Some(a)) = x else { return 2; };
1775 const GOAL: i32 = f(Some(10)) + f(None);
1781 //- minicore: option
1782 const fn f(x: Option<i32>, y: Option<i32>) -> i32 {
1784 (Some(x), Some(y)) => x * y,
1785 (Some(a), _) | (_, Some(a)) => a,
1789 const GOAL: i32 = f(Some(10), Some(20)) + f(Some(30), None) + f(None, Some(40)) + f(None, None);
1796 fn function_pointer_in_constants() {
1802 const FOO: Foo = Foo { f: add2 };
1803 fn add2(x: u8) -> u8 {
1806 const GOAL: u8 = (FOO.f)(3);
1813 fn function_pointer_and_niche_optimization() {
1816 //- minicore: option
1818 let f: fn(i32) -> i32 = |x| x + 2;
1831 fn function_pointer() {
1834 fn add2(x: u8) -> u8 {
1846 fn add2(x: u8) -> u8 {
1850 let plus2: fn(u8) -> u8 = add2;
1858 fn add2(x: u8) -> u8 {
1862 let plus2 = add2 as fn(u8) -> u8;
1870 //- minicore: coerce_unsized, index, slice
1871 fn add2(x: u8) -> u8 {
1874 fn mult3(x: u8) -> u8 {
1878 let x = [add2, mult3];
1887 fn enum_variant_as_function() {
1890 //- minicore: option
1900 //- minicore: option
1902 let f: fn(u8) -> Option<u8> = Some;
1910 //- minicore: coerce_unsized, index, slice
1916 const fn f(x: Foo) -> u8 {
1923 let x = [Add2, Mult3];
1924 f(x[0](1)) + f(x[1](5))
1932 fn function_traits() {
1936 fn add2(x: u8) -> u8 {
1939 fn call(f: impl Fn(u8) -> u8, x: u8) -> u8 {
1942 fn call_mut(mut f: impl FnMut(u8) -> u8, x: u8) -> u8 {
1945 fn call_once(f: impl FnOnce(u8) -> u8, x: u8) -> u8 {
1948 const GOAL: u8 = call(add2, 3) + call_mut(add2, 3) + call_once(add2, 3);
1954 //- minicore: coerce_unsized, fn
1955 fn add2(x: u8) -> u8 {
1958 fn call(f: &dyn Fn(u8) -> u8, x: u8) -> u8 {
1961 fn call_mut(f: &mut dyn FnMut(u8) -> u8, x: u8) -> u8 {
1964 const GOAL: u8 = call(&add2, 3) + call_mut(&mut add2, 3);
1971 fn add2(x: u8) -> u8 {
1974 fn call(f: impl Fn(u8) -> u8, x: u8) -> u8 {
1977 fn call_mut(mut f: impl FnMut(u8) -> u8, x: u8) -> u8 {
1980 fn call_once(f: impl FnOnce(u8) -> u8, x: u8) -> u8 {
1984 let add2: fn(u8) -> u8 = add2;
1985 call(add2, 3) + call_mut(add2, 3) + call_once(add2, 3)
1993 fn add2(x: u8) -> u8 {
1996 fn call(f: &&&&&impl Fn(u8) -> u8, x: u8) -> u8 {
1999 const GOAL: u8 = call(&&&&&add2, 3);
2009 //- minicore: coerce_unsized, index, slice
2011 fn foo(&self) -> u8 { 10 }
2017 fn foo(&self) -> u8 { 1 }
2020 fn foo(&self) -> u8 { 2 }
2024 let x: &[&dyn Foo] = &[&S1, &S2, &S3];
2025 x[0].foo() + x[1].foo() + x[2].foo()
2032 //- minicore: coerce_unsized, index, slice
2034 fn foo(&self) -> i32 { 10 }
2037 fn bar(&self) -> i32 { 20 }
2042 fn foo(&self) -> i32 { 200 }
2044 impl Bar for dyn Foo {
2045 fn bar(&self) -> i32 { 700 }
2048 let x: &dyn Foo = &S;
2056 //- minicore: coerce_unsized, index, slice
2064 fn x(&self) -> i32 {
2073 const fn f(x: &dyn B) -> i32 {
2077 const GOAL: i32 = f(&2i32);
2084 fn coerce_unsized() {
2087 //- minicore: coerce_unsized, deref_mut, slice, index, transmute, non_null
2088 use core::ops::{Deref, DerefMut, CoerceUnsized};
2089 use core::{marker::Unsize, mem::transmute, ptr::NonNull};
2091 struct ArcInner<T: ?Sized> {
2097 pub struct Arc<T: ?Sized> {
2098 inner: NonNull<ArcInner<T>>,
2101 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
2103 const 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);
2119 //- minicore: coerce_unsized, deref_mut, slice
2120 use core::ops::{Deref, DerefMut};
2121 use core::{marker::Unsize, ops::CoerceUnsized};
2123 #[lang = "owned_box"]
2124 pub struct Box<T: ?Sized> {
2128 fn new(t: T) -> Self {
2134 impl<T: ?Sized> Deref for Box<T> {
2137 fn deref(&self) -> &T {
2142 impl<T: ?Sized> DerefMut for Box<T> {
2143 fn deref_mut(&mut self) -> &mut T {
2148 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
2150 const GOAL: usize = {
2151 let x = Box::new(5);
2152 let y: Box<[i32]> = Box::new([1, 2, 3]);
2161 fn array_and_index() {
2164 //- minicore: coerce_unsized, index, slice
2166 let a = [10, 20, 3, 15];
2175 //- minicore: coerce_unsized, index, slice
2176 const GOAL: usize = [1, 2, 3][2];"#,
2181 //- minicore: coerce_unsized, index, slice
2182 const GOAL: usize = { let a = [1, 2, 3]; let x: &[i32] = &a; x.len() };"#,
2187 //- minicore: coerce_unsized, index, slice
2188 const GOAL: usize = {
2198 //- minicore: coerce_unsized, index, slice
2199 const GOAL: usize = [1, 2, 3, 4, 5].len();"#,
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),
2210 //- minicore: coerce_unsized, index, slice
2211 const GOAL: [u16; 5] = [12; 5];"#,
2212 12 + (12 << 16) + (12 << 32) + (12 << 48) + (12 << 64),
2216 //- minicore: coerce_unsized, index, slice
2217 const LEN: usize = 4;
2230 //- minicore: coerce_unsized, index, slice
2231 const GOAL: &str = "hello";
2241 //- minicore: coerce_unsized, index, slice
2256 //- minicore: index, slice
2270 //- minicore: index, slice
2289 const F3: i32 = 3 * F2;
2290 const F2: i32 = 2 * F1;
2291 const GOAL: i32 = F3;
2298 const F1: i32 = 2147483647;
2299 const F2: i32 = F1 - 25;
2300 const GOAL: i32 = F2;
2307 const F1: i32 = -2147483648;
2308 const F2: i32 = F1 + 18;
2309 const GOAL: i32 = F2;
2317 const F2: i32 = F1 - 20;
2318 const GOAL: i32 = F2;
2326 const F2: i32 = F1 - 25;
2327 const GOAL: i32 = F2;
2334 const A: i32 = -2147483648;
2335 const GOAL: bool = A > 0;
2342 const GOAL: i64 = (-2147483648_i32) as i64;
2353 use core::cell::Cell;
2355 static S: Cell<i32> = Cell::new(10);
2359 const GOAL: i32 = f() + f() + f();
2366 fn extern_weak_statics() {
2370 #[linkage = "extern_weak"]
2371 static __dso_handle: *mut u8;
2373 const GOAL: usize = __dso_handle as usize;
2380 fn from_ne_bytes() {
2383 //- minicore: int_impl
2384 const GOAL: u32 = u32::from_ne_bytes([44, 1, 0, 0]);
2396 F2 = 2 * E::F1 as isize, // Rustc expects an isize here
2397 F3 = 3 * E::F2 as isize,
2399 const GOAL: u8 = E::F3 as u8;
2405 enum E { F1 = 1, F2, }
2406 const GOAL: u8 = E::F2 as u8;
2413 const GOAL: u8 = E::F1 as u8;
2417 let (db
, file_id
) = TestDB
::with_single_file(
2420 const GOAL: E = E::A;
2423 let r
= eval_goal(&db
, file_id
).unwrap();
2424 assert_eq
!(try_const_usize(&db
, &r
), Some(1));
2431 const F1: i32 = 1 * F3;
2432 const F3: i32 = 3 * F2;
2433 const F2: i32 = 2 * F1;
2434 const GOAL: i32 = F3;
2436 |e
| e
== ConstEvalError
::MirLowerError(MirLowerError
::Loop
),
2441 fn const_transfer_memory() {
2444 //- minicore: slice, index, coerce_unsized, option
2445 const A1: &i32 = &1;
2446 const A2: &i32 = &10;
2447 const A3: [&i32; 3] = [&1, &2, &100];
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);
2456 fn anonymous_const_block() {
2459 extern "rust-intrinsic" {
2460 pub fn size_of<T>() -> usize;
2463 const fn f<T>() -> usize {
2464 let r = const { size_of::<T>() };
2468 const GOAL: usize = {
2469 let x = const { 2 + const { 3 } };
2479 fn const_impl_assoc() {
2484 const VAL: usize = 5;
2486 const GOAL: usize = U5::VAL + <U5>::VAL;
2493 fn const_generic_subst_fn() {
2496 const fn f<const A: usize>(x: usize) -> usize {
2499 const GOAL: usize = f::<2>(3);
2505 fn f<const N: usize>(x: [i32; N]) -> usize {
2510 fn f(self) -> usize;
2513 impl<T, const N: usize> ArrayExt for [T; N] {
2514 fn g(self) -> usize {
2519 const GOAL: usize = f([1, 2, 5]);
2526 fn layout_of_type_with_associated_type_field_defined_inside_body() {
2533 struct St<T: Tr>(T::Ty);
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
2545 struct Goal(St<St2>);
2547 let x = Goal(St(5));
2556 fn const_generic_subst_assoc_const_impl() {
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;
2563 const GOAL: usize = Adder::<2, 3>::VAL;
2570 fn associated_types() {
2575 fn get_item(&self) -> Self::Item;
2583 fn get_item(&self) -> Self::Item {
2588 fn my_get_item<T: Tr>(x: T) -> <T as Tr>::Item {
2592 const GOAL: i32 = my_get_item(X(3)).0;
2599 fn const_trait_assoc() {
2606 impl ToConst for U0 {
2607 const VAL: usize = 0;
2609 impl ToConst for i32 {
2610 const VAL: usize = 32;
2612 const GOAL: usize = U0::VAL + i32::VAL;
2618 //- /a/lib.rs crate:a
2622 pub const fn to_const<T: ToConst>() -> usize {
2625 //- /main.rs crate:main deps:a
2626 use a::{ToConst, to_const};
2628 impl ToConst for U0 {
2629 const VAL: usize = 5;
2631 const GOAL: usize = to_const::<U0>();
2637 //- minicore: size_of, fn
2638 //- /a/lib.rs crate:a
2639 use core::mem::size_of;
2642 pub const X: usize = {
2644 let f = || core::mem::size_of::<T>();
2648 //- /main.rs crate:main deps:a
2656 struct K<T: Tr>(<T as Tr>::Ty);
2657 const GOAL: usize = S::<K<i32>>::X;
2663 struct S<T>(*mut T);
2665 trait MySized: Sized {
2666 const SIZE: S<Self> = S(1 as *mut Self);
2669 impl MySized for i32 {
2670 const SIZE: S<i32> = S(10 as *mut i32);
2673 impl MySized for i64 {
2676 const fn f<T: MySized>() -> usize {
2680 const GOAL: usize = f::<i32>() + f::<i64>() * 2;
2688 if skip_slow_tests() {
2694 const GOAL: usize = loop {};
2696 |e
| e
== ConstEvalError
::MirEvalError(MirEvalError
::ExecutionLimitExceeded
),
2700 const fn f(x: i32) -> i32 {
2703 const GOAL: i32 = f(0);
2705 |e
| e
== ConstEvalError
::MirEvalError(MirEvalError
::ExecutionLimitExceeded
),
2707 // Reasonable code should still work
2710 const fn nth_odd(n: i32) -> i32 {
2713 const fn f(n: i32) -> i32 {
2718 sum = sum + nth_odd(i);
2722 const GOAL: i32 = f(1000);
2734 fn __rust_alloc(size: usize, align: usize) -> *mut u8;
2737 const GOAL: u8 = unsafe {
2738 __rust_alloc(30_000_000_000, 1); // 30GB
2743 e
== ConstEvalError
::MirEvalError(MirEvalError
::Panic(
2744 "Memory allocation of 30000000000 bytes failed".to_string(),
2756 let y: (u8, u8) = x;
2760 |e
| matches
!(e
, ConstEvalError
::MirLowerError(MirLowerError
::TypeMismatch(_
))),
2765 fn unsized_field() {
2768 //- minicore: coerce_unsized, index, slice, transmute
2769 use core::mem::transmute;
2771 struct Slice([usize]);
2772 struct Slice2(Slice);
2775 fn as_inner(&self) -> &Slice {
2779 fn as_bytes(&self) -> &[usize] {
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
2796 fn unsized_local() {
2799 //- minicore: coerce_unsized, index, slice
2800 const fn x() -> SomeUnknownTypeThatDereferenceToSlice {
2801 SomeUnknownTypeThatDereferenceToSlice
2810 |e
| matches
!(e
, ConstEvalError
::MirLowerError(MirLowerError
::UnsizedTemporary(_
))),