]>
Commit | Line | Data |
---|---|---|
add651ee FG |
1 | //! Type cast logic. Basically coercion + additional casts. |
2 | ||
3 | use crate::{infer::unify::InferenceTable, Interner, Ty, TyExt, TyKind}; | |
4 | ||
5 | #[derive(Clone, Debug)] | |
6 | pub(super) struct CastCheck { | |
7 | expr_ty: Ty, | |
8 | cast_ty: Ty, | |
9 | } | |
10 | ||
11 | impl CastCheck { | |
12 | pub(super) fn new(expr_ty: Ty, cast_ty: Ty) -> Self { | |
13 | Self { expr_ty, cast_ty } | |
14 | } | |
15 | ||
16 | pub(super) fn check(self, table: &mut InferenceTable<'_>) { | |
17 | // FIXME: This function currently only implements the bits that influence the type | |
18 | // inference. We should return the adjustments on success and report diagnostics on error. | |
19 | let expr_ty = table.resolve_ty_shallow(&self.expr_ty); | |
20 | let cast_ty = table.resolve_ty_shallow(&self.cast_ty); | |
21 | ||
22 | if expr_ty.contains_unknown() || cast_ty.contains_unknown() { | |
23 | return; | |
24 | } | |
25 | ||
26 | if table.coerce(&expr_ty, &cast_ty).is_ok() { | |
27 | return; | |
28 | } | |
29 | ||
30 | if check_ref_to_ptr_cast(expr_ty, cast_ty, table) { | |
31 | // Note that this type of cast is actually split into a coercion to a | |
32 | // pointer type and a cast: | |
33 | // &[T; N] -> *[T; N] -> *T | |
34 | return; | |
35 | } | |
36 | ||
37 | // FIXME: Check other kinds of non-coercion casts and report error if any? | |
38 | } | |
39 | } | |
40 | ||
41 | fn check_ref_to_ptr_cast(expr_ty: Ty, cast_ty: Ty, table: &mut InferenceTable<'_>) -> bool { | |
781aab86 FG |
42 | let Some((expr_inner_ty, _, _)) = expr_ty.as_reference() else { |
43 | return false; | |
44 | }; | |
45 | let Some((cast_inner_ty, _)) = cast_ty.as_raw_ptr() else { | |
46 | return false; | |
47 | }; | |
48 | let TyKind::Array(expr_elt_ty, _) = expr_inner_ty.kind(Interner) else { | |
49 | return false; | |
50 | }; | |
add651ee FG |
51 | table.coerce(expr_elt_ty, cast_inner_ty).is_ok() |
52 | } |