[gccrs COMMIT 2/6] typecheck: Add array to slice unsize coercion support
gerris.rs@gmail.com
gerris.rs@gmail.com
Sat Aug 15 21:42:13 GMT 2026
From: Enes Cevik <enes@nsvke.com>
This patch enables fundamental array-to-slice (`[T; N]` to `[T]`)
unsized coercions. Previously, the compiler only handled `dyn Trait`
unsized coercions and immediately rejected array-to-slice conversions.
Now, the compiler correctly identifies valid array-to-slice coercions
and generates the appropriate `Adjustment::UNSIZE` tags.
gcc/rust/ChangeLog:
* typecheck/rust-coercion.cc
(TypeCoercionRules::coerce_unsized): Add array-to-slice coercion
support.
gcc/testsuite/ChangeLog:
* rust/compile/coercion.rs: New test.
Signed-off-by: Enes Cevik <enes@nsvke.com>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github: https://github.com/Rust-GCC/gccrs/commit/19b40258edd45bdeef85a5d5289baae358057156
The commit has NOT been mentioned in any issue.
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4722
gcc/rust/typecheck/rust-coercion.cc | 72 ++++++++++++++++++++++++++
gcc/testsuite/rust/compile/coercion.rs | 39 ++++++++++++++
2 files changed, 111 insertions(+)
create mode 100644 gcc/testsuite/rust/compile/coercion.rs
diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc
index 954065ee6..a423449ba 100644
--- a/gcc/rust/typecheck/rust-coercion.cc
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -322,6 +322,7 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
source->debug_str ().c_str (), target->debug_str ().c_str ());
bool source_is_ref = source->get_kind () == TyTy::TypeKind::REF;
+ bool source_is_ptr = source->get_kind () == TyTy::TypeKind::POINTER;
bool target_is_ref = target->get_kind () == TyTy::TypeKind::REF;
bool target_is_ptr = target->get_kind () == TyTy::TypeKind::POINTER;
@@ -377,6 +378,30 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
needs_reborrow = true;
expected_mutability = to_mutbl;
+ adjustments.emplace_back (Adjustment::AdjustmentType::INDIRECTION,
+ source_ref, ty_a);
+ }
+ else if (source_is_ptr && target_is_ptr)
+ {
+ TyTy::PointerType *source_ref = static_cast<TyTy::PointerType *> (source);
+ TyTy::PointerType *target_ref = static_cast<TyTy::PointerType *> (target);
+
+ Mutability from_mutbl = source_ref->mutability ();
+ Mutability to_mutbl = target_ref->mutability ();
+ if (!coerceable_mutability (from_mutbl, to_mutbl))
+ {
+ location_t lhs = mappings.lookup_location (source->get_ref ());
+ location_t rhs = mappings.lookup_location (target->get_ref ());
+ mismatched_mutability_error (locus, lhs, rhs);
+ return tl::unexpected<CoerceUnsizedError> (
+ CoerceUnsizedError::Unsafe);
+ }
+
+ ty_a = source_ref->get_base ();
+ ty_b = target_ref->get_base ();
+ needs_reborrow = true;
+ expected_mutability = to_mutbl;
+
adjustments.emplace_back (Adjustment::AdjustmentType::INDIRECTION,
source_ref, ty_a);
}
@@ -393,6 +418,9 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
bool expect_dyn = b->get_kind () == TyTy::TypeKind::DYNAMIC;
bool need_unsize = a->get_kind () != TyTy::TypeKind::DYNAMIC;
+ bool expect_slice = b->get_kind () == TyTy::TypeKind::SLICE;
+ bool is_array = a->get_kind () == TyTy::TypeKind::ARRAY;
+
if (expect_dyn && need_unsize)
{
bool bounds_compatible = b->bounds_compatible (*a, locus, false);
@@ -420,6 +448,50 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
adjustments.emplace_back (borrow_type, result, reborrow);
result = reborrow;
}
+ return CoercionResult{adjustments, result};
+ }
+ else if (expect_slice && is_array)
+ {
+ auto array_type = static_cast<const TyTy::ArrayType *> (a);
+ auto slice_type = static_cast<const TyTy::SliceType *> (b);
+
+ TyTy::BaseType *array_element = array_type->get_element_type ();
+ TyTy::BaseType *slice_element = slice_type->get_element_type ();
+
+ if (!array_element->is_equal (*slice_element))
+ {
+ adjustments.clear ();
+ return tl::unexpected<CoerceUnsizedError> (
+ CoerceUnsizedError::Regular);
+ }
+ TyTy::BaseType *result = b->clone ();
+
+ adjustments.emplace_back (Adjustment::UNSIZE, a, result);
+
+ if (needs_reborrow)
+ {
+ TyTy::BaseType *reborrow = nullptr;
+ if (target->get_kind () == TyTy::TypeKind::POINTER)
+ {
+ reborrow
+ = new TyTy::PointerType (source->get_ref (),
+ TyTy::TyVar (result->get_ref ()),
+ expected_mutability);
+ }
+ else
+ {
+ reborrow
+ = new TyTy::ReferenceType (source->get_ref (),
+ TyTy::TyVar (result->get_ref ()),
+ expected_mutability);
+ }
+
+ Adjustment::AdjustmentType borrow_type
+ = expected_mutability == Mutability::Imm ? Adjustment::IMM_REF
+ : Adjustment::MUT_REF;
+ adjustments.emplace_back (borrow_type, result, reborrow);
+ result = reborrow;
+ }
return CoercionResult{adjustments, result};
}
diff --git a/gcc/testsuite/rust/compile/coercion.rs b/gcc/testsuite/rust/compile/coercion.rs
new file mode 100644
index 000000000..30adbd266
--- /dev/null
+++ b/gcc/testsuite/rust/compile/coercion.rs
@@ -0,0 +1,39 @@
+#![feature(lang_items, no_core)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+fn main() {
+ let arr: [i32; 4] = [1, 2, 3, 4];
+ let mut arr_mut: [i32; 4] = [1, 2, 3, 4];
+
+ // 1. &mut T -> &mut U
+ let _mut_to_mut: &mut [i32] = &mut arr_mut;
+
+ // 2. &mut T -> &U
+ let _mut_to_ref: &[i32] = &mut arr_mut;
+
+ // 3. &mut T -> *mut U
+ let _mut_to_ptr_mut: *mut [i32] = &mut arr_mut;
+
+ // 4. &mut T -> *const U
+ let _mut_to_ptr_const: *const [i32] = &mut arr_mut;
+
+ // 5. &T -> &U
+ let _ref_to_ref: &[i32] = &arr;
+
+ // 6. &T -> *const U
+ let _ref_to_ptr_const: *const [i32] = &arr;
+
+ // 7. *mut T -> *mut U
+ let raw_mut: *mut [i32; 4] = &mut arr_mut;
+ let _ptr_mut_to_ptr_mut: *mut [i32] = raw_mut;
+
+ // 8. *mut T -> *const U
+ let _ptr_mut_to_ptr_const: *const [i32] = raw_mut;
+
+ // 9. *const T -> *const U
+ let raw_const: *const [i32; 4] = &arr;
+ let _ptr_const_to_ptr_const: *const [i32] = raw_const;
+}
--
2.54.0
More information about the Gcc-rust
mailing list