Skip to content

Commit

Permalink
Merge #1045
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
bors[bot] and philberty authored Mar 28, 2022
2 parents 729bbac + afa451b commit e8b9587
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 0 deletions.
3 changes: 3 additions & 0 deletions gcc/rust/backend/rust-compile-base.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
30 changes: 30 additions & 0 deletions gcc/rust/backend/rust-compile-expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down Expand Up @@ -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)
{
Expand Down
21 changes: 21 additions & 0 deletions gcc/rust/typecheck/rust-autoderef.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions gcc/rust/typecheck/rust-autoderef.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Adjustment
DEREF,
DEREF_MUT,
INDIRECTION,
UNSIZE,
};

// ctor for all adjustments except derefs
Expand Down Expand Up @@ -78,6 +79,8 @@ class Adjustment
return "DEREF_MUT";
case AdjustmentType::INDIRECTION:
return "INDIRECTION";
case AdjustmentType::UNSIZE:
return "UNSIZE";
}
gcc_unreachable ();
return "";
Expand Down Expand Up @@ -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;
};
Expand Down
15 changes: 15 additions & 0 deletions gcc/rust/typecheck/rust-hir-dot-operator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 ())
Expand Down
1 change: 1 addition & 0 deletions gcc/rust/typecheck/rust-hir-type-check.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions gcc/rust/typecheck/rust-tyctx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down

0 comments on commit e8b9587

Please sign in to comment.