Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions gcc/rust/backend/rust-compile-resolve-path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,8 @@ ResolvePathRef::resolve_with_node_id (
tl::optional<HirId> hid
= ctx->get_mappings ().lookup_node_to_hir (resolved_node_id);
if (!hid.has_value ())
{
rust_error_at (expr_locus, "reverse call path lookup failure");
return error_mark_node;
}
return error_mark_node;

auto ref = hid.value ();

// might be a constant
Expand Down Expand Up @@ -189,6 +187,17 @@ ResolvePathRef::resolve_with_node_id (
}
}

// possibly a const expr value
if (lookup->get_kind () == TyTy::TypeKind::CONST)
{
auto d = lookup->destructure ();
rust_assert (d->get_kind () == TyTy::TypeKind::CONST);
auto c = d->as_const_type ();
rust_assert (c->const_kind () == TyTy::BaseConstType::ConstKind::Value);
auto val = static_cast<TyTy::ConstValueType *> (c);
return val->get_value ();
}

// Handle unit struct
tree resolved_item = error_mark_node;
if (lookup->get_kind () == TyTy::TypeKind::ADT)
Expand All @@ -203,9 +212,7 @@ ResolvePathRef::resolve_with_node_id (
resolved_item = query_compile (ref, lookup, final_segment, mappings,
expr_locus, is_qualified_path);
if (resolved_item != error_mark_node)
{
TREE_USED (resolved_item) = 1;
}
TREE_USED (resolved_item) = 1;

return resolved_item;
}
Expand Down
22 changes: 16 additions & 6 deletions gcc/rust/typecheck/rust-hir-type-check-item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,27 @@ TypeCheckItem::ResolveImplBlockSelfWithInference (
std::vector<TyTy::SubstitutionArg> args;
for (auto &p : substitutions)
{
if (p.needs_substitution ())
auto param = p.get_param_ty ();
if (!p.needs_substitution ())
{
TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
args.emplace_back (&p, infer_var.get_tyty ());
auto resolved = param->destructure ();
args.emplace_back (&p, resolved);

continue;
}

TyTy::BaseType *argument = nullptr;
if (param->get_kind () == TyTy::TypeKind::CONST)
{
auto i = TyTy::TyVar::get_implicit_const_infer_var (locus);
argument = i.get_tyty ();
}
else
{
auto param = p.get_param_ty ();
auto resolved = param->destructure ();
args.emplace_back (&p, resolved);
auto i = TyTy::TyVar::get_implicit_infer_var (locus);
argument = i.get_tyty ();
}
args.emplace_back (&p, argument);
}

// create argument mappings
Expand Down
10 changes: 5 additions & 5 deletions gcc/rust/typecheck/rust-type-util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,13 @@ unify_site_and (HirId id, TyTy::TyWithLocation lhs, TyTy::TyWithLocation rhs,
}
else if (cleanup)
{
// FIXME
// reset the get_next_hir_id

for (auto &i : infers)
{
i.param->set_ref (i.pref);
i.param->set_ty_ref (i.ptyref);
if (i.param != nullptr)
{
i.param->set_ref (i.pref);
i.param->set_ty_ref (i.ptyref);
}

// remove the inference variable
context.clear_type (i.infer);
Expand Down
7 changes: 4 additions & 3 deletions gcc/rust/typecheck/rust-tyty-util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,15 @@ TyVar::get_implicit_infer_var (location_t locus)
}

TyVar
TyVar::get_implicit_const_infer_var (location_t locus)
TyVar::get_implicit_const_infer_var (location_t locus, TyVar *implicit_type)
{
auto &mappings = Analysis::Mappings::get ();
auto context = Resolver::TypeCheckContext::get ();

TyVar ty_infer = get_implicit_infer_var (locus);
TyVar it = (implicit_type != nullptr) ? *implicit_type
: get_implicit_infer_var (locus);
HirId next = mappings.get_next_hir_id ();
auto infer = new ConstInferType (ty_infer.get_tyty (), next, next, {});
auto infer = new ConstInferType (it.get_tyty (), next, next, {});

context->insert_implicit_type (infer->get_ref (), infer);
mappings.insert_location (infer->get_ref (), locus);
Expand Down
3 changes: 2 additions & 1 deletion gcc/rust/typecheck/rust-tyty-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ class TyVar

static TyVar get_implicit_infer_var (location_t locus);

static TyVar get_implicit_const_infer_var (location_t locus);
static TyVar get_implicit_const_infer_var (location_t locus,
TyVar *implicit_type = nullptr);

static TyVar subst_covariant_var (TyTy::BaseType *orig,
TyTy::BaseType *subst);
Expand Down
36 changes: 29 additions & 7 deletions gcc/rust/typecheck/rust-tyty.cc
Original file line number Diff line number Diff line change
Expand Up @@ -785,11 +785,18 @@ BaseType::is_concrete () const
{
const TyTy::BaseType *x = destructure ();

if (x->is<ParamType> () || x->is<ProjectionType> ()
|| x->is<ConstParamType> ())
if (x->is<ParamType> () || x->is<ProjectionType> ())
{
return false;
}
else if (x->get_kind () == TyTy::TypeKind::CONST)
{
auto p = x->as_const_type ();
if (p->const_kind () == BaseConstType::ConstKind::Decl)
return false;

return true;
}
// placeholder is a special case for this case when it is not resolvable
// it means we its just an empty placeholder associated type which is
// concrete
Expand Down Expand Up @@ -3633,9 +3640,8 @@ ConstParamType::get_name () const
return get_symbol ();

BaseType *lookup = resolve ();
// Avoid infinite recursion if resolve() returns this same type
if (lookup == this->as_base_type ())
return get_symbol ();
return get_symbol () + ":" + get_specified_type ()->get_name ();

return lookup->get_name ();
}
Expand All @@ -3660,9 +3666,25 @@ ConstParamType::is_equal (const BaseType &other) const
return false;

if (can_resolve ())
return Resolver::types_compatable (TyTy::TyWithLocation (resolve ()),
TyTy::TyWithLocation (other2.resolve ()),
ident.locus, false);
{
// Compare the resolved ty_ref values to avoid infinite recursion
// through types_compatable/unification
BaseType *lhs = resolve ();
BaseType *rhs = other2.resolve ();

// If they resolve to the same type (same ty_ref), they're equal
if (lhs->get_ty_ref () == rhs->get_ty_ref ())
return true;

// Otherwise check if the resolved types are equal
// Avoid recursion by checking if we'd be comparing ConstParamTypes again
if (lhs->get_kind () == TypeKind::CONST
&& lhs->as_const_type ()->const_kind ()
== BaseConstType::ConstKind::Decl)
return false; // Would cause recursion, so not equal

return lhs->is_equal (*rhs);
}

return get_symbol ().compare (other2.get_symbol ()) == 0;
}
Expand Down
62 changes: 47 additions & 15 deletions gcc/rust/typecheck/rust-unify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

#include "rust-unify.h"
#include "fold-const.h"
#include "rust-tyty-util.h"
#include "rust-tyty.h"
#include "tree.h"

namespace Rust {
namespace Resolver {
Expand Down Expand Up @@ -302,35 +302,67 @@ UnifyRules::go ()
else if (ltype->get_kind () == TyTy::TypeKind::CONST
&& rtype->get_kind () == TyTy::TypeKind::CONST)
{
const auto &lhs = *ltype->as_const_type ();
const auto &rhs = *rtype->as_const_type ();
auto lhs = ltype->as_const_type ();
auto rhs = rtype->as_const_type ();

bool both_are_decls
= lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl
&& rhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl;
= lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl
&& rhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl;
bool have_decls
= lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl
|| rhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl;
= lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl
|| rhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl;

if (have_decls && !both_are_decls)
{
if (lhs.const_kind () == TyTy::BaseConstType::ConstKind::Decl)
if (lhs->const_kind () == TyTy::BaseConstType::ConstKind::Decl)
{
TyTy::TyVar iv = TyTy::TyVar::get_implicit_const_infer_var (
lhs.as_base_type ()->get_locus ());
ltype = iv.get_tyty ();
auto l = lhs->as_base_type ()->get_locus ();
auto p = static_cast<TyTy::ConstParamType *> (lhs);
auto it = TyTy::TyVar::get_implicit_infer_var (l);
auto iv = TyTy::TyVar::get_implicit_const_infer_var (l, &it);
auto ivt = iv.get_tyty ();

infers.emplace_back (0, 0, nullptr, it.get_tyty ());
infers.emplace_back (ltype->get_ref (), ltype->get_ty_ref (),
p, ivt);

ltype = ivt;
p->set_ty_ref (ltype->get_ref ());
}
else if (rhs.const_kind ()
else if (rhs->const_kind ()
== TyTy::BaseConstType::ConstKind::Decl)
{
TyTy::TyVar iv = TyTy::TyVar::get_implicit_const_infer_var (
rhs.as_base_type ()->get_locus ());
rtype = iv.get_tyty ();
auto l = rhs->as_base_type ()->get_locus ();
auto p = static_cast<TyTy::ConstParamType *> (rhs);
auto it = TyTy::TyVar::get_implicit_infer_var (l);
auto iv = TyTy::TyVar::get_implicit_const_infer_var (l, &it);
auto ivt = iv.get_tyty ();

infers.emplace_back (0, 0, nullptr, it.get_tyty ());
infers.emplace_back (rtype->get_ref (), rtype->get_ty_ref (),
p, ivt);

rtype = ivt;
p->set_ty_ref (rtype->get_ref ());
}
}
}
}

if (ltype->get_kind () != TyTy::TypeKind::CONST
&& rtype->get_kind () == TyTy::TypeKind::CONST)
{
auto *rc = rtype->as_const_type ();
rtype = rc->get_specified_type ();
}

if (ltype->get_kind () == TyTy::TypeKind::CONST
&& rtype->get_kind () != TyTy::TypeKind::CONST)
{
auto *lc = ltype->as_const_type ();
ltype = lc->get_specified_type ();
}

switch (ltype->get_kind ())
{
case TyTy::INFER:
Expand Down
8 changes: 4 additions & 4 deletions gcc/rust/typecheck/rust-unify.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ class UnifyRules
public:
struct InferenceSite
{
InferenceSite (HirId pref, HirId ptyref, TyTy::ParamType *param,
TyTy::InferType *infer)
InferenceSite (HirId pref, HirId ptyref, TyTy::BaseGeneric *param,
TyTy::BaseType *infer)
: pref (pref), ptyref (ptyref), param (param), infer (infer)
{}

HirId pref;
HirId ptyref;
TyTy::ParamType *param;
TyTy::InferType *infer;
TyTy::BaseGeneric *param;
TyTy::BaseType *infer;
};
struct CommitSite
{
Expand Down
20 changes: 20 additions & 0 deletions gcc/testsuite/rust/execute/torture/const-generics-2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#[lang = "sized"]
trait Sized {}

trait Magic {
fn magic(&self) -> usize;
}

struct Foo<const N: usize>;

impl<const N: usize> Magic for Foo<N> {
fn magic(&self) -> usize {
N
}
}

fn main() -> i32 {
let f = Foo::<7> {};
let n = f.magic();
n as i32 - 7
}
Loading