Skip to content

Commit e8b9587

Browse files
bors[bot]philberty
andauthored
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 <[email protected]>
2 parents 729bbac + afa451b commit e8b9587

7 files changed

+82
-0
lines changed

gcc/rust/backend/rust-compile-base.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ class HIRCompileBase
7272
tree resolve_indirection_adjustment (Resolver::Adjustment &adjustment,
7373
tree expression, Location locus);
7474

75+
tree resolve_unsized_adjustment (Resolver::Adjustment &adjustment,
76+
tree expression, Location locus);
77+
7578
static void setup_attributes_on_fndecl (
7679
tree fndecl, bool is_main_entry_point, HIR::Visibility &visibility,
7780
const HIR::FunctionQualifiers &qualifiers, const AST::AttrVec &attrs);

gcc/rust/backend/rust-compile-expr.cc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,6 +1204,10 @@ HIRCompileBase::resolve_adjustements (
12041204
case Resolver::Adjustment::AdjustmentType::INDIRECTION:
12051205
e = resolve_indirection_adjustment (adjustment, e, locus);
12061206
break;
1207+
1208+
case Resolver::Adjustment::AdjustmentType::UNSIZE:
1209+
e = resolve_unsized_adjustment (adjustment, e, locus);
1210+
break;
12071211
}
12081212
}
12091213

@@ -1257,6 +1261,32 @@ HIRCompileBase::resolve_indirection_adjustment (
12571261
locus);
12581262
}
12591263

1264+
tree
1265+
HIRCompileBase::resolve_unsized_adjustment (Resolver::Adjustment &adjustment,
1266+
tree expression, Location locus)
1267+
{
1268+
// assumes this is an array
1269+
tree expr_type = TREE_TYPE (expression);
1270+
rust_assert (TREE_CODE (expr_type) == ARRAY_TYPE);
1271+
1272+
// takes an array and returns a fat-pointer so this becomes a constructor
1273+
// expression
1274+
rust_assert (adjustment.get_expected ()->get_kind ()
1275+
== TyTy::TypeKind::SLICE);
1276+
tree fat_pointer
1277+
= TyTyResolveCompile::compile (ctx, adjustment.get_expected ());
1278+
1279+
// make a constructor for this
1280+
tree data = address_expression (expression, locus);
1281+
1282+
// fetch the size from the domain
1283+
tree domain = TYPE_DOMAIN (expr_type);
1284+
tree size = TYPE_MAX_VALUE (domain);
1285+
1286+
return ctx->get_backend ()->constructor_expression (fat_pointer, false,
1287+
{data, size}, -1, locus);
1288+
}
1289+
12601290
void
12611291
CompileExpr::visit (HIR::IdentifierExpr &expr)
12621292
{

gcc/rust/typecheck/rust-autoderef.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,27 @@ Adjuster::try_raw_deref_type (const TyTy::BaseType *ty)
9898
return Adjustment (Adjustment::AdjustmentType::INDIRECTION, infered);
9999
}
100100

101+
Adjustment
102+
Adjuster::try_unsize_type (const TyTy::BaseType *ty)
103+
{
104+
bool is_valid_type = ty->get_kind () == TyTy::TypeKind::ARRAY;
105+
if (!is_valid_type)
106+
return Adjustment::get_error ();
107+
108+
auto mappings = Analysis::Mappings::get ();
109+
auto context = TypeCheckContext::get ();
110+
111+
const auto ref_base = static_cast<const TyTy::ArrayType *> (ty);
112+
auto slice_elem = ref_base->get_element_type ();
113+
114+
auto slice
115+
= new TyTy::SliceType (mappings->get_next_hir_id (), ty->get_ident ().locus,
116+
TyTy::TyVar (slice_elem->get_ref ()));
117+
context->insert_implicit_type (slice);
118+
119+
return Adjustment (Adjustment::AdjustmentType::INDIRECTION, slice);
120+
}
121+
101122
static bool
102123
resolve_operator_overload_fn (
103124
Analysis::RustLangItem::ItemType lang_item_type, const TyTy::BaseType *ty,

gcc/rust/typecheck/rust-autoderef.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class Adjustment
3636
DEREF,
3737
DEREF_MUT,
3838
INDIRECTION,
39+
UNSIZE,
3940
};
4041

4142
// ctor for all adjustments except derefs
@@ -78,6 +79,8 @@ class Adjustment
7879
return "DEREF_MUT";
7980
case AdjustmentType::INDIRECTION:
8081
return "INDIRECTION";
82+
case AdjustmentType::UNSIZE:
83+
return "UNSIZE";
8184
}
8285
gcc_unreachable ();
8386
return "";
@@ -135,6 +138,8 @@ class Adjuster
135138

136139
static Adjustment try_raw_deref_type (const TyTy::BaseType *ty);
137140

141+
static Adjustment try_unsize_type (const TyTy::BaseType *ty);
142+
138143
private:
139144
const TyTy::BaseType *base;
140145
};

gcc/rust/typecheck/rust-hir-dot-operator.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,21 @@ MethodResolver::Probe (const TyTy::BaseType *receiver,
4040
if (autoderef_flag)
4141
return MethodCandidate::get_error ();
4242

43+
// try unsize
44+
Adjustment unsize = Adjuster::try_unsize_type (r);
45+
if (!unsize.is_error ())
46+
{
47+
adjustments.push_back (unsize);
48+
auto unsize_r = unsize.get_expected ();
49+
auto res = Try (unsize_r, segment_name, adjustments);
50+
if (!res.is_error ())
51+
{
52+
return res;
53+
}
54+
55+
adjustments.pop_back ();
56+
}
57+
4358
Adjustment deref
4459
= Adjuster::try_deref_type (r, Analysis::RustLangItem::ItemType::DEREF);
4560
if (!deref.is_error ())

gcc/rust/typecheck/rust-hir-type-check.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ class TypeCheckContext
103103

104104
void insert_type (const Analysis::NodeMapping &mappings,
105105
TyTy::BaseType *type);
106+
void insert_implicit_type (TyTy::BaseType *type);
106107
bool lookup_type (HirId id, TyTy::BaseType **type);
107108

108109
void insert_implicit_type (HirId id, TyTy::BaseType *type);

gcc/rust/typecheck/rust-tyctx.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,13 @@ TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings,
8383
resolved[id] = type;
8484
}
8585

86+
void
87+
TypeCheckContext::insert_implicit_type (TyTy::BaseType *type)
88+
{
89+
rust_assert (type != nullptr);
90+
resolved[type->get_ref ()] = type;
91+
}
92+
8693
void
8794
TypeCheckContext::insert_implicit_type (HirId id, TyTy::BaseType *type)
8895
{

0 commit comments

Comments
 (0)