diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index c33d0b072d0..5f306620f7b 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -132,10 +132,8 @@ ResolvePathRef::resolve_with_node_id ( tl::optional 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 @@ -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 (c); + return val->get_value (); + } + // Handle unit struct tree resolved_item = error_mark_node; if (lookup->get_kind () == TyTy::TypeKind::ADT) @@ -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; } diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc index 4987c88ab70..ee5c4e98fba 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.cc +++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc @@ -112,17 +112,27 @@ TypeCheckItem::ResolveImplBlockSelfWithInference ( std::vector 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 diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc index 6f30ebf49e9..a6b99665848 100644 --- a/gcc/rust/typecheck/rust-type-util.cc +++ b/gcc/rust/typecheck/rust-type-util.cc @@ -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); diff --git a/gcc/rust/typecheck/rust-tyty-util.cc b/gcc/rust/typecheck/rust-tyty-util.cc index 72761d9842b..b780eaac743 100644 --- a/gcc/rust/typecheck/rust-tyty-util.cc +++ b/gcc/rust/typecheck/rust-tyty-util.cc @@ -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); diff --git a/gcc/rust/typecheck/rust-tyty-util.h b/gcc/rust/typecheck/rust-tyty-util.h index 26101fd4d93..b132487eb5e 100644 --- a/gcc/rust/typecheck/rust-tyty-util.h +++ b/gcc/rust/typecheck/rust-tyty-util.h @@ -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); diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index da5c35049fa..480e244fd38 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -785,11 +785,18 @@ BaseType::is_concrete () const { const TyTy::BaseType *x = destructure (); - if (x->is () || x->is () - || x->is ()) + if (x->is () || x->is ()) { 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 @@ -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 (); } @@ -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; } diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc index 43dd6dca617..36dbc0e187e 100644 --- a/gcc/rust/typecheck/rust-unify.cc +++ b/gcc/rust/typecheck/rust-unify.cc @@ -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 { @@ -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 (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 (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: diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h index 4bed24c924f..2b772feb8b9 100644 --- a/gcc/rust/typecheck/rust-unify.h +++ b/gcc/rust/typecheck/rust-unify.h @@ -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 { diff --git a/gcc/testsuite/rust/execute/torture/const-generics-2.rs b/gcc/testsuite/rust/execute/torture/const-generics-2.rs new file mode 100644 index 00000000000..cf92953a37a --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/const-generics-2.rs @@ -0,0 +1,20 @@ +#[lang = "sized"] +trait Sized {} + +trait Magic { + fn magic(&self) -> usize; +} + +struct Foo; + +impl Magic for Foo { + fn magic(&self) -> usize { + N + } +} + +fn main() -> i32 { + let f = Foo::<7> {}; + let n = f.magic(); + n as i32 - 7 +}