https://gcc.gnu.org/g:1243e4abaaf0bd1e9cb33a4e1171502e0258b5a4
commit r17-4109-g1243e4abaaf0bd1e9cb33a4e1171502e0258b5a4 Author: Enes Cevik <[email protected]> Date: Thu Jun 25 13:25:50 2026 +0300 gccrs: typecheck: Add array to slice unsize coercion support 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 <[email protected]> Diff: --- gcc/rust/typecheck/rust-coercion.cc | 72 ++++++++++++++++++++++++++++++++++ gcc/testsuite/rust/compile/coercion.rs | 39 ++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc index 954065ee62b4..a423449badf8 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 000000000000..30adbd2666c5 --- /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; +}
