Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 3303a6e

Browse files
committed
Implement some intrinsics
1 parent 8e73ea5 commit 3303a6e

File tree

7 files changed

+521
-145
lines changed

7 files changed

+521
-145
lines changed

crates/hir-ty/src/consteval/tests.rs

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ use super::{
1111
ConstEvalError,
1212
};
1313

14+
mod intrinsics;
15+
1416
fn simplify(e: ConstEvalError) -> ConstEvalError {
1517
match e {
1618
ConstEvalError::MirEvalError(MirEvalError::InFunction(_, e)) => {
@@ -82,6 +84,49 @@ fn bit_op() {
8284
check_number(r#"const GOAL: i8 = 1 << 8"#, 0);
8385
}
8486

87+
#[test]
88+
fn casts() {
89+
check_number(r#"const GOAL: usize = 12 as *const i32 as usize"#, 12);
90+
check_number(
91+
r#"
92+
//- minicore: coerce_unsized, index, slice
93+
const GOAL: i32 = {
94+
let a = [10, 20, 3, 15];
95+
let x: &[i32] = &a;
96+
let y: *const [i32] = x;
97+
let z = y as *const i32;
98+
unsafe { *z }
99+
};
100+
"#,
101+
10,
102+
);
103+
check_number(
104+
r#"
105+
//- minicore: coerce_unsized, index, slice
106+
const GOAL: i16 = {
107+
let a = &mut 5;
108+
let z = a as *mut _;
109+
unsafe { *z }
110+
};
111+
"#,
112+
5,
113+
);
114+
check_number(
115+
r#"
116+
//- minicore: coerce_unsized, index, slice
117+
const GOAL: usize = {
118+
let a = [10, 20, 3, 15];
119+
let x: &[i32] = &a;
120+
let y: *const [i32] = x;
121+
let z = y as *const [u8]; // slice fat pointer cast don't touch metadata
122+
let w = unsafe { &*z };
123+
w.len()
124+
};
125+
"#,
126+
4,
127+
);
128+
}
129+
85130
#[test]
86131
fn locals() {
87132
check_number(
@@ -279,20 +324,6 @@ fn function_call() {
279324
);
280325
}
281326

282-
#[test]
283-
fn intrinsics() {
284-
check_number(
285-
r#"
286-
extern "rust-intrinsic" {
287-
pub fn size_of<T>() -> usize;
288-
}
289-
290-
const GOAL: usize = size_of::<i32>();
291-
"#,
292-
4,
293-
);
294-
}
295-
296327
#[test]
297328
fn trait_basic() {
298329
check_number(
@@ -1353,6 +1384,17 @@ fn array_and_index() {
13531384
check_number(
13541385
r#"
13551386
//- minicore: coerce_unsized, index, slice
1387+
const GOAL: usize = {
1388+
let a = [1, 2, 3];
1389+
let x: &[i32] = &a;
1390+
let y = &*x;
1391+
y.len()
1392+
};"#,
1393+
3,
1394+
);
1395+
check_number(
1396+
r#"
1397+
//- minicore: coerce_unsized, index, slice
13561398
const GOAL: usize = [1, 2, 3, 4, 5].len();"#,
13571399
5,
13581400
);
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
use super::*;
2+
3+
#[test]
4+
fn size_of() {
5+
check_number(
6+
r#"
7+
extern "rust-intrinsic" {
8+
pub fn size_of<T>() -> usize;
9+
}
10+
11+
const GOAL: usize = size_of::<i32>();
12+
"#,
13+
4,
14+
);
15+
}
16+
17+
#[test]
18+
fn transmute() {
19+
check_number(
20+
r#"
21+
extern "rust-intrinsic" {
22+
pub fn transmute<T, U>(e: T) -> U;
23+
}
24+
25+
const GOAL: i32 = transmute((1i16, 1i16));
26+
"#,
27+
0x00010001,
28+
);
29+
}
30+
31+
#[test]
32+
fn const_eval_select() {
33+
check_number(
34+
r#"
35+
extern "rust-intrinsic" {
36+
pub fn const_eval_select<ARG, F, G, RET>(arg: ARG, called_in_const: F, called_at_rt: G) -> RET
37+
where
38+
G: FnOnce<ARG, Output = RET>,
39+
F: FnOnce<ARG, Output = RET>;
40+
}
41+
42+
const fn in_const(x: i32, y: i32) -> i32 {
43+
x + y
44+
}
45+
46+
fn in_rt(x: i32, y: i32) -> i32 {
47+
x + y
48+
}
49+
50+
const GOAL: i32 = const_eval_select((2, 3), in_const, in_rt);
51+
"#,
52+
5,
53+
);
54+
}
55+
56+
#[test]
57+
fn wrapping_add() {
58+
check_number(
59+
r#"
60+
extern "rust-intrinsic" {
61+
pub fn wrapping_add<T>(a: T, b: T) -> T;
62+
}
63+
64+
const GOAL: u8 = wrapping_add(10, 250);
65+
"#,
66+
4,
67+
);
68+
}
69+
70+
#[test]
71+
fn offset() {
72+
check_number(
73+
r#"
74+
//- minicore: coerce_unsized, index, slice
75+
extern "rust-intrinsic" {
76+
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
77+
}
78+
79+
const GOAL: u8 = unsafe {
80+
let ar: &[(u8, u8, u8)] = &[
81+
(10, 11, 12),
82+
(20, 21, 22),
83+
(30, 31, 32),
84+
(40, 41, 42),
85+
(50, 51, 52),
86+
];
87+
let ar: *const [(u8, u8, u8)] = ar;
88+
let ar = ar as *const (u8, u8, u8);
89+
let element = offset(ar, 2);
90+
element.1
91+
};
92+
"#,
93+
31,
94+
);
95+
}
96+
97+
#[test]
98+
fn arith_offset() {
99+
check_number(
100+
r#"
101+
//- minicore: coerce_unsized, index, slice
102+
extern "rust-intrinsic" {
103+
pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
104+
}
105+
106+
const GOAL: u8 = unsafe {
107+
let ar: &[(u8, u8, u8)] = &[
108+
(10, 11, 12),
109+
(20, 21, 22),
110+
(30, 31, 32),
111+
(40, 41, 42),
112+
(50, 51, 52),
113+
];
114+
let ar: *const [(u8, u8, u8)] = ar;
115+
let ar = ar as *const (u8, u8, u8);
116+
let element = arith_offset(arith_offset(ar, 102), -100);
117+
element.1
118+
};
119+
"#,
120+
31,
121+
);
122+
}
123+
124+
#[test]
125+
fn copy_nonoverlapping() {
126+
check_number(
127+
r#"
128+
extern "rust-intrinsic" {
129+
pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
130+
}
131+
132+
const GOAL: u8 = unsafe {
133+
let mut x = 2;
134+
let y = 5;
135+
copy_nonoverlapping(&y, &mut x, 1);
136+
x
137+
};
138+
"#,
139+
5,
140+
);
141+
}
142+
143+
#[test]
144+
fn copy() {
145+
check_number(
146+
r#"
147+
//- minicore: coerce_unsized, index, slice
148+
extern "rust-intrinsic" {
149+
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
150+
}
151+
152+
const GOAL: i32 = unsafe {
153+
let mut x = [1i32, 2, 3, 4, 5];
154+
let y = (&mut x as *mut _) as *mut i32;
155+
let z = (y as usize + 4) as *const i32;
156+
copy(z, y, 4);
157+
x[0] + x[1] + x[2] + x[3] + x[4]
158+
};
159+
"#,
160+
19,
161+
);
162+
}

crates/hir-ty/src/infer/expr.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -630,8 +630,15 @@ impl<'a> InferenceContext<'a> {
630630
Expr::Cast { expr, type_ref } => {
631631
let cast_ty = self.make_ty(type_ref);
632632
// FIXME: propagate the "castable to" expectation
633-
let _inner_ty = self.infer_expr_no_expect(*expr);
634-
// FIXME check the cast...
633+
let inner_ty = self.infer_expr_no_expect(*expr);
634+
match (inner_ty.kind(Interner), cast_ty.kind(Interner)) {
635+
(TyKind::Ref(_, _, inner), TyKind::Raw(_, cast)) => {
636+
// FIXME: record invalid cast diagnostic in case of mismatch
637+
self.unify(inner, cast);
638+
}
639+
// FIXME check the other kinds of cast...
640+
_ => (),
641+
}
635642
cast_ty
636643
}
637644
Expr::Ref { expr, rawness, mutability } => {

0 commit comments

Comments
 (0)