diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index c30aa4d05159..c7f7f406ebd6 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -72,6 +72,9 @@ class HIRCompileBase tree resolve_indirection_adjustment (Resolver::Adjustment &adjustment, tree expression, Location locus); + tree resolve_unsized_adjustment (Resolver::Adjustment &adjustment, + tree expression, Location locus); + static void setup_attributes_on_fndecl ( tree fndecl, bool is_main_entry_point, HIR::Visibility &visibility, const HIR::FunctionQualifiers &qualifiers, const AST::AttrVec &attrs); diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index 03e3c2efea3c..74ab6a468a82 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -1204,6 +1204,10 @@ HIRCompileBase::resolve_adjustements ( case Resolver::Adjustment::AdjustmentType::INDIRECTION: e = resolve_indirection_adjustment (adjustment, e, locus); break; + + case Resolver::Adjustment::AdjustmentType::UNSIZE: + e = resolve_unsized_adjustment (adjustment, e, locus); + break; } } @@ -1257,6 +1261,32 @@ HIRCompileBase::resolve_indirection_adjustment ( locus); } +tree +HIRCompileBase::resolve_unsized_adjustment (Resolver::Adjustment &adjustment, + tree expression, Location locus) +{ + // assumes this is an array + tree expr_type = TREE_TYPE (expression); + rust_assert (TREE_CODE (expr_type) == ARRAY_TYPE); + + // takes an array and returns a fat-pointer so this becomes a constructor + // expression + rust_assert (adjustment.get_expected ()->get_kind () + == TyTy::TypeKind::SLICE); + tree fat_pointer + = TyTyResolveCompile::compile (ctx, adjustment.get_expected ()); + + // make a constructor for this + tree data = address_expression (expression, locus); + + // fetch the size from the domain + tree domain = TYPE_DOMAIN (expr_type); + tree size = TYPE_MAX_VALUE (domain); + + return ctx->get_backend ()->constructor_expression (fat_pointer, false, + {data, size}, -1, locus); +} + void CompileExpr::visit (HIR::IdentifierExpr &expr) { diff --git a/gcc/rust/typecheck/rust-autoderef.cc b/gcc/rust/typecheck/rust-autoderef.cc index 286225266a2b..67c19084df92 100644 --- a/gcc/rust/typecheck/rust-autoderef.cc +++ b/gcc/rust/typecheck/rust-autoderef.cc @@ -98,6 +98,27 @@ Adjuster::try_raw_deref_type (const TyTy::BaseType *ty) return Adjustment (Adjustment::AdjustmentType::INDIRECTION, infered); } +Adjustment +Adjuster::try_unsize_type (const TyTy::BaseType *ty) +{ + bool is_valid_type = ty->get_kind () == TyTy::TypeKind::ARRAY; + if (!is_valid_type) + return Adjustment::get_error (); + + auto mappings = Analysis::Mappings::get (); + auto context = TypeCheckContext::get (); + + const auto ref_base = static_cast (ty); + auto slice_elem = ref_base->get_element_type (); + + auto slice + = new TyTy::SliceType (mappings->get_next_hir_id (), ty->get_ident ().locus, + TyTy::TyVar (slice_elem->get_ref ())); + context->insert_implicit_type (slice); + + return Adjustment (Adjustment::AdjustmentType::INDIRECTION, slice); +} + static bool resolve_operator_overload_fn ( Analysis::RustLangItem::ItemType lang_item_type, const TyTy::BaseType *ty, diff --git a/gcc/rust/typecheck/rust-autoderef.h b/gcc/rust/typecheck/rust-autoderef.h index f389aff62c0c..369744e3b8c3 100644 --- a/gcc/rust/typecheck/rust-autoderef.h +++ b/gcc/rust/typecheck/rust-autoderef.h @@ -36,6 +36,7 @@ class Adjustment DEREF, DEREF_MUT, INDIRECTION, + UNSIZE, }; // ctor for all adjustments except derefs @@ -78,6 +79,8 @@ class Adjustment return "DEREF_MUT"; case AdjustmentType::INDIRECTION: return "INDIRECTION"; + case AdjustmentType::UNSIZE: + return "UNSIZE"; } gcc_unreachable (); return ""; @@ -135,6 +138,8 @@ class Adjuster static Adjustment try_raw_deref_type (const TyTy::BaseType *ty); + static Adjustment try_unsize_type (const TyTy::BaseType *ty); + private: const TyTy::BaseType *base; }; diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc index 84bbc0c4e0a9..ce7c4e1028c3 100644 --- a/gcc/rust/typecheck/rust-hir-dot-operator.cc +++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc @@ -40,6 +40,21 @@ MethodResolver::Probe (const TyTy::BaseType *receiver, if (autoderef_flag) return MethodCandidate::get_error (); + // try unsize + Adjustment unsize = Adjuster::try_unsize_type (r); + if (!unsize.is_error ()) + { + adjustments.push_back (unsize); + auto unsize_r = unsize.get_expected (); + auto res = Try (unsize_r, segment_name, adjustments); + if (!res.is_error ()) + { + return res; + } + + adjustments.pop_back (); + } + Adjustment deref = Adjuster::try_deref_type (r, Analysis::RustLangItem::ItemType::DEREF); if (!deref.is_error ()) diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 49141b3b46ba..e63ef9fa26b3 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -103,6 +103,7 @@ class TypeCheckContext void insert_type (const Analysis::NodeMapping &mappings, TyTy::BaseType *type); + void insert_implicit_type (TyTy::BaseType *type); bool lookup_type (HirId id, TyTy::BaseType **type); void insert_implicit_type (HirId id, TyTy::BaseType *type); diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc index bd8e14fc0b72..434809c1e085 100644 --- a/gcc/rust/typecheck/rust-tyctx.cc +++ b/gcc/rust/typecheck/rust-tyctx.cc @@ -83,6 +83,13 @@ TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings, resolved[id] = type; } +void +TypeCheckContext::insert_implicit_type (TyTy::BaseType *type) +{ + rust_assert (type != nullptr); + resolved[type->get_ref ()] = type; +} + void TypeCheckContext::insert_implicit_type (HirId id, TyTy::BaseType *type) {