From: Enes Cevik <[email protected]>
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]>
---
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.