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>
This commit is contained in:
bors[bot] 2022-03-28 14:22:24 +00:00 committed by GitHub
commit e8b9587d3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 82 additions and 0 deletions

View File

@ -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);

View File

@ -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)
{

View File

@ -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,

View File

@ -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;
};

View File

@ -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 ())

View File

@ -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);

View File

@ -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)
{