Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/cast.rs')
| -rw-r--r-- | crates/hir-ty/src/infer/cast.rs | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs new file mode 100644 index 0000000000..9e1c74b16f --- /dev/null +++ b/crates/hir-ty/src/infer/cast.rs @@ -0,0 +1,46 @@ +//! Type cast logic. Basically coercion + additional casts. + +use crate::{infer::unify::InferenceTable, Interner, Ty, TyExt, TyKind}; + +#[derive(Clone, Debug)] +pub(super) struct CastCheck { + expr_ty: Ty, + cast_ty: Ty, +} + +impl CastCheck { + pub(super) fn new(expr_ty: Ty, cast_ty: Ty) -> Self { + Self { expr_ty, cast_ty } + } + + pub(super) fn check(self, table: &mut InferenceTable<'_>) { + // FIXME: This function currently only implements the bits that influence the type + // inference. We should return the adjustments on success and report diagnostics on error. + let expr_ty = table.resolve_ty_shallow(&self.expr_ty); + let cast_ty = table.resolve_ty_shallow(&self.cast_ty); + + if expr_ty.contains_unknown() || cast_ty.contains_unknown() { + return; + } + + if table.coerce(&expr_ty, &cast_ty).is_ok() { + return; + } + + if check_ref_to_ptr_cast(expr_ty, cast_ty, table) { + // Note that this type of cast is actually split into a coercion to a + // pointer type and a cast: + // &[T; N] -> *[T; N] -> *T + return; + } + + // FIXME: Check other kinds of non-coercion casts and report error if any? + } +} + +fn check_ref_to_ptr_cast(expr_ty: Ty, cast_ty: Ty, table: &mut InferenceTable<'_>) -> bool { + let Some((expr_inner_ty, _, _)) = expr_ty.as_reference() else { return false; }; + let Some((cast_inner_ty, _)) = cast_ty.as_raw_ptr() else { return false; }; + let TyKind::Array(expr_elt_ty, _) = expr_inner_ty.kind(Interner) else { return false; }; + table.coerce(expr_elt_ty, cast_inner_ty).is_ok() +} |