aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-03-28 14:22:24 +0000
committerGitHub <noreply@github.com>2022-03-28 14:22:24 +0000
commite8b9587d3a0615f497cfe9c66995c1f21e42a536 (patch)
treed68047eb3249dda74d6469b9e8ec4ec822ce802f
parent729bbacbd175350fbff3959d7503ae954d22aeef (diff)
parentafa451b311dec27476941e6f307d04450d28ab88 (diff)
downloadgcc-e8b9587d3a0615f497cfe9c66995c1f21e42a536.zip
gcc-e8b9587d3a0615f497cfe9c66995c1f21e42a536.tar.gz
gcc-e8b9587d3a0615f497cfe9c66995c1f21e42a536.tar.bz2
Merge #1045
1045: Add initial support for unsized method resolution r=philberty a=philberty In order to support slices, we end up with an operator overload call of: ``` impl<T, I> Index<I> for [T] where I: SliceIndex<[T]>, { type Output = I::Output; fn index(&self, index: I) -> &I::Output { index.index(self) } } ``` So this means the self, in this case, is an array[T,capacity] and the index parameter is of type Range<usize>. In order to actually call this method which has a self parameter of [T] we need to be able to 'unsize' the array into a slice. Addresses #849 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
-rw-r--r--gcc/rust/backend/rust-compile-base.h3
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc30
-rw-r--r--gcc/rust/typecheck/rust-autoderef.cc21
-rw-r--r--gcc/rust/typecheck/rust-autoderef.h5
-rw-r--r--gcc/rust/typecheck/rust-hir-dot-operator.cc15
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h1
-rw-r--r--gcc/rust/typecheck/rust-tyctx.cc7
7 files changed, 82 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h
index c30aa4d..c7f7f40 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -72,6 +72,9 @@ protected:
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 03e3c2e..74ab6a4 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 2862252..67c1908 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<const TyTy::ArrayType *> (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 f389aff..369744e 100644
--- a/gcc/rust/typecheck/rust-autoderef.h
+++ b/gcc/rust/typecheck/rust-autoderef.h
@@ -36,6 +36,7 @@ public:
DEREF,
DEREF_MUT,
INDIRECTION,
+ UNSIZE,
};
// ctor for all adjustments except derefs
@@ -78,6 +79,8 @@ public:
return "DEREF_MUT";
case AdjustmentType::INDIRECTION:
return "INDIRECTION";
+ case AdjustmentType::UNSIZE:
+ return "UNSIZE";
}
gcc_unreachable ();
return "";
@@ -135,6 +138,8 @@ public:
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 84bbc0c..ce7c4e1 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 49141b3..e63ef9f 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -103,6 +103,7 @@ public:
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 bd8e14f..434809c 100644
--- a/gcc/rust/typecheck/rust-tyctx.cc
+++ b/gcc/rust/typecheck/rust-tyctx.cc
@@ -84,6 +84,13 @@ TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings,
}
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)
{
rust_assert (type != nullptr);