aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in2
-rw-r--r--gcc/rust/ast/rust-path.h17
-rw-r--r--gcc/rust/backend/rust-compile-context.h9
-rw-r--r--gcc/rust/backend/rust-compile-expr.h5
-rw-r--r--gcc/rust/backend/rust-compile-implitem.h214
-rw-r--r--gcc/rust/backend/rust-compile-item.h16
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc103
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.h18
-rw-r--r--gcc/rust/backend/rust-compile-tyty.h2
-rw-r--r--gcc/rust/backend/rust-compile.cc47
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h3
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h27
-rw-r--r--gcc/rust/hir/rust-ast-lower-implitem.h52
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc49
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-test.cc4
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h21
-rw-r--r--gcc/rust/hir/tree/rust-hir-path.h72
-rw-r--r--gcc/rust/hir/tree/rust-hir.h4
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h17
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-toplevel.h13
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc117
-rw-r--r--gcc/rust/typecheck/rust-hir-const-fold.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.h47
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-ref.h98
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.cc231
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.h45
-rw-r--r--gcc/rust/typecheck/rust-hir-type-bounds.h19
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h364
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.h3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h13
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-util.cc41
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-util.h216
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h71
-rw-r--r--gcc/rust/typecheck/rust-substitution-mapper.h4
-rw-r--r--gcc/rust/typecheck/rust-tyty-bounds.cc10
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty-cast.h11
-rw-r--r--gcc/rust/typecheck/rust-tyty-cmp.h76
-rw-r--r--gcc/rust/typecheck/rust-tyty-coercion.h11
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h52
-rw-r--r--gcc/rust/typecheck/rust-tyty-visitor.h2
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc131
-rw-r--r--gcc/rust/typecheck/rust-tyty.h73
-rw-r--r--gcc/rust/util/rust-canonical-path.h11
-rw-r--r--gcc/testsuite/rust/compile/torture/traits10.rs32
-rw-r--r--gcc/testsuite/rust/compile/torture/traits11.rs32
-rw-r--r--gcc/testsuite/rust/compile/traits1.rs1
-rw-r--r--gcc/testsuite/rust/compile/traits2.rs1
-rw-r--r--gcc/testsuite/rust/execute/torture/trait1.rs52
49 files changed, 2148 insertions, 315 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index f4bc9ea..7ed380e 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -80,6 +80,8 @@ GRS_OBJS = \
rust/rust-tyty.o \
rust/rust-tyctx.o \
rust/rust-tyty-bounds.o \
+ rust/rust-hir-type-check-util.o \
+ rust/rust-hir-trait-resolve.o \
rust/rust-hir-const-fold.o \
rust/rust-lint-marklive.o \
$(END)
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index 011ac3e..74ea795 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -771,11 +771,9 @@ struct QualifiedPathType
{
private:
std::unique_ptr<Type> type_to_invoke_on;
-
- // bool has_as_clause;
TypePath trait_path;
-
Location locus;
+ NodeId node_id;
public:
// Constructor
@@ -783,13 +781,15 @@ public:
Location locus = Location (),
TypePath trait_path = TypePath::create_error ())
: type_to_invoke_on (std::move (invoke_on_type)),
- trait_path (std::move (trait_path)), locus (locus)
+ trait_path (std::move (trait_path)), locus (locus),
+ node_id (Analysis::Mappings::get ()->get_next_node_id ())
{}
// Copy constructor uses custom deep copy for Type to preserve polymorphism
QualifiedPathType (QualifiedPathType const &other)
: trait_path (other.trait_path), locus (other.locus)
{
+ node_id = other.node_id;
// guard to prevent null dereference
if (other.type_to_invoke_on != nullptr)
type_to_invoke_on = other.type_to_invoke_on->clone_type ();
@@ -801,6 +801,7 @@ public:
// overload assignment operator to use custom clone method
QualifiedPathType &operator= (QualifiedPathType const &other)
{
+ node_id = other.node_id;
trait_path = other.trait_path;
locus = other.locus;
@@ -846,6 +847,8 @@ public:
rust_assert (has_as_clause ());
return trait_path;
}
+
+ NodeId get_node_id () const { return node_id; }
};
/* AST node representing a qualified path-in-expression pattern (path that
@@ -855,6 +858,7 @@ class QualifiedPathInExpression : public PathPattern, public PathExpr
std::vector<Attribute> outer_attrs;
QualifiedPathType path_type;
Location locus;
+ NodeId _node_id;
public:
std::string as_string () const override;
@@ -864,7 +868,8 @@ public:
std::vector<Attribute> outer_attrs, Location locus)
: PathPattern (std::move (path_segments)),
outer_attrs (std::move (outer_attrs)),
- path_type (std::move (qual_path_type)), locus (locus)
+ path_type (std::move (qual_path_type)), locus (locus),
+ _node_id (Analysis::Mappings::get ()->get_next_node_id ())
{}
/* TODO: maybe make a shortcut constructor that has QualifiedPathType elements
@@ -907,6 +912,8 @@ public:
outer_attrs = std::move (new_attrs);
}
+ NodeId get_node_id () const override { return _node_id; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h
index 8007c2f..66d037d 100644
--- a/gcc/rust/backend/rust-compile-context.h
+++ b/gcc/rust/backend/rust-compile-context.h
@@ -287,7 +287,7 @@ public:
// this needs to support Legacy and V0 see github #429 or #305
std::string mangle_item (const TyTy::BaseType *ty,
- const std::string &name) const;
+ const Resolver::CanonicalPath &path) const;
std::string mangle_impl_item (const TyTy::BaseType *self,
const TyTy::BaseType *ty,
@@ -336,7 +336,12 @@ public:
void visit (TyTy::InferType &) override { gcc_unreachable (); }
- void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); }
+ void visit (TyTy::ProjectionType &) override { gcc_unreachable (); }
+
+ void visit (TyTy::PlaceholderType &type) override
+ {
+ type.resolve ()->accept_vis (*this);
+ }
void visit (TyTy::ParamType &param) override
{
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index 4658295..80cdc5e 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -629,6 +629,11 @@ public:
expr.get_locus ());
}
+ void visit (HIR::QualifiedPathInExpression &expr) override
+ {
+ translated = ResolvePathRef::Compile (expr, ctx);
+ }
+
void visit (HIR::PathInExpression &expr) override
{
translated = ResolvePathRef::Compile (expr, ctx);
diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h
index 7608599..7337154 100644
--- a/gcc/rust/backend/rust-compile-implitem.h
+++ b/gcc/rust/backend/rust-compile-implitem.h
@@ -297,6 +297,220 @@ private:
TyTy::BaseType *concrete;
};
+class CompileTraitItem : public HIRCompileBase
+{
+ using Rust::Compile::HIRCompileBase::visit;
+
+public:
+ static void Compile (TyTy::BaseType *self, HIR::TraitItem *item, Context *ctx,
+ TyTy::BaseType *concrete)
+ {
+ CompileTraitItem compiler (self, ctx, concrete);
+ item->accept_vis (compiler);
+ }
+
+ void visit (HIR::TraitItemFunc &func) override
+ {
+ rust_assert (func.has_block_defined ());
+
+ rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
+ TyTy::FnType *fntype = static_cast<TyTy::FnType *> (concrete);
+
+ // items can be forward compiled which means we may not need to invoke this
+ // code. We might also have already compiled this generic function as well.
+ Bfunction *lookup = nullptr;
+ if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup))
+ {
+ // has this been added to the list then it must be finished
+ if (ctx->function_completed (lookup))
+ {
+ Bfunction *dummy = nullptr;
+ if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy))
+ {
+ ctx->insert_function_decl (fntype->get_ty_ref (), lookup,
+ fntype);
+ }
+ return;
+ }
+ }
+
+ if (fntype->has_subsititions_defined ())
+ {
+ // override the Hir Lookups for the substituions in this context
+ fntype->override_context ();
+ }
+
+ // convert to the actual function type
+ ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
+
+ HIR::TraitFunctionDecl &function = func.get_decl ();
+ unsigned int flags = 0;
+
+ const Resolver::CanonicalPath *canonical_path = nullptr;
+ rust_assert (ctx->get_mappings ()->lookup_canonical_path (
+ func.get_mappings ().get_crate_num (), func.get_mappings ().get_nodeid (),
+ &canonical_path));
+
+ std::string fn_identifier = canonical_path->get ();
+ std::string asm_name = ctx->mangle_item (fntype, *canonical_path);
+
+ Bfunction *fndecl
+ = ctx->get_backend ()->function (compiled_fn_type, fn_identifier,
+ asm_name, flags, func.get_locus ());
+ ctx->insert_function_decl (fntype->get_ty_ref (), fndecl, fntype);
+
+ // setup the params
+ TyTy::BaseType *tyret = fntype->get_return_type ();
+ std::vector<Bvariable *> param_vars;
+
+ if (function.is_method ())
+ {
+ // insert self
+ TyTy::BaseType *self_tyty_lookup = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ function.get_self ().get_mappings ().get_hirid (),
+ &self_tyty_lookup))
+ {
+ rust_error_at (function.get_self ().get_locus (),
+ "failed to lookup self param type");
+ return;
+ }
+
+ Btype *self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup);
+ if (self_type == nullptr)
+ {
+ rust_error_at (function.get_self ().get_locus (),
+ "failed to compile self param type");
+ return;
+ }
+
+ Bvariable *compiled_self_param
+ = CompileSelfParam::compile (ctx, fndecl, function.get_self (),
+ self_type,
+ function.get_self ().get_locus ());
+ if (compiled_self_param == nullptr)
+ {
+ rust_error_at (function.get_self ().get_locus (),
+ "failed to compile self param variable");
+ return;
+ }
+
+ param_vars.push_back (compiled_self_param);
+ ctx->insert_var_decl (function.get_self ().get_mappings ().get_hirid (),
+ compiled_self_param);
+ }
+
+ // offset from + 1 for the TyTy::FnType being used when this is a method to
+ // skip over Self on the FnType
+ size_t i = function.is_method () ? 1 : 0;
+ for (auto referenced_param : function.get_function_params ())
+ {
+ auto tyty_param = fntype->param_at (i);
+ auto param_tyty = tyty_param.second;
+
+ auto compiled_param_type
+ = TyTyResolveCompile::compile (ctx, param_tyty);
+ if (compiled_param_type == nullptr)
+ {
+ rust_error_at (referenced_param.get_locus (),
+ "failed to compile parameter type");
+ return;
+ }
+
+ Location param_locus
+ = ctx->get_mappings ()->lookup_location (param_tyty->get_ref ());
+ Bvariable *compiled_param_var
+ = CompileFnParam::compile (ctx, fndecl, &referenced_param,
+ compiled_param_type, param_locus);
+ if (compiled_param_var == nullptr)
+ {
+ rust_error_at (param_locus, "Failed to compile parameter variable");
+ return;
+ }
+
+ param_vars.push_back (compiled_param_var);
+
+ ctx->insert_var_decl (referenced_param.get_mappings ().get_hirid (),
+ compiled_param_var);
+ i++;
+ }
+
+ if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars))
+ {
+ rust_fatal_error (func.get_locus (),
+ "failed to setup parameter variables");
+ return;
+ }
+
+ // lookup locals
+ auto block_expr = func.get_block_expr ().get ();
+ auto body_mappings = block_expr->get_mappings ();
+
+ Resolver::Rib *rib = nullptr;
+ if (!ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (),
+ &rib))
+ {
+ rust_fatal_error (func.get_locus (),
+ "failed to setup locals per block");
+ return;
+ }
+
+ std::vector<Bvariable *> locals;
+ bool ok = compile_locals_for_block (*rib, fndecl, locals);
+ rust_assert (ok);
+
+ Bblock *enclosing_scope = NULL;
+ HIR::BlockExpr *function_body = func.get_block_expr ().get ();
+ Location start_location = function_body->get_locus ();
+ Location end_location = function_body->get_closing_locus ();
+
+ Bblock *code_block
+ = ctx->get_backend ()->block (fndecl, enclosing_scope, locals,
+ start_location, end_location);
+ ctx->push_block (code_block);
+
+ Bvariable *return_address = nullptr;
+ if (function.has_return_type ())
+ {
+ Btype *return_type = TyTyResolveCompile::compile (ctx, tyret);
+
+ bool address_is_taken = false;
+ Bstatement *ret_var_stmt = nullptr;
+
+ return_address = ctx->get_backend ()->temporary_variable (
+ fndecl, code_block, return_type, NULL, address_is_taken,
+ func.get_locus (), &ret_var_stmt);
+
+ ctx->add_statement (ret_var_stmt);
+ }
+
+ ctx->push_fn (fndecl, return_address);
+
+ compile_function_body (fndecl, func.get_block_expr (),
+ function.has_return_type ());
+
+ ctx->pop_block ();
+ auto body = ctx->get_backend ()->block_statement (code_block);
+ if (!ctx->get_backend ()->function_set_body (fndecl, body))
+ {
+ rust_error_at (func.get_locus (), "failed to set body to function");
+ return;
+ }
+
+ ctx->pop_fn ();
+ ctx->push_function (fndecl);
+ }
+
+private:
+ CompileTraitItem (TyTy::BaseType *self, Context *ctx,
+ TyTy::BaseType *concrete)
+ : HIRCompileBase (ctx), self (self), concrete (concrete)
+ {}
+
+ TyTy::BaseType *self;
+ TyTy::BaseType *concrete;
+};
+
} // namespace Compile
} // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h
index 8b36289..a12e67e 100644
--- a/gcc/rust/backend/rust-compile-item.h
+++ b/gcc/rust/backend/rust-compile-item.h
@@ -59,7 +59,7 @@ public:
&canonical_path));
std::string name = canonical_path->get ();
- std::string asm_name = ctx->mangle_item (resolved_type, name);
+ std::string asm_name = ctx->mangle_item (resolved_type, *canonical_path);
bool is_external = false;
bool is_hidden = false;
@@ -168,12 +168,24 @@ public:
std::string ir_symbol_name
= canonical_path->get () + fntype->subst_as_string ();
+
std::string asm_name = function.get_function_name ();
// we don't mangle the main fn since we haven't implemented the main shim
// yet
if (!is_main_fn)
- asm_name = ctx->mangle_item (fntype, ir_symbol_name);
+ {
+ std::string substs_str = fntype->subst_as_string ();
+
+ Resolver::CanonicalPath mangle_me
+ = substs_str.empty ()
+ ? *canonical_path
+ : canonical_path->append (
+ Resolver::CanonicalPath::new_seg (0,
+ fntype->subst_as_string ()));
+
+ asm_name = ctx->mangle_item (fntype, mangle_me);
+ }
Bfunction *fndecl
= ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name,
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index 5f07a2a..1539378 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -27,18 +27,33 @@ namespace Rust {
namespace Compile {
void
+ResolvePathRef::visit (HIR::QualifiedPathInExpression &expr)
+{
+ resolve (expr.get_final_segment ().get_segment (), expr.get_mappings (),
+ expr.get_locus (), true);
+}
+
+void
ResolvePathRef::visit (HIR::PathInExpression &expr)
{
+ resolve (expr.get_final_segment ().get_segment (), expr.get_mappings (),
+ expr.get_locus (), false);
+}
+
+void
+ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
+ const Analysis::NodeMapping &mappings,
+ Location expr_locus, bool is_qualified_path)
+{
// need to look up the reference for this identifier
NodeId ref_node_id = UNKNOWN_NODEID;
- if (ctx->get_resolver ()->lookup_resolved_name (
- expr.get_mappings ().get_nodeid (), &ref_node_id))
+ if (ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (),
+ &ref_node_id))
{
Resolver::Definition def;
if (!ctx->get_resolver ()->lookup_definition (ref_node_id, &def))
{
- rust_error_at (expr.get_locus (),
- "unknown reference for resolved name");
+ rust_error_at (expr_locus, "unknown reference for resolved name");
return;
}
ref_node_id = def.parent;
@@ -50,10 +65,10 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
return;
HirId ref;
- if (!ctx->get_mappings ()->lookup_node_to_hir (
- expr.get_mappings ().get_crate_num (), ref_node_id, &ref))
+ if (!ctx->get_mappings ()->lookup_node_to_hir (mappings.get_crate_num (),
+ ref_node_id, &ref))
{
- rust_error_at (expr.get_locus (), "reverse call path lookup failure");
+ rust_error_at (expr_locus, "reverse call path lookup failure");
return;
}
@@ -65,24 +80,25 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
Bvariable *var = nullptr;
if (ctx->lookup_var_decl (ref, &var))
{
- resolved = ctx->get_backend ()->var_expression (var, expr.get_locus ());
+ resolved = ctx->get_backend ()->var_expression (var, expr_locus);
return;
}
// must be a function call but it might be a generic function which needs to
// be compiled first
TyTy::BaseType *lookup = nullptr;
- bool ok = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
- &lookup);
+ bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup);
rust_assert (ok);
rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
+ TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
Bfunction *fn = nullptr;
if (!ctx->lookup_function_decl (lookup->get_ty_ref (), &fn))
{
// it must resolve to some kind of HIR::Item or HIR::InheritImplItem
- HIR::Item *resolved_item = ctx->get_mappings ()->lookup_hir_item (
- expr.get_mappings ().get_crate_num (), ref);
+ HIR::Item *resolved_item
+ = ctx->get_mappings ()->lookup_hir_item (mappings.get_crate_num (),
+ ref);
if (resolved_item != nullptr)
{
if (!lookup->has_subsititions_defined ())
@@ -95,14 +111,14 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
HirId parent_impl_id = UNKNOWN_HIRID;
HIR::ImplItem *resolved_item
= ctx->get_mappings ()->lookup_hir_implitem (
- expr.get_mappings ().get_crate_num (), ref, &parent_impl_id);
+ mappings.get_crate_num (), ref, &parent_impl_id);
if (resolved_item == nullptr)
{
// it might be resolved to a trait item
HIR::TraitItem *trait_item
= ctx->get_mappings ()->lookup_hir_trait_item (
- expr.get_mappings ().get_crate_num (), ref);
+ mappings.get_crate_num (), ref);
HIR::Trait *trait
= ctx->get_mappings ()->lookup_trait_item_mapping (
trait_item->get_mappings ().get_hirid ());
@@ -114,8 +130,8 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
rust_assert (ok);
TyTy::BaseType *receiver = nullptr;
- ok = ctx->get_tyctx ()->lookup_receiver (
- expr.get_mappings ().get_hirid (), &receiver);
+ ok = ctx->get_tyctx ()->lookup_receiver (mappings.get_hirid (),
+ &receiver);
rust_assert (ok);
if (receiver->get_kind () == TyTy::TypeKind::PARAM)
@@ -129,17 +145,52 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
// item so its up to us to figure out if this path should resolve
// to an trait-impl-block-item or if it can be defaulted to the
// trait-impl-item's definition
- std::vector<Resolver::PathProbeCandidate> candidates
- = Resolver::PathProbeType::Probe (
- receiver, expr.get_final_segment ().get_segment (), true,
- false, true);
+ std::vector<Resolver::PathProbeCandidate> candidates;
+ if (!is_qualified_path)
+ {
+ candidates
+ = Resolver::PathProbeType::Probe (receiver, final_segment,
+ true, false, true);
+ }
if (candidates.size () == 0)
{
// this means we are defaulting back to the trait_item if
// possible
- // TODO
- gcc_unreachable ();
+ Resolver::TraitItemReference *trait_item_ref = nullptr;
+ bool ok = trait_ref->lookup_hir_trait_item (*trait_item,
+ &trait_item_ref);
+ rust_assert (ok); // found
+ rust_assert (
+ trait_item_ref->is_optional ()); // has definition
+
+ Analysis::NodeMapping trait_mappings
+ = trait_item_ref->get_parent_trait_mappings ();
+ auto associated_impl_id
+ = ctx->get_tyctx ()
+ ->lookup_associated_impl_mapping_for_self (
+ trait_mappings.get_hirid (), receiver);
+
+ rust_assert (associated_impl_id != UNKNOWN_HIRID);
+
+ Resolver::AssociatedImplTrait *associated = nullptr;
+ bool found_associated_trait_impl
+ = ctx->get_tyctx ()->lookup_associated_trait_impl (
+ associated_impl_id, &associated);
+ rust_assert (found_associated_trait_impl);
+ associated->setup_associated_types ();
+
+ CompileTraitItem::Compile (
+ receiver, trait_item_ref->get_hir_trait_item (), ctx,
+ fntype);
+
+ if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &fn))
+ {
+ resolved = ctx->get_backend ()->error_expression ();
+ rust_error_at (expr_locus,
+ "forward declaration was not compiled");
+ return;
+ }
}
else
{
@@ -169,7 +220,7 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
{
rust_assert (parent_impl_id != UNKNOWN_HIRID);
HIR::Item *impl_ref = ctx->get_mappings ()->lookup_hir_item (
- expr.get_mappings ().get_crate_num (), parent_impl_id);
+ mappings.get_crate_num (), parent_impl_id);
rust_assert (impl_ref != nullptr);
HIR::ImplBlock *impl = static_cast<HIR::ImplBlock *> (impl_ref);
@@ -190,14 +241,12 @@ ResolvePathRef::visit (HIR::PathInExpression &expr)
if (!ctx->lookup_function_decl (lookup->get_ty_ref (), &fn))
{
resolved = ctx->get_backend ()->error_expression ();
- rust_error_at (expr.get_locus (),
- "forward declaration was not compiled");
+ rust_error_at (expr_locus, "forward declaration was not compiled");
return;
}
}
- resolved
- = ctx->get_backend ()->function_code_expression (fn, expr.get_locus ());
+ resolved = ctx->get_backend ()->function_code_expression (fn, expr_locus);
}
} // namespace Compile
diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h
index 30486d0..41067c8 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.h
+++ b/gcc/rust/backend/rust-compile-resolve-path.h
@@ -30,6 +30,14 @@ class ResolvePathRef : public HIRCompileBase
using Rust::Compile::HIRCompileBase::visit;
public:
+ static Bexpression *Compile (HIR::QualifiedPathInExpression &expr,
+ Context *ctx)
+ {
+ ResolvePathRef resolver (ctx);
+ expr.accept_vis (resolver);
+ return resolver.resolved;
+ }
+
static Bexpression *Compile (HIR::PathInExpression &expr, Context *ctx)
{
ResolvePathRef resolver (ctx);
@@ -39,8 +47,16 @@ public:
void visit (HIR::PathInExpression &expr) override;
+ void visit (HIR::QualifiedPathInExpression &expr) override;
+
private:
- ResolvePathRef (Context *ctx) : HIRCompileBase (ctx), resolved (nullptr) {}
+ ResolvePathRef (Context *ctx)
+ : HIRCompileBase (ctx), resolved (ctx->get_backend ()->error_expression ())
+ {}
+
+ void resolve (const HIR::PathIdentSegment &final_segment,
+ const Analysis::NodeMapping &mappings, Location locus,
+ bool is_qualified_path);
Bexpression *resolved;
};
diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h
index 3ddc29a..1a5747a 100644
--- a/gcc/rust/backend/rust-compile-tyty.h
+++ b/gcc/rust/backend/rust-compile-tyty.h
@@ -50,6 +50,8 @@ public:
void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); }
+ void visit (TyTy::ProjectionType &) override { gcc_unreachable (); }
+
void visit (TyTy::TupleType &type) override
{
if (type.num_fields () == 0)
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index b9b5084..baaccf0 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -181,8 +181,32 @@ CompileExpr::visit (HIR::MethodCallExpr &expr)
{
// this means we are defaulting back to the trait_item if
// possible
- // TODO
- gcc_unreachable ();
+ Resolver::TraitItemReference *trait_item_ref = nullptr;
+ bool ok = trait_ref->lookup_hir_trait_item (*trait_item,
+ &trait_item_ref);
+ rust_assert (ok); // found
+ rust_assert (trait_item_ref->is_optional ()); // has definition
+
+ TyTy::BaseType *self_type = nullptr;
+ if (!ctx->get_tyctx ()->lookup_type (
+ expr.get_receiver ()->get_mappings ().get_hirid (),
+ &self_type))
+ {
+ rust_error_at (expr.get_locus (),
+ "failed to resolve type for self param");
+ return;
+ }
+
+ CompileTraitItem::Compile (self_type,
+ trait_item_ref->get_hir_trait_item (),
+ ctx, fntype);
+ if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &fn))
+ {
+ translated = ctx->get_backend ()->error_expression ();
+ rust_error_at (expr.get_locus (),
+ "forward declaration was not compiled");
+ return;
+ }
}
else
{
@@ -529,6 +553,17 @@ mangle_name (const std::string &name)
return std::to_string (name.size ()) + name;
}
+static std::string
+mangle_canonical_path (const Resolver::CanonicalPath &path)
+{
+ std::string buffer;
+ path.iterate_segs ([&] (const Resolver::CanonicalPath &p) -> bool {
+ buffer += mangle_name (p.get ());
+ return true;
+ });
+ return buffer;
+}
+
// rustc uses a sip128 hash for legacy mangling, but an fnv 128 was quicker to
// implement for now
static std::string
@@ -579,17 +614,19 @@ mangle_self (const TyTy::BaseType *self)
}
std::string
-Context::mangle_item (const TyTy::BaseType *ty, const std::string &name) const
+Context::mangle_item (const TyTy::BaseType *ty,
+ const Resolver::CanonicalPath &path) const
{
const std::string &crate_name = mappings->get_current_crate_name ();
const std::string hash = legacy_hash (ty->as_string ());
const std::string hash_sig = mangle_name (hash);
- return kMangledSymbolPrefix + mangle_name (crate_name) + mangle_name (name)
- + hash_sig + kMangledSymbolDelim;
+ return kMangledSymbolPrefix + mangle_name (crate_name)
+ + mangle_canonical_path (path) + hash_sig + kMangledSymbolDelim;
}
+// FIXME this is a wee bit broken
std::string
Context::mangle_impl_item (const TyTy::BaseType *self, const TyTy::BaseType *ty,
const std::string &name) const
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index b1d0df3..07489f8 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -284,6 +284,9 @@ protected:
HIR::Type *lower_type_no_bounds (AST::TypeNoBounds *type);
HIR::TypeParamBound *lower_bound (AST::TypeParamBound *bound);
+
+ HIR::QualifiedPathType
+ lower_qual_path_type (AST::QualifiedPathType &qual_path_type);
};
} // namespace HIR
diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h
index 1c48651..3415567 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -48,6 +48,28 @@ private:
HIR::PathInExpression *translated;
};
+class ASTLowerQualPathInExpression : public ASTLoweringBase
+{
+ using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+ static HIR::QualifiedPathInExpression *
+ translate (AST::QualifiedPathInExpression *expr)
+ {
+ ASTLowerQualPathInExpression compiler;
+ expr->accept_vis (compiler);
+ rust_assert (compiler.translated);
+ return compiler.translated;
+ }
+
+ void visit (AST::QualifiedPathInExpression &expr) override;
+
+private:
+ ASTLowerQualPathInExpression () : translated (nullptr) {}
+
+ HIR::QualifiedPathInExpression *translated;
+};
+
class ASTLoweringExpr : public ASTLoweringBase
{
using Rust::HIR::ASTLoweringBase::visit;
@@ -145,6 +167,11 @@ public:
translated = ASTLowerPathInExpression::translate (&expr);
}
+ void visit (AST::QualifiedPathInExpression &expr) override
+ {
+ translated = ASTLowerQualPathInExpression::translate (&expr);
+ }
+
void visit (AST::ReturnExpr &expr) override
{
terminated = true;
diff --git a/gcc/rust/hir/rust-ast-lower-implitem.h b/gcc/rust/hir/rust-ast-lower-implitem.h
index cbc80d3..b2c7b13 100644
--- a/gcc/rust/hir/rust-ast-lower-implitem.h
+++ b/gcc/rust/hir/rust-ast-lower-implitem.h
@@ -354,10 +354,12 @@ public:
std::move (function_params),
std::move (return_type),
std::move (where_clause));
- HIR::Expr *block_expr
- = func.has_definition ()
- ? ASTLoweringExpr::translate (func.get_definition ().get ())
- : nullptr;
+ bool terminated = false;
+ std::unique_ptr<HIR::BlockExpr> block_expr
+ = func.has_definition () ? std::unique_ptr<HIR::BlockExpr> (
+ ASTLoweringBlock::translate (func.get_definition ().get (),
+ &terminated))
+ : nullptr;
auto crate_num = mappings->get_current_crate ();
Analysis::NodeMapping mapping (crate_num, func.get_node_id (),
@@ -366,13 +368,22 @@ public:
HIR::TraitItemFunc *trait_item
= new HIR::TraitItemFunc (mapping, std::move (decl),
- std::unique_ptr<HIR::Expr> (block_expr),
- func.get_outer_attrs (), func.get_locus ());
+ std::move (block_expr), func.get_outer_attrs (),
+ func.get_locus ());
translated = trait_item;
mappings->insert_hir_trait_item (mapping.get_crate_num (),
mapping.get_hirid (), translated);
mappings->insert_location (crate_num, mapping.get_hirid (),
trait_item->get_locus ());
+
+ // add the mappings for the function params at the end
+ for (auto &param : trait_item->get_decl ().get_function_params ())
+ {
+ mappings->insert_hir_param (mapping.get_crate_num (),
+ param.get_mappings ().get_hirid (), &param);
+ mappings->insert_location (crate_num, mapping.get_hirid (),
+ param.get_locus ());
+ }
}
void visit (AST::TraitItemMethod &method) override
@@ -423,10 +434,12 @@ public:
std::move (function_params),
std::move (return_type),
std::move (where_clause));
- HIR::Expr *block_expr
- = method.has_definition ()
- ? ASTLoweringExpr::translate (method.get_definition ().get ())
- : nullptr;
+ bool terminated = false;
+ std::unique_ptr<HIR::BlockExpr> block_expr
+ = method.has_definition () ? std::unique_ptr<HIR::BlockExpr> (
+ ASTLoweringBlock::translate (method.get_definition ().get (),
+ &terminated))
+ : nullptr;
auto crate_num = mappings->get_current_crate ();
Analysis::NodeMapping mapping (crate_num, method.get_node_id (),
@@ -435,13 +448,30 @@ public:
HIR::TraitItemFunc *trait_item
= new HIR::TraitItemFunc (mapping, std::move (decl),
- std::unique_ptr<HIR::Expr> (block_expr),
+ std::move (block_expr),
method.get_outer_attrs (), method.get_locus ());
translated = trait_item;
mappings->insert_hir_trait_item (mapping.get_crate_num (),
mapping.get_hirid (), translated);
mappings->insert_location (crate_num, mapping.get_hirid (),
trait_item->get_locus ());
+
+ // insert mappings for self
+ mappings->insert_hir_self_param (crate_num,
+ self_param.get_mappings ().get_hirid (),
+ &self_param);
+ mappings->insert_location (crate_num,
+ self_param.get_mappings ().get_hirid (),
+ self_param.get_locus ());
+
+ // add the mappings for the function params at the end
+ for (auto &param : trait_item->get_decl ().get_function_params ())
+ {
+ mappings->insert_hir_param (mapping.get_crate_num (),
+ param.get_mappings ().get_hirid (), &param);
+ mappings->insert_location (crate_num, mapping.get_hirid (),
+ param.get_locus ());
+ }
}
void visit (AST::TraitItemConst &constant) override
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index ed59777..e693799 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -282,6 +282,55 @@ ASTLowerPathInExpression::visit (AST::PathInExpression &expr)
expr.opening_scope_resolution ());
}
+HIR::QualifiedPathType
+ASTLoweringBase::lower_qual_path_type (AST::QualifiedPathType &qualified_type)
+{
+ HIR::Type *type
+ = ASTLoweringType::translate (qualified_type.get_type ().get ());
+ HIR::TypePath *trait
+ = qualified_type.has_as_clause ()
+ ? ASTLowerTypePath::translate (qualified_type.get_as_type_path ())
+ : nullptr;
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, qualified_type.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ return HIR::QualifiedPathType (mapping, std::unique_ptr<HIR::Type> (type),
+ std::unique_ptr<HIR::TypePath> (trait),
+ qualified_type.get_locus ());
+}
+
+void
+ASTLowerQualPathInExpression::visit (AST::QualifiedPathInExpression &expr)
+{
+ HIR::QualifiedPathType qual_path_type
+ = lower_qual_path_type (expr.get_qualified_path_type ());
+
+ std::vector<HIR::PathExprSegment> path_segments;
+ expr.iterate_path_segments ([&] (AST::PathExprSegment &s) mutable -> bool {
+ path_segments.push_back (lower_path_expr_seg (s));
+
+ // insert the mappings for the segment
+ HIR::PathExprSegment *lowered_seg = &path_segments.back ();
+ mappings->insert_hir_path_expr_seg (
+ lowered_seg->get_mappings ().get_crate_num (),
+ lowered_seg->get_mappings ().get_hirid (), lowered_seg);
+ return true;
+ });
+
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated = new HIR::QualifiedPathInExpression (mapping, qual_path_type,
+ std::move (path_segments),
+ expr.get_locus (),
+ expr.get_outer_attrs ());
+}
+
// rust-ast-lower-base.h
std::vector<std::unique_ptr<HIR::GenericParam> >
diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc
index dee2827..62262a2 100644
--- a/gcc/rust/hir/tree/rust-hir-full-test.cc
+++ b/gcc/rust/hir/tree/rust-hir-full-test.cc
@@ -1192,11 +1192,11 @@ std::string
QualifiedPathType::as_string () const
{
std::string str ("<");
- str += type_to_invoke_on->as_string ();
+ str += type->as_string ();
if (has_as_clause ())
{
- str += " as " + trait_path.as_string ();
+ str += " as " + trait->as_string ();
}
return str + ">";
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h
index 32ee317..3ce1342 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -2270,7 +2270,7 @@ class TraitItemFunc : public TraitItem
{
AST::AttrVec outer_attrs;
TraitFunctionDecl decl;
- std::unique_ptr<Expr> block_expr;
+ std::unique_ptr<BlockExpr> block_expr;
Location locus;
public:
@@ -2278,8 +2278,8 @@ public:
bool has_definition () const { return block_expr != nullptr; }
TraitItemFunc (Analysis::NodeMapping mappings, TraitFunctionDecl decl,
- std::unique_ptr<Expr> block_expr, AST::AttrVec outer_attrs,
- Location locus)
+ std::unique_ptr<BlockExpr> block_expr,
+ AST::AttrVec outer_attrs, Location locus)
: TraitItem (mappings), outer_attrs (std::move (outer_attrs)),
decl (std::move (decl)), block_expr (std::move (block_expr)),
locus (locus)
@@ -2291,7 +2291,7 @@ public:
decl (other.decl), locus (other.locus)
{
if (other.block_expr != nullptr)
- block_expr = other.block_expr->clone_expr ();
+ block_expr = other.block_expr->clone_block_expr ();
}
// Overloaded assignment operator to clone
@@ -2303,7 +2303,7 @@ public:
locus = other.locus;
mappings = other.mappings;
if (other.block_expr != nullptr)
- block_expr = other.block_expr->clone_expr ();
+ block_expr = other.block_expr->clone_block_expr ();
return *this;
}
@@ -2322,12 +2322,17 @@ public:
bool has_block_defined () const { return block_expr != nullptr; }
- std::unique_ptr<Expr> &get_block_expr ()
+ std::unique_ptr<BlockExpr> &get_block_expr ()
{
rust_assert (has_block_defined ());
return block_expr;
}
+ const std::string trait_identifier () const override final
+ {
+ return decl.get_function_name ();
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TraitItemFunc *clone_trait_item_impl () const override
@@ -2400,6 +2405,8 @@ public:
return expr;
}
+ const std::string trait_identifier () const override final { return name; }
+
protected:
// Clone function implementation as (not pure) virtual method
TraitItemConst *clone_trait_item_impl () const override
@@ -2474,6 +2481,8 @@ public:
return type_param_bounds;
}
+ const std::string trait_identifier () const override final { return name; }
+
protected:
// Clone function implementation as (not pure) virtual method
TraitItemType *clone_trait_item_impl () const override
diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h
index 5d9f965..a8bbbb6 100644
--- a/gcc/rust/hir/tree/rust-hir-path.h
+++ b/gcc/rust/hir/tree/rust-hir-path.h
@@ -709,26 +709,26 @@ public:
struct QualifiedPathType
{
private:
- std::unique_ptr<Type> type_to_invoke_on;
-
- // bool has_as_clause;
- TypePath trait_path;
-
+ std::unique_ptr<Type> type;
+ std::unique_ptr<TypePath> trait;
Location locus;
+ Analysis::NodeMapping mappings;
public:
// Constructor
- QualifiedPathType (std::unique_ptr<Type> invoke_on_type,
- Location locus = Location (),
- TypePath trait_path = TypePath::create_error ())
- : type_to_invoke_on (std::move (invoke_on_type)),
- trait_path (std::move (trait_path)), locus (locus)
+ QualifiedPathType (Analysis::NodeMapping mappings, std::unique_ptr<Type> type,
+ std::unique_ptr<TypePath> trait, Location locus)
+ : type (std::move (type)), trait (std::move (trait)), locus (locus),
+ mappings (mappings)
{}
// Copy constructor uses custom deep copy for Type to preserve polymorphism
QualifiedPathType (QualifiedPathType const &other)
- : type_to_invoke_on (other.type_to_invoke_on->clone_type ()),
- trait_path (other.trait_path), locus (other.locus)
+ : type (other.type->clone_type ()),
+ trait (other.has_as_clause () ? std::unique_ptr<HIR::TypePath> (
+ new HIR::TypePath (*other.trait))
+ : nullptr),
+ locus (other.locus), mappings (other.mappings)
{}
// default destructor
@@ -737,9 +737,14 @@ public:
// overload assignment operator to use custom clone method
QualifiedPathType &operator= (QualifiedPathType const &other)
{
- type_to_invoke_on = other.type_to_invoke_on->clone_type ();
- trait_path = other.trait_path;
+ type = other.type->clone_type ();
locus = other.locus;
+ mappings = other.mappings;
+ trait
+ = other.has_as_clause ()
+ ? std::unique_ptr<HIR::TypePath> (new HIR::TypePath (*other.trait))
+ : nullptr;
+
return *this;
}
@@ -748,20 +753,21 @@ public:
QualifiedPathType &operator= (QualifiedPathType &&other) = default;
// Returns whether the qualified path type has a rebind as clause.
- bool has_as_clause () const { return !trait_path.is_error (); }
-
- // Returns whether the qualified path type is in an error state.
- bool is_error () const { return type_to_invoke_on == nullptr; }
-
- // Creates an error state qualified path type.
- static QualifiedPathType create_error ()
- {
- return QualifiedPathType (nullptr);
- }
+ bool has_as_clause () const { return trait != nullptr; }
std::string as_string () const;
Location get_locus () const { return locus; }
+
+ Analysis::NodeMapping get_mappings () const { return mappings; }
+
+ std::unique_ptr<Type> &get_type () { return type; }
+
+ std::unique_ptr<TypePath> &get_trait ()
+ {
+ rust_assert (has_as_clause ());
+ return trait;
+ }
};
/* HIR node representing a qualified path-in-expression pattern (path that
@@ -785,25 +791,15 @@ public:
path_type (std::move (qual_path_type)), locus (locus)
{}
- /* TODO: maybe make a shortcut constructor that has QualifiedPathType elements
- * as params */
-
- // Returns whether qualified path in expression is in an error state.
- bool is_error () const { return path_type.is_error (); }
-
- // Creates an error qualified path in expression.
- static QualifiedPathInExpression create_error ()
- {
- return QualifiedPathInExpression (Analysis::NodeMapping::get_error (),
- QualifiedPathType::create_error (),
- std::vector<PathExprSegment> ());
- }
-
Location get_locus () const { return locus; }
Location get_locus_slow () const override { return get_locus (); }
void accept_vis (HIRVisitor &vis) override;
+ QualifiedPathType &get_path_type () { return path_type; }
+
+ Location get_locus () { return locus; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index 20408bb..b8acf1a 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -646,7 +646,9 @@ public:
virtual void accept_vis (HIRVisitor &vis) = 0;
- const Analysis::NodeMapping &get_mappings () const { return mappings; }
+ virtual const std::string trait_identifier () const = 0;
+
+ const Analysis::NodeMapping get_mappings () const { return mappings; }
};
class ImplItem
diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h
index e7e37d4..c5f88f9 100644
--- a/gcc/rust/resolve/rust-ast-resolve-expr.h
+++ b/gcc/rust/resolve/rust-ast-resolve-expr.h
@@ -39,10 +39,22 @@ public:
resolver.resolve_path (expr);
}
+ static void go (AST::QualifiedPathInExpression *expr, NodeId parent)
+ {
+ ResolvePath resolver (parent);
+ resolver.resolve_path (expr);
+ }
+
private:
ResolvePath (NodeId parent) : ResolverBase (parent) {}
void resolve_path (AST::PathInExpression *expr);
+
+ void resolve_path (AST::QualifiedPathInExpression *expr);
+
+ void resolve_segments (CanonicalPath prefix, size_t offs,
+ std::vector<AST::PathExprSegment> &segs,
+ NodeId expr_node_id, Location expr_locus);
};
class ResolveExpr : public ResolverBase
@@ -75,6 +87,11 @@ public:
ResolvePath::go (&expr, parent);
}
+ void visit (AST::QualifiedPathInExpression &expr) override
+ {
+ ResolvePath::go (&expr, parent);
+ }
+
void visit (AST::ReturnExpr &expr) override
{
if (expr.has_returned_expr ())
diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
index 2c1de66..1239206 100644
--- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h
+++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
@@ -206,6 +206,19 @@ public:
impl_type_seg);
CanonicalPath impl_prefix = prefix.append (projection);
+ resolver->get_name_scope ().insert (
+ impl_prefix, impl_block.get_node_id (), impl_block.get_locus (), false,
+ [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+ RichLocation r (impl_block.get_locus ());
+ r.add_range (locus);
+ rust_error_at (r, "redefined multiple times");
+ });
+ resolver->insert_new_definition (impl_block.get_node_id (),
+ Definition{impl_block.get_node_id (),
+ impl_block.get_node_id ()});
+ resolver->insert_resolved_name (impl_block.get_node_id (),
+ impl_block.get_node_id ());
+
for (auto &impl_item : impl_block.get_impl_items ())
ResolveToplevelImplItem::go (impl_item.get (), impl_prefix);
}
diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc
index 5b24816..5b6bb24 100644
--- a/gcc/rust/resolve/rust-ast-resolve.cc
+++ b/gcc/rust/resolve/rust-ast-resolve.cc
@@ -483,12 +483,13 @@ void
ResolvePath::resolve_path (AST::PathInExpression *expr)
{
// resolve root segment first then apply segments in turn
- AST::PathExprSegment &root_segment = expr->get_segments ().at (0);
+ std::vector<AST::PathExprSegment> &segs = expr->get_segments ();
+ AST::PathExprSegment &root_segment = segs.at (0);
AST::PathIdentSegment &root_ident_seg = root_segment.get_ident_segment ();
bool segment_is_type = false;
CanonicalPath root_seg_path
- = CanonicalPath::new_seg (expr->get_node_id (),
+ = CanonicalPath::new_seg (root_segment.get_node_id (),
root_ident_seg.as_string ());
// name scope first
@@ -515,7 +516,7 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
{
rust_error_at (expr->get_locus (),
"Cannot find path %<%s%> in this scope",
- expr->as_string ().c_str ());
+ root_segment.as_string ().c_str ());
return;
}
@@ -531,7 +532,8 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
}
}
- if (expr->is_single_segment ())
+ bool is_single_segment = segs.size () == 1;
+ if (is_single_segment)
{
if (segment_is_type)
resolver->insert_resolved_type (expr->get_node_id (), resolved_node);
@@ -544,11 +546,97 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
return;
}
+ resolve_segments (root_seg_path, 1, expr->get_segments (),
+ expr->get_node_id (), expr->get_locus ());
+}
+
+void
+ResolvePath::resolve_path (AST::QualifiedPathInExpression *expr)
+{
+ AST::QualifiedPathType &root_segment = expr->get_qualified_path_type ();
+
+ bool canonicalize_type_with_generics = false;
+ ResolveType::go (&root_segment.get_as_type_path (),
+ root_segment.get_node_id (),
+ canonicalize_type_with_generics);
+
+ ResolveType::go (root_segment.get_type ().get (), root_segment.get_node_id (),
+ canonicalize_type_with_generics);
+
+ bool canonicalize_type_args = true;
+ bool type_resolve_generic_args = true;
+
+ CanonicalPath impl_type_seg
+ = ResolveTypeToCanonicalPath::resolve (*root_segment.get_type ().get (),
+ canonicalize_type_args,
+ type_resolve_generic_args);
+
+ CanonicalPath trait_type_seg
+ = ResolveTypeToCanonicalPath::resolve (root_segment.get_as_type_path (),
+ canonicalize_type_args,
+ type_resolve_generic_args);
+ CanonicalPath root_seg_path
+ = TraitImplProjection::resolve (root_segment.get_node_id (), trait_type_seg,
+ impl_type_seg);
+ bool segment_is_type = false;
+
+ // name scope first
+ if (resolver->get_name_scope ().lookup (root_seg_path, &resolved_node))
+ {
+ segment_is_type = false;
+ resolver->insert_resolved_name (root_segment.get_node_id (),
+ resolved_node);
+ resolver->insert_new_definition (root_segment.get_node_id (),
+ Definition{expr->get_node_id (),
+ parent});
+ }
+ // check the type scope
+ else if (resolver->get_type_scope ().lookup (root_seg_path, &resolved_node))
+ {
+ segment_is_type = true;
+ resolver->insert_resolved_type (root_segment.get_node_id (),
+ resolved_node);
+ resolver->insert_new_definition (root_segment.get_node_id (),
+ Definition{expr->get_node_id (),
+ parent});
+ }
+ else
+ {
+ rust_error_at (expr->get_locus (),
+ "Cannot find path %<%s%> in this scope",
+ root_segment.as_string ().c_str ());
+ return;
+ }
+
+ bool is_single_segment = expr->get_segments ().empty ();
+ if (is_single_segment)
+ {
+ if (segment_is_type)
+ resolver->insert_resolved_type (expr->get_node_id (), resolved_node);
+ else
+ resolver->insert_resolved_name (expr->get_node_id (), resolved_node);
+
+ resolver->insert_new_definition (expr->get_node_id (),
+ Definition{expr->get_node_id (),
+ parent});
+ return;
+ }
+
+ resolve_segments (root_seg_path, 0, expr->get_segments (),
+ expr->get_node_id (), expr->get_locus ());
+}
+
+void
+ResolvePath::resolve_segments (CanonicalPath prefix, size_t offs,
+ std::vector<AST::PathExprSegment> &segs,
+ NodeId expr_node_id, Location expr_locus)
+{
// we can attempt to resolve this path fully
- CanonicalPath path = root_seg_path;
- for (size_t i = 1; i < expr->get_segments ().size (); i++)
+ CanonicalPath path = prefix;
+ bool segment_is_type = false;
+ for (size_t i = offs; i < segs.size (); i++)
{
- AST::PathExprSegment &seg = expr->get_segments ().at (i);
+ AST::PathExprSegment &seg = segs.at (i);
auto s = ResolvePathSegmentToCanonicalPath::resolve (seg);
path = path.append (s);
@@ -560,8 +648,7 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
{
resolver->insert_resolved_name (seg.get_node_id (), resolved_node);
resolver->insert_new_definition (seg.get_node_id (),
- Definition{expr->get_node_id (),
- parent});
+ Definition{expr_node_id, parent});
}
// check the type scope
else if (resolver->get_type_scope ().lookup (path, &resolved_node))
@@ -569,8 +656,7 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
segment_is_type = true;
resolver->insert_resolved_type (seg.get_node_id (), resolved_node);
resolver->insert_new_definition (seg.get_node_id (),
- Definition{expr->get_node_id (),
- parent});
+ Definition{expr_node_id, parent});
}
else
{
@@ -621,13 +707,12 @@ ResolvePath::resolve_path (AST::PathInExpression *expr)
if (resolved_node != UNKNOWN_NODEID)
{
if (segment_is_type)
- resolver->insert_resolved_type (expr->get_node_id (), resolved_node);
+ resolver->insert_resolved_type (expr_node_id, resolved_node);
else
- resolver->insert_resolved_name (expr->get_node_id (), resolved_node);
+ resolver->insert_resolved_name (expr_node_id, resolved_node);
- resolver->insert_new_definition (expr->get_node_id (),
- Definition{expr->get_node_id (),
- parent});
+ resolver->insert_new_definition (expr_node_id,
+ Definition{expr_node_id, parent});
}
}
diff --git a/gcc/rust/typecheck/rust-hir-const-fold.h b/gcc/rust/typecheck/rust-hir-const-fold.h
index 8efbb18..9e0450e 100644
--- a/gcc/rust/typecheck/rust-hir-const-fold.h
+++ b/gcc/rust/typecheck/rust-hir-const-fold.h
@@ -55,6 +55,8 @@ public:
void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); }
+ void visit (TyTy::ProjectionType &) override { gcc_unreachable (); }
+
void visit (TyTy::TupleType &type) override
{
if (type.num_fields () == 0)
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index 22b1074..f737141 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -51,6 +51,7 @@ struct PathProbeCandidate
{
const TraitReference *trait_ref;
const TraitItemReference *item_ref;
+ HIR::ImplBlock *impl;
};
CandidateType type;
@@ -128,19 +129,22 @@ public:
if (!probe_bounds)
return probe.candidates;
- std::vector<TraitReference *> probed_bounds
+ std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> probed_bounds
= TypeBoundsProbe::Probe (receiver);
- std::vector<const TraitReference *> specified_bounds;
+ std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
+ specified_bounds;
for (const TyTy::TypeBoundPredicate &predicate :
receiver->get_specified_bounds ())
{
const TraitReference *trait_item = predicate.get ();
- specified_bounds.push_back (trait_item);
+
+ // FIXME lookup impl_block for this trait impl for this receiver
+ specified_bounds.push_back ({trait_item, nullptr});
}
- std::vector<const TraitReference *> union_type_bounds
- = probe.union_bounds (probed_bounds, specified_bounds);
+ std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
+ union_type_bounds = probe.union_bounds (probed_bounds, specified_bounds);
probe.process_traits_for_candidates (union_type_bounds,
ignore_mandatory_trait_items);
return probe.candidates;
@@ -230,11 +234,15 @@ private:
}
void process_traits_for_candidates (
- const std::vector<const TraitReference *> traits,
+ const std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
+ traits,
bool ignore_mandatory_trait_items)
{
- for (const TraitReference *trait_ref : traits)
+ for (auto &ref : traits)
{
+ const TraitReference *trait_ref = ref.first;
+ HIR::ImplBlock *impl = ref.second;
+
const TraitItemReference *trait_item_ref = nullptr;
if (!trait_ref->lookup_trait_item (search.as_string (),
&trait_item_ref))
@@ -296,7 +304,7 @@ private:
}
PathProbeCandidate::TraitItemCandidate trait_item_candidate{
- trait_ref, trait_item_ref};
+ trait_ref, trait_item_ref, impl};
PathProbeCandidate candidate{candidate_type,
trait_item_tyty,
trait_ref->get_locus (),
@@ -312,24 +320,27 @@ private:
current_impl (nullptr)
{}
- std::vector<const TraitReference *>
- union_bounds (const std::vector</*const*/ TraitReference *> a,
- const std::vector<const TraitReference *> b) const
+ std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
+ union_bounds (
+ const std::vector<std::pair</*const*/ TraitReference *, HIR::ImplBlock *>>
+ a,
+ const std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> b)
+ const
{
- std::map<DefId, const TraitReference *> mapper;
- for (const TraitReference *ref : a)
+ std::map<DefId, std::pair<const TraitReference *, HIR::ImplBlock *>> mapper;
+ for (auto &ref : a)
{
- mapper.insert ({ref->get_mappings ().get_defid (), ref});
+ mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
}
- for (const TraitReference *ref : b)
+ for (auto &ref : b)
{
- mapper.insert ({ref->get_mappings ().get_defid (), ref});
+ mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
}
- std::vector<const TraitReference *> union_set;
+ std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> union_set;
for (auto it = mapper.begin (); it != mapper.end (); it++)
{
- union_set.push_back (it->second);
+ union_set.push_back ({it->second.first, it->second.second});
}
return union_set;
}
diff --git a/gcc/rust/typecheck/rust-hir-trait-ref.h b/gcc/rust/typecheck/rust-hir-trait-ref.h
index 21a8beb..9d16e36 100644
--- a/gcc/rust/typecheck/rust-hir-trait-ref.h
+++ b/gcc/rust/typecheck/rust-hir-trait-ref.h
@@ -21,6 +21,7 @@
#include "rust-hir-full.h"
#include "rust-tyty-visitor.h"
+#include "rust-hir-type-check-util.h"
namespace Rust {
namespace Resolver {
@@ -111,9 +112,11 @@ public:
const HIR::TraitItem *get_hir_trait_item () const { return hir_trait_item; }
+ HIR::TraitItem *get_hir_trait_item () { return hir_trait_item; }
+
Location get_locus () const { return locus; }
- const Analysis::NodeMapping &get_mappings () const
+ const Analysis::NodeMapping get_mappings () const
{
return hir_trait_item->get_mappings ();
}
@@ -146,6 +149,19 @@ public:
return get_error ();
}
+ Analysis::NodeMapping get_parent_trait_mappings () const;
+
+ // this is called when the trait is completed resolution and gives the items a
+ // chance to run their specific type resolution passes. If we call their
+ // resolution on construction it can lead to a case where the trait being
+ // resolved recursively trying to resolve the trait itself infinitely since
+ // the trait will not be stored in its own map yet
+ void on_resolved ();
+
+ void associated_type_set (TyTy::BaseType *ty);
+
+ void associated_type_reset ();
+
private:
TyTy::ErrorType *get_error () const
{
@@ -160,6 +176,11 @@ private:
TyTy::BaseType *get_type_from_fn (/*const*/ HIR::TraitItemFunc &fn) const;
+ bool is_item_resolved () const;
+ void resolve_item (HIR::TraitItemType &type);
+ void resolve_item (HIR::TraitItemConst &constant);
+ void resolve_item (HIR::TraitItemFunc &func);
+
std::string identifier;
bool optional_flag;
TraitItemType type;
@@ -172,6 +193,7 @@ private:
Resolver::TypeCheckContext *context;
};
+// this wraps up the HIR::Trait so we can do analysis on it
class TraitReference
{
public:
@@ -233,6 +255,31 @@ public:
return hir_trait_ref->get_mappings ();
}
+ bool lookup_hir_trait_item (const HIR::TraitItem &item,
+ TraitItemReference **ref)
+ {
+ return lookup_trait_item (item.trait_identifier (), ref);
+ }
+
+ bool lookup_trait_item (const std::string &ident, TraitItemReference **ref)
+ {
+ for (auto &item : item_refs)
+ {
+ if (ident.compare (item.get_identifier ()) == 0)
+ {
+ *ref = &item;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool lookup_hir_trait_item (const HIR::TraitItem &item,
+ const TraitItemReference **ref) const
+ {
+ return lookup_trait_item (item.trait_identifier (), ref);
+ }
+
bool lookup_trait_item (const std::string &ident,
const TraitItemReference **ref) const
{
@@ -269,11 +316,60 @@ public:
return item_refs;
}
+ void on_resolved ()
+ {
+ for (auto &item : item_refs)
+ {
+ item.on_resolved ();
+ }
+ }
+
+ void clear_associated_types ()
+ {
+ for (auto &item : item_refs)
+ {
+ bool is_assoc_type = item.get_trait_item_type ()
+ == TraitItemReference::TraitItemType::TYPE;
+ if (is_assoc_type)
+ item.associated_type_reset ();
+ }
+ }
+
private:
const HIR::Trait *hir_trait_ref;
std::vector<TraitItemReference> item_refs;
};
+class AssociatedImplTrait
+{
+public:
+ AssociatedImplTrait (TraitReference *trait, HIR::ImplBlock *impl,
+ TyTy::BaseType *self,
+ Resolver::TypeCheckContext *context)
+ : trait (trait), impl (impl), self (self), context (context)
+ {}
+
+ TraitReference *get_trait () { return trait; }
+
+ HIR::ImplBlock *get_impl_block () { return impl; }
+
+ TyTy::BaseType *get_self () { return self; }
+
+ void setup_associated_types ();
+
+ void reset_associated_types ();
+
+ TyTy::BaseType *get_projected_type (const TraitItemReference *trait_item_ref,
+ TyTy::BaseType *reciever, HirId ref,
+ Location expr_locus);
+
+private:
+ TraitReference *trait;
+ HIR::ImplBlock *impl;
+ TyTy::BaseType *self;
+ Resolver::TypeCheckContext *context;
+};
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
new file mode 100644
index 0000000..cf3f2fb
--- /dev/null
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -0,0 +1,231 @@
+// Copyright (C) 2021 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-trait-resolve.h"
+#include "rust-hir-type-check-expr.h"
+
+namespace Rust {
+namespace Resolver {
+
+void
+ResolveTraitItemToRef::visit (HIR::TraitItemType &type)
+{
+ // create trait-item-ref
+ Location locus = type.get_locus ();
+ bool is_optional = false;
+ std::string identifier = type.get_name ();
+
+ resolved = TraitItemReference (identifier, is_optional,
+ TraitItemReference::TraitItemType::TYPE, &type,
+ self, substitutions, locus);
+}
+
+void
+ResolveTraitItemToRef::visit (HIR::TraitItemConst &cst)
+{
+ // create trait-item-ref
+ Location locus = cst.get_locus ();
+ bool is_optional = cst.has_expr ();
+ std::string identifier = cst.get_name ();
+
+ resolved = TraitItemReference (identifier, is_optional,
+ TraitItemReference::TraitItemType::CONST, &cst,
+ self, substitutions, locus);
+}
+
+void
+ResolveTraitItemToRef::visit (HIR::TraitItemFunc &fn)
+{
+ // create trait-item-ref
+ Location locus = fn.get_locus ();
+ bool is_optional = fn.has_block_defined ();
+ std::string identifier = fn.get_decl ().get_function_name ();
+
+ resolved = TraitItemReference (identifier, is_optional,
+ TraitItemReference::TraitItemType::FN, &fn,
+ self, substitutions, locus);
+}
+
+// TraitItemReference items
+
+void
+TraitItemReference::on_resolved ()
+{
+ switch (type)
+ {
+ case CONST:
+ resolve_item (static_cast<HIR::TraitItemConst &> (*hir_trait_item));
+ break;
+
+ case TYPE:
+ resolve_item (static_cast<HIR::TraitItemType &> (*hir_trait_item));
+ break;
+
+ case FN:
+ resolve_item (static_cast<HIR::TraitItemFunc &> (*hir_trait_item));
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+TraitItemReference::resolve_item (HIR::TraitItemType &type)
+{
+ TyTy::BaseType *ty
+ = new TyTy::PlaceholderType (type.get_name (),
+ type.get_mappings ().get_hirid ());
+ context->insert_type (type.get_mappings (), ty);
+}
+
+void
+TraitItemReference::resolve_item (HIR::TraitItemConst &constant)
+{
+ // TODO
+}
+
+void
+TraitItemReference::resolve_item (HIR::TraitItemFunc &func)
+{
+ if (!is_optional ())
+ return;
+
+ TyTy::BaseType *item_tyty = get_tyty ();
+ if (item_tyty->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+
+ // check the block and return types
+ rust_assert (item_tyty->get_kind () == TyTy::TypeKind::FNDEF);
+
+ // need to get the return type from this
+ TyTy::FnType *resolved_fn_type = static_cast<TyTy::FnType *> (item_tyty);
+ auto expected_ret_tyty = resolved_fn_type->get_return_type ();
+ context->push_return_type (expected_ret_tyty);
+
+ auto block_expr_ty
+ = TypeCheckExpr::Resolve (func.get_block_expr ().get (), false);
+
+ context->pop_return_type ();
+
+ if (block_expr_ty->get_kind () != TyTy::NEVER)
+ expected_ret_tyty->unify (block_expr_ty);
+}
+
+void
+TraitItemReference::associated_type_set (TyTy::BaseType *ty)
+{
+ rust_assert (get_trait_item_type () == TraitItemType::TYPE);
+
+ TyTy::BaseType *item_ty = get_tyty ();
+ rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
+ TyTy::PlaceholderType *placeholder
+ = static_cast<TyTy::PlaceholderType *> (item_ty);
+
+ placeholder->set_associated_type (ty->get_ref ());
+}
+
+void
+TraitItemReference::associated_type_reset ()
+{
+ rust_assert (get_trait_item_type () == TraitItemType::TYPE);
+
+ TyTy::BaseType *item_ty = get_tyty ();
+ rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
+ TyTy::PlaceholderType *placeholder
+ = static_cast<TyTy::PlaceholderType *> (item_ty);
+
+ placeholder->clear_associated_type ();
+}
+
+void
+AssociatedImplTrait::setup_associated_types ()
+{
+ ImplTypeIterator iter (*impl, [&] (HIR::TypeAlias &type) {
+ TraitItemReference *resolved_trait_item = nullptr;
+ bool ok = trait->lookup_trait_item (type.get_new_type_name (),
+ &resolved_trait_item);
+ if (!ok)
+ return;
+ if (resolved_trait_item->get_trait_item_type ()
+ != TraitItemReference::TraitItemType::TYPE)
+ return;
+
+ TyTy::BaseType *lookup;
+ if (!context->lookup_type (type.get_mappings ().get_hirid (), &lookup))
+ return;
+
+ resolved_trait_item->associated_type_set (lookup);
+ });
+ iter.go ();
+}
+
+void
+AssociatedImplTrait::reset_associated_types ()
+{
+ trait->clear_associated_types ();
+}
+
+Analysis::NodeMapping
+TraitItemReference::get_parent_trait_mappings () const
+{
+ auto mappings = Analysis::Mappings::get ();
+
+ HIR::Trait *trait
+ = mappings->lookup_trait_item_mapping (get_mappings ().get_hirid ());
+ rust_assert (trait != nullptr);
+
+ return trait->get_mappings ();
+}
+
+TyTy::BaseType *
+AssociatedImplTrait::get_projected_type (
+ const TraitItemReference *trait_item_ref, TyTy::BaseType *receiver, HirId ref,
+ Location expr_locus)
+{
+ TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ()->clone ();
+
+ // we can substitute the Self with the receiver here
+ if (trait_item_tyty->get_kind () == TyTy::TypeKind::FNDEF)
+ {
+ TyTy::FnType *fn = static_cast<TyTy::FnType *> (trait_item_tyty);
+ TyTy::SubstitutionParamMapping *param = nullptr;
+ for (auto &param_mapping : fn->get_substs ())
+ {
+ const HIR::TypeParam &type_param = param_mapping.get_generic_param ();
+ if (type_param.get_type_representation ().compare ("Self") == 0)
+ {
+ param = &param_mapping;
+ break;
+ }
+ }
+ rust_assert (param != nullptr);
+
+ std::vector<TyTy::SubstitutionArg> mappings;
+ mappings.push_back (TyTy::SubstitutionArg (param, receiver->clone ()));
+
+ Location locus; // FIXME
+ TyTy::SubstitutionArgumentMappings args (std::move (mappings), locus);
+ trait_item_tyty = SubstMapperInternal::Resolve (trait_item_tyty, args);
+ }
+
+ return trait_item_tyty;
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.h b/gcc/rust/typecheck/rust-hir-trait-resolve.h
index 1669a37..6874a3a 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.h
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.h
@@ -42,45 +42,11 @@ public:
return resolver.resolved;
}
- void visit (HIR::TraitItemType &type) override
- {
- TyTy::BaseType *ty
- = new TyTy::PlaceholderType (type.get_mappings ().get_hirid ());
- context->insert_type (type.get_mappings (), ty);
-
- // create trait-item-ref
- Location locus = type.get_locus ();
- bool is_optional = false;
- std::string identifier = type.get_name ();
-
- resolved = TraitItemReference (identifier, is_optional,
- TraitItemReference::TraitItemType::TYPE,
- &type, self, substitutions, locus);
- }
+ void visit (HIR::TraitItemType &type) override;
- void visit (HIR::TraitItemConst &cst) override
- {
- // create trait-item-ref
- Location locus = cst.get_locus ();
- bool is_optional = cst.has_expr ();
- std::string identifier = cst.get_name ();
-
- resolved = TraitItemReference (identifier, is_optional,
- TraitItemReference::TraitItemType::CONST,
- &cst, self, substitutions, locus);
- }
+ void visit (HIR::TraitItemConst &cst) override;
- void visit (HIR::TraitItemFunc &fn) override
- {
- // create trait-item-ref
- Location locus = fn.get_locus ();
- bool is_optional = fn.has_block_defined ();
- std::string identifier = fn.get_decl ().get_function_name ();
-
- resolved = TraitItemReference (identifier, is_optional,
- TraitItemReference::TraitItemType::FN, &fn,
- self, substitutions, locus);
- }
+ void visit (HIR::TraitItemFunc &fn) override;
private:
ResolveTraitItemToRef (
@@ -188,6 +154,11 @@ private:
trait_reference->get_mappings ().get_defid (), &tref);
rust_assert (ok);
+ // hook to allow the trait to resolve its optional item blocks, we cant
+ // resolve the blocks of functions etc because it can end up in a recursive
+ // loop of trying to resolve traits as required by the types
+ tref->on_resolved ();
+
return tref;
}
diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h
index ce694da..1ba6049 100644
--- a/gcc/rust/typecheck/rust-hir-type-bounds.h
+++ b/gcc/rust/typecheck/rust-hir-type-bounds.h
@@ -31,13 +31,28 @@ class TypeBoundsProbe : public TypeCheckBase
using Rust::Resolver::TypeCheckBase::visit;
public:
- static std::vector<TraitReference *> Probe (const TyTy::BaseType *receiver)
+ static std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
+ Probe (const TyTy::BaseType *receiver)
{
TypeBoundsProbe probe (receiver);
probe.scan ();
return probe.trait_references;
}
+ static bool is_bound_satisfied_for_type (TyTy::BaseType *receiver,
+ TraitReference *ref)
+ {
+ std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds
+ = Probe (receiver);
+ for (auto &bound : bounds)
+ {
+ TraitReference *b = bound.first;
+ if (b == ref)
+ return true;
+ }
+ return false;
+ }
+
private:
void scan ();
@@ -47,7 +62,7 @@ private:
{}
const TyTy::BaseType *receiver;
- std::vector<TraitReference *> trait_references;
+ std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> trait_references;
};
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index d39b2ee..e3347ea 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -28,6 +28,8 @@
#include "rust-hir-path-probe.h"
#include "rust-substitution-mapper.h"
#include "rust-hir-const-fold.h"
+#include "rust-hir-trait-resolve.h"
+#include "rust-hir-type-bounds.h"
namespace Rust {
namespace Resolver {
@@ -923,146 +925,168 @@ public:
infered = resolved->get_field_type ();
}
- void visit (HIR::PathInExpression &expr) override
+ void visit (HIR::QualifiedPathInExpression &expr) override
{
- NodeId resolved_node_id = UNKNOWN_NODEID;
+ HIR::QualifiedPathType qual_path_type = expr.get_path_type ();
+ TyTy::BaseType *root
+ = TypeCheckType::Resolve (qual_path_type.get_type ().get ());
+ if (root->get_kind () == TyTy::TypeKind::ERROR)
+ return;
- size_t offset = -1;
- TyTy::BaseType *tyseg
- = resolve_root_path (expr, &offset, &resolved_node_id);
+ if (!qual_path_type.has_as_clause ())
+ {
+ // then this is just a normal path-in-expression
+ NodeId root_resolved_node_id = UNKNOWN_NODEID;
+ bool ok = resolver->lookup_resolved_type (
+ qual_path_type.get_type ()->get_mappings ().get_nodeid (),
+ &root_resolved_node_id);
+ rust_assert (ok);
+
+ resolve_segments (root_resolved_node_id, expr.get_segments (), 0, root,
+ expr.get_mappings (), expr.get_locus ());
+ }
- rust_assert (tyseg != nullptr);
+ // Resolve the trait now
+ TraitReference *trait_ref
+ = TraitResolver::Resolve (*qual_path_type.get_trait ().get ());
+ if (trait_ref->is_error ())
+ return;
- if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
+ // does this type actually implement this type-bound?
+ if (!TypeBoundsProbe::is_bound_satisfied_for_type (root, trait_ref))
return;
- // this is the case where the name resolver has already fully resolved the
- // name, which means all the work is already done.
- bool name_resolved_fully = offset >= expr.get_num_segments ();
+ // then we need to look at the next segment to create perform the correct
+ // projection type
+ if (expr.get_segments ().empty ())
+ return;
- if (expr.get_num_segments () == 1)
- {
- Location locus = expr.get_segments ().back ().get_locus ();
+ // we need resolve to the impl block
+ NodeId impl_resolved_id = UNKNOWN_NODEID;
+ bool ok = resolver->lookup_resolved_name (
+ qual_path_type.get_mappings ().get_nodeid (), &impl_resolved_id);
+ rust_assert (ok);
- bool is_big_self
- = expr.get_segments ().front ().get_segment ().as_string ().compare (
- "Self")
- == 0;
- if (!is_big_self && tyseg->needs_generic_substitutions ())
- {
- tyseg = SubstMapper::InferSubst (tyseg, locus);
- }
+ HirId impl_block_id;
+ ok = mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (),
+ impl_resolved_id, &impl_block_id);
+ rust_assert (ok);
- infered = tyseg;
- return;
- }
+ AssociatedImplTrait *lookup_associated = nullptr;
+ bool found_impl_trait
+ = context->lookup_associated_trait_impl (impl_block_id,
+ &lookup_associated);
+ rust_assert (found_impl_trait);
- TyTy::BaseType *prev_segment = tyseg;
- for (size_t i = offset; i < expr.get_num_segments (); i++)
+ DefId resolved_item_id = UNKNOWN_DEFID;
+ HIR::PathExprSegment &item_seg = expr.get_segments ().at (0);
+
+ const TraitItemReference *trait_item_ref = nullptr;
+ ok = trait_ref->lookup_trait_item (item_seg.get_segment ().as_string (),
+ &trait_item_ref);
+ if (!ok)
{
- HIR::PathExprSegment &seg = expr.get_segments ().at (i);
+ rust_error_at (item_seg.get_locus (), "unknown associated item");
+ return;
+ }
+ resolved_item_id = trait_item_ref->get_mappings ().get_defid ();
- bool reciever_is_generic
- = prev_segment->get_kind () == TyTy::TypeKind::PARAM;
- bool probe_bounds = true;
- bool probe_impls = !reciever_is_generic;
- bool ignore_mandatory_trait_items = !reciever_is_generic;
+ infered = lookup_associated->get_projected_type (
+ trait_item_ref, root, item_seg.get_mappings ().get_hirid (),
+ item_seg.get_locus ());
- // probe the path
- auto candidates
- = PathProbeType::Probe (tyseg, seg.get_segment (), probe_impls,
- probe_bounds, ignore_mandatory_trait_items);
- if (candidates.size () == 0)
- {
- rust_error_at (
- seg.get_locus (),
- "failed to resolve path segment using an impl Probe");
- return;
- }
- else if (candidates.size () > 1)
+ // turbo-fish segment path::<ty>
+ if (item_seg.has_generic_args ())
+ {
+ if (!infered->can_substitute ())
{
- ReportMultipleCandidateError::Report (candidates,
- seg.get_segment (),
- seg.get_locus ());
+ rust_error_at (item_seg.get_locus (),
+ "substitutions not supported for %s",
+ infered->as_string ().c_str ());
+ infered = new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
return;
}
+ infered = SubstMapper::Resolve (infered, expr.get_locus (),
+ &item_seg.get_generic_args ());
+ }
- auto &candidate = candidates.at (0);
- prev_segment = tyseg;
- tyseg = candidate.ty;
+ TyTy::ProjectionType *projection
+ = new TyTy::ProjectionType (qual_path_type.get_mappings ().get_hirid (),
+ TyTy::TyVar (root->get_ref ()), trait_ref,
+ resolved_item_id, lookup_associated);
+ context->insert_type (qual_path_type.get_mappings (), projection);
- if (candidate.is_impl_candidate ())
- {
- resolved_node_id
- = candidate.item.impl.impl_item->get_impl_mappings ()
- .get_nodeid ();
- }
- else
- {
- resolved_node_id
- = candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
- }
+ // continue on as a path-in-expression
+ NodeId root_resolved_node_id
+ = trait_item_ref->get_mappings ().get_nodeid ();
+ bool fully_resolved = expr.get_segments ().size () <= 1;
- if (seg.has_generic_args ())
+ if (fully_resolved)
+ {
+ // lookup if the name resolver was able to canonically resolve this or
+ // not
+ NodeId path_resolved_id = UNKNOWN_NODEID;
+ if (resolver->lookup_resolved_name (expr.get_mappings ().get_nodeid (),
+ &path_resolved_id))
{
- if (!tyseg->can_substitute ())
- {
- rust_error_at (expr.get_locus (),
- "substitutions not supported for %s",
- tyseg->as_string ().c_str ());
- return;
- }
-
- tyseg = SubstMapper::Resolve (tyseg, expr.get_locus (),
- &seg.get_generic_args ());
- if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
- return;
+ rust_assert (path_resolved_id == root_resolved_node_id);
}
- }
-
- context->insert_receiver (expr.get_mappings ().get_hirid (), prev_segment);
- if (tyseg->needs_generic_substitutions ())
- {
- Location locus = expr.get_segments ().back ().get_locus ();
- if (!prev_segment->needs_generic_substitutions ())
+ // check the type scope
+ else if (resolver->lookup_resolved_type (
+ expr.get_mappings ().get_nodeid (), &path_resolved_id))
{
- auto used_args_in_prev_segment
- = GetUsedSubstArgs::From (prev_segment);
- if (!used_args_in_prev_segment.is_error ())
- tyseg = SubstMapperInternal::Resolve (tyseg,
- used_args_in_prev_segment);
+ rust_assert (path_resolved_id == root_resolved_node_id);
}
else
{
- tyseg = SubstMapper::InferSubst (tyseg, locus);
+ resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
+ root_resolved_node_id);
}
- if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
- return;
+ context->insert_receiver (expr.get_mappings ().get_hirid (), root);
+ return;
}
- rust_assert (resolved_node_id != UNKNOWN_NODEID);
+ resolve_segments (root_resolved_node_id, expr.get_segments (), 1, infered,
+ expr.get_mappings (), expr.get_locus ());
+ }
- // lookup if the name resolver was able to canonically resolve this or not
- NodeId path_resolved_id = UNKNOWN_NODEID;
- if (resolver->lookup_resolved_name (expr.get_mappings ().get_nodeid (),
- &path_resolved_id))
- {
- rust_assert (path_resolved_id == resolved_node_id);
- }
- // check the type scope
- else if (resolver->lookup_resolved_type (expr.get_mappings ().get_nodeid (),
- &path_resolved_id))
+ void visit (HIR::PathInExpression &expr) override
+ {
+ NodeId resolved_node_id = UNKNOWN_NODEID;
+
+ size_t offset = -1;
+ TyTy::BaseType *tyseg
+ = resolve_root_path (expr, &offset, &resolved_node_id);
+
+ if (tyseg == nullptr)
{
- rust_assert (path_resolved_id == resolved_node_id);
+ rust_debug_loc (expr.get_locus (), "failed to resolve root_seg");
}
- else if (!name_resolved_fully)
+ rust_assert (tyseg != nullptr);
+
+ if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+
+ if (expr.get_num_segments () == 1)
{
- resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
- resolved_node_id);
+ Location locus = expr.get_segments ().back ().get_locus ();
+
+ bool is_big_self
+ = expr.get_segments ().front ().get_segment ().as_string ().compare (
+ "Self")
+ == 0;
+ if (!is_big_self && tyseg->needs_generic_substitutions ())
+ {
+ tyseg = SubstMapper::InferSubst (tyseg, locus);
+ }
+
+ infered = tyseg;
+ return;
}
- infered = tyseg;
+ resolve_segments (resolved_node_id, expr.get_segments (), offset, tyseg,
+ expr.get_mappings (), expr.get_locus ());
}
void visit (HIR::LoopExpr &expr) override
@@ -1353,6 +1377,136 @@ private:
return root_tyty;
}
+ void resolve_segments (NodeId root_resolved_node_id,
+ std::vector<HIR::PathExprSegment> &segments,
+ size_t offset, TyTy::BaseType *tyseg,
+ const Analysis::NodeMapping &expr_mappings,
+ Location expr_locus)
+ {
+ NodeId resolved_node_id = root_resolved_node_id;
+ TyTy::BaseType *prev_segment = tyseg;
+ for (size_t i = offset; i < segments.size (); i++)
+ {
+ HIR::PathExprSegment &seg = segments.at (i);
+
+ bool reciever_is_generic
+ = prev_segment->get_kind () == TyTy::TypeKind::PARAM;
+ bool probe_bounds = true;
+ bool probe_impls = !reciever_is_generic;
+ bool ignore_mandatory_trait_items = !reciever_is_generic;
+
+ // probe the path
+ auto candidates
+ = PathProbeType::Probe (prev_segment, seg.get_segment (), probe_impls,
+ probe_bounds, ignore_mandatory_trait_items);
+ if (candidates.size () == 0)
+ {
+ rust_error_at (
+ seg.get_locus (),
+ "failed to resolve path segment using an impl Probe");
+ return;
+ }
+ else if (candidates.size () > 1)
+ {
+ ReportMultipleCandidateError::Report (candidates,
+ seg.get_segment (),
+ seg.get_locus ());
+ return;
+ }
+
+ auto &candidate = candidates.at (0);
+ prev_segment = tyseg;
+ tyseg = candidate.ty;
+
+ if (candidate.is_impl_candidate ())
+ {
+ resolved_node_id
+ = candidate.item.impl.impl_item->get_impl_mappings ()
+ .get_nodeid ();
+ }
+ else
+ {
+ resolved_node_id
+ = candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
+
+ // lookup the associated-impl-trait
+ HIR::ImplBlock *impl = candidate.item.trait.impl;
+ if (impl != nullptr)
+ {
+ AssociatedImplTrait *lookup_associated = nullptr;
+ bool found_impl_trait = context->lookup_associated_trait_impl (
+ impl->get_mappings ().get_hirid (), &lookup_associated);
+ rust_assert (found_impl_trait);
+
+ lookup_associated->setup_associated_types ();
+
+ // we need a new ty_ref_id for this trait item
+ tyseg = tyseg->clone ();
+ tyseg->set_ty_ref (mappings->get_next_hir_id ());
+ }
+ }
+
+ if (seg.has_generic_args ())
+ {
+ if (!tyseg->can_substitute ())
+ {
+ rust_error_at (expr_locus, "substitutions not supported for %s",
+ tyseg->as_string ().c_str ());
+ return;
+ }
+
+ tyseg = SubstMapper::Resolve (tyseg, expr_locus,
+ &seg.get_generic_args ());
+ if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+ }
+ }
+
+ context->insert_receiver (expr_mappings.get_hirid (), prev_segment);
+ if (tyseg->needs_generic_substitutions ())
+ {
+ Location locus = segments.back ().get_locus ();
+ if (!prev_segment->needs_generic_substitutions ())
+ {
+ auto used_args_in_prev_segment
+ = GetUsedSubstArgs::From (prev_segment);
+ if (!used_args_in_prev_segment.is_error ())
+ tyseg = SubstMapperInternal::Resolve (tyseg,
+ used_args_in_prev_segment);
+ }
+ else
+ {
+ tyseg = SubstMapper::InferSubst (tyseg, locus);
+ }
+
+ if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
+ return;
+ }
+
+ rust_assert (resolved_node_id != UNKNOWN_NODEID);
+
+ // lookup if the name resolver was able to canonically resolve this or not
+ NodeId path_resolved_id = UNKNOWN_NODEID;
+ if (resolver->lookup_resolved_name (expr_mappings.get_nodeid (),
+ &path_resolved_id))
+ {
+ rust_assert (path_resolved_id == resolved_node_id);
+ }
+ // check the type scope
+ else if (resolver->lookup_resolved_type (expr_mappings.get_nodeid (),
+ &path_resolved_id))
+ {
+ rust_assert (path_resolved_id == resolved_node_id);
+ }
+ else
+ {
+ resolver->insert_resolved_name (expr_mappings.get_nodeid (),
+ resolved_node_id);
+ }
+
+ infered = tyseg;
+ }
+
bool
validate_arithmetic_type (TyTy::BaseType *type,
HIR::ArithmeticOrLogicalExpr::ExprType expr_type)
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
index 65088be..3d83523 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
@@ -383,8 +383,7 @@ public:
trait_reference.get_name ().c_str ());
}
- context->insert_type (resolved_trait_item.get_mappings (),
- lookup->clone ());
+ resolved_trait_item.associated_type_set (lookup);
}
void visit (HIR::Function &function) override
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h
index 372171f..72da26d 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.h
@@ -123,6 +123,19 @@ public:
trait_reference->get_name ().c_str ());
}
}
+
+ if (is_trait_impl_block)
+ {
+ trait_reference->clear_associated_types ();
+
+ AssociatedImplTrait associated (trait_reference, &impl_block, self,
+ context);
+ context->insert_associated_trait_impl (
+ impl_block.get_mappings ().get_hirid (), std::move (associated));
+ context->insert_associated_impl_mapping (
+ trait_reference->get_mappings ().get_hirid (), self,
+ impl_block.get_mappings ().get_hirid ());
+ }
}
void visit (HIR::Function &function) override
diff --git a/gcc/rust/typecheck/rust-hir-type-check-util.cc b/gcc/rust/typecheck/rust-hir-type-check-util.cc
new file mode 100644
index 0000000..82bd081
--- /dev/null
+++ b/gcc/rust/typecheck/rust-hir-type-check-util.cc
@@ -0,0 +1,41 @@
+// Copyright (C) 2021 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-type-check-util.h"
+#include "rust-hir-full.h"
+
+namespace Rust {
+namespace Resolver {
+
+void
+ImplTypeIterator::go ()
+{
+ for (auto &item : impl.get_impl_items ())
+ {
+ item->accept_vis (*this);
+ }
+}
+
+void
+ImplTypeIterator::visit (HIR::TypeAlias &alias)
+{
+ cb (alias);
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-util.h b/gcc/rust/typecheck/rust-hir-type-check-util.h
new file mode 100644
index 0000000..0ba07a1
--- /dev/null
+++ b/gcc/rust/typecheck/rust-hir-type-check-util.h
@@ -0,0 +1,216 @@
+// Copyright (C) 2021 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_TYPE_CHECK_UTIL_H
+#define RUST_HIR_TYPE_CHECK_UTIL_H
+
+#include <functional>
+#include "rust-hir-visitor.h"
+
+namespace Rust {
+namespace Resolver {
+
+class SimpleHirVisitor : public HIR::HIRVisitor
+{
+public:
+ virtual ~SimpleHirVisitor () {}
+
+ virtual void visit (HIR::IdentifierExpr &) override {}
+ virtual void visit (HIR::Lifetime &) override {}
+ virtual void visit (HIR::LifetimeParam &) override {}
+ virtual void visit (HIR::PathInExpression &) override {}
+ virtual void visit (HIR::TypePathSegment &) override {}
+ virtual void visit (HIR::TypePathSegmentGeneric &) override {}
+ virtual void visit (HIR::TypePathSegmentFunction &) override {}
+ virtual void visit (HIR::TypePath &) override {}
+ virtual void visit (HIR::QualifiedPathInExpression &) override {}
+ virtual void visit (HIR::QualifiedPathInType &) override {}
+
+ virtual void visit (HIR::LiteralExpr &) override {}
+ virtual void visit (HIR::BorrowExpr &) override {}
+ virtual void visit (HIR::DereferenceExpr &) override {}
+ virtual void visit (HIR::ErrorPropagationExpr &) override {}
+ virtual void visit (HIR::NegationExpr &) override {}
+ virtual void visit (HIR::ArithmeticOrLogicalExpr &) override {}
+ virtual void visit (HIR::ComparisonExpr &) override {}
+ virtual void visit (HIR::LazyBooleanExpr &) override {}
+ virtual void visit (HIR::TypeCastExpr &) override {}
+ virtual void visit (HIR::AssignmentExpr &) override {}
+
+ virtual void visit (HIR::GroupedExpr &) override {}
+
+ virtual void visit (HIR::ArrayElemsValues &) override {}
+ virtual void visit (HIR::ArrayElemsCopied &) override {}
+ virtual void visit (HIR::ArrayExpr &) override {}
+ virtual void visit (HIR::ArrayIndexExpr &) override {}
+ virtual void visit (HIR::TupleExpr &) override {}
+ virtual void visit (HIR::TupleIndexExpr &) override {}
+ virtual void visit (HIR::StructExprStruct &) override {}
+
+ virtual void visit (HIR::StructExprFieldIdentifier &) override {}
+ virtual void visit (HIR::StructExprFieldIdentifierValue &) override {}
+
+ virtual void visit (HIR::StructExprFieldIndexValue &) override {}
+ virtual void visit (HIR::StructExprStructFields &) override {}
+ virtual void visit (HIR::StructExprStructBase &) override {}
+ virtual void visit (HIR::StructExprTuple &) override {}
+ virtual void visit (HIR::StructExprUnit &) override {}
+
+ virtual void visit (HIR::EnumExprFieldIdentifier &) override {}
+ virtual void visit (HIR::EnumExprFieldIdentifierValue &) override {}
+
+ virtual void visit (HIR::EnumExprFieldIndexValue &) override {}
+ virtual void visit (HIR::EnumExprStruct &) override {}
+ virtual void visit (HIR::EnumExprTuple &) override {}
+ virtual void visit (HIR::EnumExprFieldless &) override {}
+ virtual void visit (HIR::CallExpr &) override {}
+ virtual void visit (HIR::MethodCallExpr &) override {}
+ virtual void visit (HIR::FieldAccessExpr &) override {}
+ virtual void visit (HIR::ClosureExprInner &) override {}
+ virtual void visit (HIR::BlockExpr &) override {}
+ virtual void visit (HIR::ClosureExprInnerTyped &) override {}
+ virtual void visit (HIR::ContinueExpr &) override {}
+ virtual void visit (HIR::BreakExpr &) override {}
+ virtual void visit (HIR::RangeFromToExpr &) override {}
+ virtual void visit (HIR::RangeFromExpr &) override {}
+ virtual void visit (HIR::RangeToExpr &) override {}
+ virtual void visit (HIR::RangeFullExpr &) override {}
+ virtual void visit (HIR::RangeFromToInclExpr &) override {}
+ virtual void visit (HIR::RangeToInclExpr &) override {}
+ virtual void visit (HIR::ReturnExpr &) override {}
+ virtual void visit (HIR::UnsafeBlockExpr &) override {}
+ virtual void visit (HIR::LoopExpr &) override {}
+ virtual void visit (HIR::WhileLoopExpr &) override {}
+ virtual void visit (HIR::WhileLetLoopExpr &) override {}
+ virtual void visit (HIR::ForLoopExpr &) override {}
+ virtual void visit (HIR::IfExpr &) override {}
+ virtual void visit (HIR::IfExprConseqElse &) override {}
+ virtual void visit (HIR::IfExprConseqIf &) override {}
+ virtual void visit (HIR::IfExprConseqIfLet &) override {}
+ virtual void visit (HIR::IfLetExpr &) override {}
+ virtual void visit (HIR::IfLetExprConseqElse &) override {}
+ virtual void visit (HIR::IfLetExprConseqIf &) override {}
+ virtual void visit (HIR::IfLetExprConseqIfLet &) override {}
+
+ virtual void visit (HIR::MatchExpr &) override {}
+ virtual void visit (HIR::AwaitExpr &) override {}
+ virtual void visit (HIR::AsyncBlockExpr &) override {}
+
+ virtual void visit (HIR::TypeParam &) override {}
+
+ virtual void visit (HIR::LifetimeWhereClauseItem &) override {}
+ virtual void visit (HIR::TypeBoundWhereClauseItem &) override {}
+ virtual void visit (HIR::ModuleBodied &) override {}
+ virtual void visit (HIR::ModuleNoBody &) override {}
+ virtual void visit (HIR::ExternCrate &) override {}
+
+ virtual void visit (HIR::UseTreeGlob &) override {}
+ virtual void visit (HIR::UseTreeList &) override {}
+ virtual void visit (HIR::UseTreeRebind &) override {}
+ virtual void visit (HIR::UseDeclaration &) override {}
+ virtual void visit (HIR::Function &) override {}
+ virtual void visit (HIR::TypeAlias &) override {}
+ virtual void visit (HIR::StructStruct &) override {}
+ virtual void visit (HIR::TupleStruct &) override {}
+ virtual void visit (HIR::EnumItem &) override {}
+ virtual void visit (HIR::EnumItemTuple &) override {}
+ virtual void visit (HIR::EnumItemStruct &) override {}
+ virtual void visit (HIR::EnumItemDiscriminant &) override {}
+ virtual void visit (HIR::Enum &) override {}
+ virtual void visit (HIR::Union &) override {}
+ virtual void visit (HIR::ConstantItem &) override {}
+ virtual void visit (HIR::StaticItem &) override {}
+ virtual void visit (HIR::TraitItemFunc &) override {}
+ virtual void visit (HIR::TraitItemConst &) override {}
+ virtual void visit (HIR::TraitItemType &) override {}
+ virtual void visit (HIR::Trait &) override {}
+ virtual void visit (HIR::ImplBlock &) override {}
+
+ virtual void visit (HIR::ExternalStaticItem &) override {}
+ virtual void visit (HIR::ExternalFunctionItem &) override {}
+ virtual void visit (HIR::ExternBlock &) override {}
+
+ virtual void visit (HIR::LiteralPattern &) override {}
+ virtual void visit (HIR::IdentifierPattern &) override {}
+ virtual void visit (HIR::WildcardPattern &) override {}
+
+ virtual void visit (HIR::RangePatternBoundLiteral &) override {}
+ virtual void visit (HIR::RangePatternBoundPath &) override {}
+ virtual void visit (HIR::RangePatternBoundQualPath &) override {}
+ virtual void visit (HIR::RangePattern &) override {}
+ virtual void visit (HIR::ReferencePattern &) override {}
+
+ virtual void visit (HIR::StructPatternFieldTuplePat &) override {}
+ virtual void visit (HIR::StructPatternFieldIdentPat &) override {}
+ virtual void visit (HIR::StructPatternFieldIdent &) override {}
+ virtual void visit (HIR::StructPattern &) override {}
+
+ virtual void visit (HIR::TupleStructItemsNoRange &) override {}
+ virtual void visit (HIR::TupleStructItemsRange &) override {}
+ virtual void visit (HIR::TupleStructPattern &) override {}
+
+ virtual void visit (HIR::TuplePatternItemsMultiple &) override {}
+ virtual void visit (HIR::TuplePatternItemsRanged &) override {}
+ virtual void visit (HIR::TuplePattern &) override {}
+ virtual void visit (HIR::GroupedPattern &) override {}
+ virtual void visit (HIR::SlicePattern &) override {}
+
+ virtual void visit (HIR::EmptyStmt &) override {}
+ virtual void visit (HIR::LetStmt &) override {}
+ virtual void visit (HIR::ExprStmtWithoutBlock &) override {}
+ virtual void visit (HIR::ExprStmtWithBlock &) override {}
+
+ virtual void visit (HIR::TraitBound &) override {}
+ virtual void visit (HIR::ImplTraitType &) override {}
+ virtual void visit (HIR::TraitObjectType &) override {}
+ virtual void visit (HIR::ParenthesisedType &) override {}
+ virtual void visit (HIR::ImplTraitTypeOneBound &) override {}
+ virtual void visit (HIR::TraitObjectTypeOneBound &) override {}
+ virtual void visit (HIR::TupleType &) override {}
+ virtual void visit (HIR::NeverType &) override {}
+ virtual void visit (HIR::RawPointerType &) override {}
+ virtual void visit (HIR::ReferenceType &) override {}
+ virtual void visit (HIR::ArrayType &) override {}
+ virtual void visit (HIR::SliceType &) override {}
+ virtual void visit (HIR::InferredType &) override {}
+ virtual void visit (HIR::BareFunctionType &) override {}
+};
+
+class ImplTypeIterator : public SimpleHirVisitor
+{
+ using SimpleHirVisitor::visit;
+
+public:
+ ImplTypeIterator (HIR::ImplBlock &impl,
+ std::function<void (HIR::TypeAlias &alias)> cb)
+ : impl (impl), cb (cb)
+ {}
+
+ void go ();
+
+ void visit (HIR::TypeAlias &alias) override;
+
+private:
+ HIR::ImplBlock &impl;
+ std::function<void (HIR::TypeAlias &alias)> cb;
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_HIR_TYPE_CHECK_UTIL_H
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index d834ad8..27b7f12 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -117,6 +117,70 @@ public:
return true;
}
+ void insert_associated_trait_impl (HirId id, AssociatedImplTrait &&associated)
+ {
+ rust_assert (associated_impl_traits.find (id)
+ == associated_impl_traits.end ());
+ associated_impl_traits.emplace (id, std::move (associated));
+ }
+
+ bool lookup_associated_trait_impl (HirId id, AssociatedImplTrait **associated)
+ {
+ auto it = associated_impl_traits.find (id);
+ if (it == associated_impl_traits.end ())
+ return false;
+
+ *associated = &it->second;
+ return true;
+ }
+
+ void insert_associated_type_mapping (HirId id, HirId mapping)
+ {
+ associated_type_mappings[id] = mapping;
+ }
+
+ void clear_associated_type_mapping (HirId id)
+ {
+ associated_type_mappings[id] = UNKNOWN_HIRID;
+ }
+
+ HirId lookup_associated_type_mapping (HirId id, HirId default_value)
+ {
+ auto it = associated_type_mappings.find (id);
+ if (it == associated_type_mappings.end ())
+ return default_value;
+
+ return it->second;
+ }
+
+ void insert_associated_impl_mapping (HirId trait_id,
+ const TyTy::BaseType *impl_type,
+ HirId impl_id)
+ {
+ auto it = associated_traits_to_impls.find (trait_id);
+ if (it == associated_traits_to_impls.end ())
+ {
+ associated_traits_to_impls[trait_id] = {};
+ }
+
+ associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id});
+ }
+
+ HirId lookup_associated_impl_mapping_for_self (HirId trait_id,
+ const TyTy::BaseType *self)
+ {
+ auto it = associated_traits_to_impls.find (trait_id);
+ if (it == associated_traits_to_impls.end ())
+ return UNKNOWN_HIRID;
+
+ for (auto &item : it->second)
+ {
+ if (item.first->can_eq (self, false))
+ return item.second;
+ }
+ return UNKNOWN_HIRID;
+ }
+
private:
TypeCheckContext ();
@@ -127,6 +191,13 @@ private:
std::vector<TyTy::BaseType *> loop_type_stack;
std::map<DefId, TraitReference> trait_context;
std::map<HirId, TyTy::BaseType *> receiver_context;
+ std::map<HirId, AssociatedImplTrait> associated_impl_traits;
+
+ // trait-id -> list of < self-tyty:impl-id>
+ std::map<HirId, std::vector<std::pair<const TyTy::BaseType *, HirId>>>
+ associated_traits_to_impls;
+
+ std::map<HirId, HirId> associated_type_mappings;
};
class TypeResolution
diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h
index a3c00da..c7ea029 100644
--- a/gcc/rust/typecheck/rust-substitution-mapper.h
+++ b/gcc/rust/typecheck/rust-substitution-mapper.h
@@ -108,6 +108,7 @@ public:
void visit (TyTy::StrType &) override { gcc_unreachable (); }
void visit (TyTy::NeverType &) override { gcc_unreachable (); }
void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); }
+ void visit (TyTy::ProjectionType &) override { gcc_unreachable (); }
private:
SubstMapper (HirId ref, HIR::GenericArgs *generics, Location locus)
@@ -191,6 +192,7 @@ public:
void visit (TyTy::StrType &) override { gcc_unreachable (); }
void visit (TyTy::NeverType &) override { gcc_unreachable (); }
void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); }
+ void visit (TyTy::ProjectionType &) override { gcc_unreachable (); }
private:
SubstMapperInternal (HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
@@ -248,6 +250,7 @@ public:
void visit (TyTy::StrType &) override { gcc_unreachable (); }
void visit (TyTy::NeverType &) override { gcc_unreachable (); }
void visit (TyTy::PlaceholderType &) override { gcc_unreachable (); }
+ void visit (TyTy::ProjectionType &) override { gcc_unreachable (); }
private:
SubstMapperFromExisting (TyTy::BaseType *concrete, TyTy::BaseType *receiver)
@@ -298,6 +301,7 @@ public:
void visit (TyTy::StrType &) override {}
void visit (TyTy::NeverType &) override {}
void visit (TyTy::PlaceholderType &) override {}
+ void visit (TyTy::ProjectionType &) override {}
private:
GetUsedSubstArgs () : args (TyTy::SubstitutionArgumentMappings::error ()) {}
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index 008dc19..1bd7865 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -25,7 +25,8 @@ namespace Resolver {
void
TypeBoundsProbe::scan ()
{
- std::vector<HIR::TypePath *> possible_trait_paths;
+ std::vector<std::pair<HIR::TypePath *, HIR::ImplBlock *>>
+ possible_trait_paths;
mappings->iterate_impl_blocks (
[&] (HirId id, HIR::ImplBlock *impl) mutable -> bool {
// we are filtering for trait-impl-blocks
@@ -42,16 +43,17 @@ TypeBoundsProbe::scan ()
if (!receiver->can_eq (impl_type, false))
return true;
- possible_trait_paths.push_back (impl->get_trait_ref ().get ());
+ possible_trait_paths.push_back ({impl->get_trait_ref ().get (), impl});
return true;
});
- for (auto &trait_path : possible_trait_paths)
+ for (auto &path : possible_trait_paths)
{
+ HIR::TypePath *trait_path = path.first;
TraitReference *trait_ref = TraitResolver::Resolve (*trait_path);
if (!trait_ref->is_error ())
- trait_references.push_back (trait_ref);
+ trait_references.push_back ({trait_ref, path.second});
}
}
diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h
index 636d40b..4e74e59 100644
--- a/gcc/rust/typecheck/rust-tyty-call.h
+++ b/gcc/rust/typecheck/rust-tyty-call.h
@@ -56,6 +56,7 @@ public:
void visit (StrType &) override { gcc_unreachable (); }
void visit (NeverType &) override { gcc_unreachable (); }
void visit (PlaceholderType &) override { gcc_unreachable (); }
+ void visit (ProjectionType &) override { gcc_unreachable (); }
// tuple-structs
void visit (ADTType &type) override;
@@ -106,6 +107,7 @@ public:
void visit (StrType &) override { gcc_unreachable (); }
void visit (NeverType &) override { gcc_unreachable (); }
void visit (PlaceholderType &) override { gcc_unreachable (); }
+ void visit (ProjectionType &) override { gcc_unreachable (); }
// FIXME
void visit (FnPtr &type) override { gcc_unreachable (); }
diff --git a/gcc/rust/typecheck/rust-tyty-cast.h b/gcc/rust/typecheck/rust-tyty-cast.h
index c457931..51c9791 100644
--- a/gcc/rust/typecheck/rust-tyty-cast.h
+++ b/gcc/rust/typecheck/rust-tyty-cast.h
@@ -307,6 +307,17 @@ public:
type.as_string ().c_str ());
}
+ virtual void visit (ProjectionType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "invalid cast [%s] to [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
protected:
BaseCastRules (BaseType *base)
: mappings (Analysis::Mappings::get ()),
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index 049a4b7..100e384 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -43,6 +43,16 @@ public:
return ok;
}
}
+ else if (other->get_kind () == TypeKind::PLACEHOLDER)
+ {
+ const PlaceholderType *p = static_cast<const PlaceholderType *> (other);
+ if (p->can_resolve ())
+ {
+ const BaseType *resolved = p->resolve ();
+ resolved->accept_vis (*this);
+ return ok;
+ }
+ }
other->accept_vis (*this);
return ok;
@@ -337,6 +347,22 @@ public:
}
}
+ virtual void visit (const ProjectionType &type) override
+ {
+ ok = false;
+ if (emit_error_flag)
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus
+ = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "expected [%s] got [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+ }
+
virtual void visit (const PlaceholderType &type) override
{
// it is ok for types to can eq to a placeholder
@@ -1149,43 +1175,55 @@ public:
: BaseCmp (base, emit_errors), base (base)
{}
- virtual void visit (const TupleType &) override { ok = true; }
+ bool can_eq (const BaseType *other) override
+ {
+ if (!base->can_resolve ())
+ return BaseCmp::can_eq (other);
+
+ BaseType *lookup = base->resolve ();
+ return lookup->can_eq (other, emit_error_flag);
+ }
+
+ void visit (const TupleType &) override { ok = true; }
- virtual void visit (const ADTType &) override { ok = true; }
+ void visit (const ADTType &) override { ok = true; }
- virtual void visit (const InferType &) override { ok = true; }
+ void visit (const InferType &) override { ok = true; }
- virtual void visit (const FnType &) override { ok = true; }
+ void visit (const FnType &) override { ok = true; }
- virtual void visit (const FnPtr &) override { ok = true; }
+ void visit (const FnPtr &) override { ok = true; }
- virtual void visit (const ArrayType &) override { ok = true; }
+ void visit (const ArrayType &) override { ok = true; }
- virtual void visit (const BoolType &) override { ok = true; }
+ void visit (const BoolType &) override { ok = true; }
- virtual void visit (const IntType &) override { ok = true; }
+ void visit (const IntType &) override { ok = true; }
- virtual void visit (const UintType &) override { ok = true; }
+ void visit (const UintType &) override { ok = true; }
- virtual void visit (const USizeType &) override { ok = true; }
+ void visit (const USizeType &) override { ok = true; }
- virtual void visit (const ISizeType &) override { ok = true; }
+ void visit (const ISizeType &) override { ok = true; }
- virtual void visit (const FloatType &) override { ok = true; }
+ void visit (const FloatType &) override { ok = true; }
- virtual void visit (const ErrorType &) override { ok = true; }
+ void visit (const ErrorType &) override { ok = true; }
- virtual void visit (const CharType &) override { ok = true; }
+ void visit (const CharType &) override { ok = true; }
- virtual void visit (const ReferenceType &) override { ok = true; }
+ void visit (const ReferenceType &) override { ok = true; }
- virtual void visit (const ParamType &) override { ok = true; }
+ void visit (const ParamType &) override { ok = true; }
- virtual void visit (const StrType &) override { ok = true; }
+ void visit (const StrType &) override { ok = true; }
- virtual void visit (const NeverType &) override { ok = true; }
+ void visit (const NeverType &) override { ok = true; }
- virtual void visit (const PlaceholderType &) override { ok = true; }
+ void visit (const PlaceholderType &type) override
+ {
+ ok = base->get_symbol ().compare (type.get_symbol ()) == 0;
+ }
private:
const BaseType *get_base () const override { return base; }
diff --git a/gcc/rust/typecheck/rust-tyty-coercion.h b/gcc/rust/typecheck/rust-tyty-coercion.h
index f19871e..d30be7f 100644
--- a/gcc/rust/typecheck/rust-tyty-coercion.h
+++ b/gcc/rust/typecheck/rust-tyty-coercion.h
@@ -307,6 +307,17 @@ public:
type.as_string ().c_str ());
}
+ virtual void visit (ProjectionType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "expected [%s] got [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
protected:
BaseCoercionRules (BaseType *base)
: mappings (Analysis::Mappings::get ()),
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
index de9a5d9..4d0b977 100644
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ b/gcc/rust/typecheck/rust-tyty-rules.h
@@ -68,6 +68,14 @@ public:
other = p->resolve ();
}
}
+ else if (other->get_kind () == TypeKind::PLACEHOLDER)
+ {
+ PlaceholderType *p = static_cast<PlaceholderType *> (other);
+ if (p->can_resolve ())
+ {
+ other = p->resolve ();
+ }
+ }
other->accept_vis (*this);
if (resolved->get_kind () == TyTy::TypeKind::ERROR)
@@ -329,6 +337,17 @@ public:
type.as_string ().c_str ());
}
+ virtual void visit (ProjectionType &type) override
+ {
+ Location ref_locus = mappings->lookup_location (type.get_ref ());
+ Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
+ RichLocation r (ref_locus);
+ r.add_range (base_locus);
+ rust_error_at (r, "expected [%s] got [%s]",
+ get_base ()->as_string ().c_str (),
+ type.as_string ().c_str ());
+ }
+
protected:
BaseRules (BaseType *base)
: mappings (Analysis::Mappings::get ()),
@@ -1238,7 +1257,7 @@ class NeverRules : public BaseRules
public:
NeverRules (NeverType *base) : BaseRules (base), base (base) {}
- virtual void visit (NeverType &type) override { resolved = type.clone (); }
+ void visit (NeverType &type) override { resolved = type.clone (); }
private:
BaseType *get_base () override { return base; }
@@ -1253,6 +1272,37 @@ class PlaceholderRules : public BaseRules
public:
PlaceholderRules (PlaceholderType *base) : BaseRules (base), base (base) {}
+ BaseType *unify (BaseType *other) override final
+ {
+ if (!base->can_resolve ())
+ return BaseRules::unify (other);
+
+ BaseType *lookup = base->resolve ();
+ return lookup->unify (other);
+ }
+
+ void visit (PlaceholderType &type) override
+ {
+ if (base->get_symbol ().compare (type.get_symbol ()) != 0)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = type.clone ();
+ }
+
+ void visit (InferType &type) override
+ {
+ if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
+ {
+ BaseRules::visit (type);
+ return;
+ }
+
+ resolved = base->clone ();
+ }
+
private:
BaseType *get_base () override { return base; }
diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h
index 66b11b9..0e9a58b 100644
--- a/gcc/rust/typecheck/rust-tyty-visitor.h
+++ b/gcc/rust/typecheck/rust-tyty-visitor.h
@@ -47,6 +47,7 @@ public:
virtual void visit (StrType &type) = 0;
virtual void visit (NeverType &type) = 0;
virtual void visit (PlaceholderType &type) = 0;
+ virtual void visit (ProjectionType &type) = 0;
};
class TyConstVisitor
@@ -72,6 +73,7 @@ public:
virtual void visit (const StrType &type) = 0;
virtual void visit (const NeverType &type) = 0;
virtual void visit (const PlaceholderType &type) = 0;
+ virtual void visit (const ProjectionType &type) = 0;
};
} // namespace TyTy
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 2d165c3..56fdafd 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -49,10 +49,10 @@ BaseType::satisfies_bound (const TypeBoundPredicate &predicate) const
return true;
}
- std::vector<Resolver::TraitReference *> probed
- = Resolver::TypeBoundsProbe::Probe (this);
- for (const Resolver::TraitReference *bound : probed)
+ auto probed = Resolver::TypeBoundsProbe::Probe (this);
+ for (auto &b : probed)
{
+ const Resolver::TraitReference *bound = b.first;
bool found = bound->get_mappings ().get_defid ()
== query->get_mappings ().get_defid ();
if (found)
@@ -2015,6 +2015,8 @@ NeverType::clone () const
return new NeverType (get_ref (), get_ty_ref (), get_combined_refs ());
}
+// placeholder type
+
void
PlaceholderType::accept_vis (TyVisitor &vis)
{
@@ -2030,7 +2032,8 @@ PlaceholderType::accept_vis (TyConstVisitor &vis) const
std::string
PlaceholderType::as_string () const
{
- return "<placeholder>";
+ return "<placeholder:" + (can_resolve () ? resolve ()->as_string () : "")
+ + ">";
}
BaseType *
@@ -2064,7 +2067,114 @@ PlaceholderType::can_eq (const BaseType *other, bool emit_errors) const
BaseType *
PlaceholderType::clone () const
{
- return new PlaceholderType (get_ref (), get_ty_ref (), get_combined_refs ());
+ return new PlaceholderType (get_symbol (), get_ref (), get_ty_ref (),
+ get_combined_refs ());
+}
+
+void
+PlaceholderType::set_associated_type (HirId ref)
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ context->insert_associated_type_mapping (get_ty_ref (), ref);
+}
+
+void
+PlaceholderType::clear_associated_type ()
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ context->clear_associated_type_mapping (get_ty_ref ());
+}
+
+bool
+PlaceholderType::can_resolve () const
+{
+ auto context = Resolver::TypeCheckContext::get ();
+ HirId val
+ = context->lookup_associated_type_mapping (get_ty_ref (), UNKNOWN_HIRID);
+ return val != UNKNOWN_HIRID;
+}
+
+BaseType *
+PlaceholderType::resolve () const
+{
+ auto context = Resolver::TypeCheckContext::get ();
+
+ rust_assert (can_resolve ());
+ HirId val
+ = context->lookup_associated_type_mapping (get_ty_ref (), UNKNOWN_HIRID);
+ rust_assert (val != UNKNOWN_HIRID);
+
+ return TyVar (val).get_tyty ();
+}
+
+bool
+PlaceholderType::is_equal (const BaseType &other) const
+{
+ if (get_kind () != other.get_kind ())
+ {
+ if (!can_resolve ())
+ return false;
+
+ return resolve ()->is_equal (other);
+ }
+
+ auto other2 = static_cast<const PlaceholderType &> (other);
+ return get_symbol ().compare (other2.get_symbol ()) == 0;
+}
+
+// Projection type
+
+void
+ProjectionType::accept_vis (TyVisitor &vis)
+{
+ vis.visit (*this);
+}
+
+void
+ProjectionType::accept_vis (TyConstVisitor &vis) const
+{
+ vis.visit (*this);
+}
+
+std::string
+ProjectionType::as_string () const
+{
+ return "<Projection>";
+}
+
+BaseType *
+ProjectionType::unify (BaseType *other)
+{
+ gcc_unreachable ();
+ return nullptr;
+}
+
+BaseType *
+ProjectionType::coerce (BaseType *other)
+{
+ gcc_unreachable ();
+ return nullptr;
+}
+
+BaseType *
+ProjectionType::cast (BaseType *other)
+{
+ gcc_unreachable ();
+ return nullptr;
+}
+
+bool
+ProjectionType::can_eq (const BaseType *other, bool emit_errors) const
+{
+ gcc_unreachable ();
+ return false;
+}
+
+BaseType *
+ProjectionType::clone () const
+{
+ return new ProjectionType (get_ref (), get_ty_ref (), base, trait, item,
+ associated, get_combined_refs ());
}
// rust-tyty-call.h
@@ -2186,6 +2296,17 @@ TypeCheckCallExpr::visit (FnType &type)
return;
}
+ if (type.get_return_type ()->get_kind () == TyTy::TypeKind::PLACEHOLDER)
+ {
+ const TyTy::PlaceholderType *p
+ = static_cast<const TyTy::PlaceholderType *> (type.get_return_type ());
+ if (p->can_resolve ())
+ {
+ resolved = p->resolve ()->clone ();
+ return;
+ }
+ }
+
resolved = type.get_return_type ()->clone ();
}
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index c1afa14..743874a 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -27,7 +27,8 @@
namespace Rust {
namespace Resolver {
class TraitReference;
-}
+class AssociatedImplTrait;
+} // namespace Resolver
namespace TyTy {
@@ -54,6 +55,7 @@ enum TypeKind
ISIZE,
NEVER,
PLACEHOLDER,
+ PROJECTION,
// there are more to add...
ERROR
};
@@ -122,6 +124,9 @@ public:
case TypeKind::PLACEHOLDER:
return "Placeholder";
+ case TypeKind::PROJECTION:
+ return "Projection";
+
case TypeKind::ERROR:
return "ERROR";
}
@@ -1679,13 +1684,15 @@ public:
class PlaceholderType : public BaseType
{
public:
- PlaceholderType (HirId ref, std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ref, TypeKind::PLACEHOLDER, refs)
+ PlaceholderType (std::string symbol, HirId ref,
+ std::set<HirId> refs = std::set<HirId> ())
+ : BaseType (ref, ref, TypeKind::PLACEHOLDER, refs), symbol (symbol)
+
{}
- PlaceholderType (HirId ref, HirId ty_ref,
+ PlaceholderType (std::string symbol, HirId ref, HirId ty_ref,
std::set<HirId> refs = std::set<HirId> ())
- : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER, refs)
+ : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER, refs), symbol (symbol)
{}
void accept_vis (TyVisitor &vis) override;
@@ -1703,6 +1710,62 @@ public:
std::string get_name () const override final { return as_string (); }
bool is_unit () const override { return true; }
+
+ std::string get_symbol () const { return symbol; }
+
+ void set_associated_type (HirId ref);
+
+ void clear_associated_type ();
+
+ bool can_resolve () const;
+
+ BaseType *resolve () const;
+
+ bool is_equal (const BaseType &other) const override;
+
+private:
+ std::string symbol;
+};
+
+class ProjectionType : public BaseType
+{
+public:
+ ProjectionType (HirId ref, TyVar base, Resolver::TraitReference *trait,
+ DefId item, Resolver::AssociatedImplTrait *associated,
+ std::set<HirId> refs = std::set<HirId> ())
+ : BaseType (ref, ref, TypeKind::PROJECTION, refs), base (base),
+ trait (trait), item (item), associated (associated)
+ {}
+
+ ProjectionType (HirId ref, HirId ty_ref, TyVar base,
+ Resolver::TraitReference *trait, DefId item,
+ Resolver::AssociatedImplTrait *associated,
+ std::set<HirId> refs = std::set<HirId> ())
+ : BaseType (ref, ty_ref, TypeKind::PROJECTION, refs), base (base),
+ trait (trait), item (item), associated (associated)
+ {}
+
+ void accept_vis (TyVisitor &vis) override;
+ void accept_vis (TyConstVisitor &vis) const override;
+
+ std::string as_string () const override;
+
+ BaseType *unify (BaseType *other) override;
+ bool can_eq (const BaseType *other, bool emit_errors) const override final;
+ BaseType *coerce (BaseType *other) override;
+ BaseType *cast (BaseType *other) override;
+
+ BaseType *clone () const final override;
+
+ std::string get_name () const override final { return as_string (); }
+
+ bool is_unit () const override { return false; }
+
+private:
+ TyVar base;
+ Resolver::TraitReference *trait;
+ DefId item;
+ Resolver::AssociatedImplTrait *associated;
};
} // namespace TyTy
diff --git a/gcc/rust/util/rust-canonical-path.h b/gcc/rust/util/rust-canonical-path.h
index d6ba90d..b5f8dd7 100644
--- a/gcc/rust/util/rust-canonical-path.h
+++ b/gcc/rust/util/rust-canonical-path.h
@@ -110,6 +110,17 @@ public:
}
}
+ void iterate_segs (std::function<bool (const CanonicalPath &)> cb) const
+ {
+ for (auto &seg : segs)
+ {
+ std::vector<std::pair<NodeId, std::string>> buf;
+ buf.push_back ({seg.first, seg.second});
+ if (!cb (CanonicalPath (buf)))
+ return;
+ }
+ }
+
size_t size () const { return segs.size (); }
NodeId get_id () const
diff --git a/gcc/testsuite/rust/compile/torture/traits10.rs b/gcc/testsuite/rust/compile/torture/traits10.rs
new file mode 100644
index 0000000..3e47b1b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits10.rs
@@ -0,0 +1,32 @@
+trait Foo
+where
+ Self: Sized,
+{
+ fn get(self) -> i32;
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+ fn test(self) -> i32 {
+ self.get()
+ }
+}
+
+struct Bar(i32);
+impl Foo for Bar {
+ fn get(self) -> i32 {
+ self.0
+ }
+}
+
+fn main() {
+ let a;
+ a = Bar(123);
+
+ let b;
+ b = Bar::get(a);
+
+ let a;
+ a = Bar(123);
+
+ let b;
+ b = a.test();
+}
diff --git a/gcc/testsuite/rust/compile/torture/traits11.rs b/gcc/testsuite/rust/compile/torture/traits11.rs
new file mode 100644
index 0000000..b5fc023
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/traits11.rs
@@ -0,0 +1,32 @@
+trait Foo {
+ type A;
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+
+ fn test(a: Self::A) -> Self::A {
+ a
+ }
+}
+
+struct Bar(i32);
+impl Foo for Bar {
+ type A = i32;
+}
+
+struct Baz(f32);
+impl Foo for Baz {
+ type A = f32;
+}
+
+fn main() {
+ let a;
+ a = Bar(123);
+
+ let b;
+ b = Bar::test(a.0);
+
+ let c;
+ c = Baz(123f32);
+
+ let d;
+ d = Baz::test(c.0);
+}
diff --git a/gcc/testsuite/rust/compile/traits1.rs b/gcc/testsuite/rust/compile/traits1.rs
index 30483b1..355064e 100644
--- a/gcc/testsuite/rust/compile/traits1.rs
+++ b/gcc/testsuite/rust/compile/traits1.rs
@@ -1,5 +1,6 @@
trait Foo {
fn Bar() -> i32 {}
+ // { dg-error "expected .i32. got .()." "" { target *-*-* } .-1 }
}
struct Baz;
diff --git a/gcc/testsuite/rust/compile/traits2.rs b/gcc/testsuite/rust/compile/traits2.rs
index 08e6bd3..7357c22 100644
--- a/gcc/testsuite/rust/compile/traits2.rs
+++ b/gcc/testsuite/rust/compile/traits2.rs
@@ -1,5 +1,6 @@
trait Foo {
fn Bar() -> i32 {}
+ // { dg-error "expected .i32. got .()." "" { target *-*-* } .-1 }
}
struct Baz;
diff --git a/gcc/testsuite/rust/execute/torture/trait1.rs b/gcc/testsuite/rust/execute/torture/trait1.rs
new file mode 100644
index 0000000..dc3cc47
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait1.rs
@@ -0,0 +1,52 @@
+/* { dg-output "S::f\nT1::f\nT2::f\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct S;
+
+impl S {
+ fn f() {
+ unsafe {
+ let a = "S::f\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ }
+}
+
+trait T1 {
+ fn f() {
+ unsafe {
+ let a = "T1::f\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ }
+}
+impl T1 for S {}
+
+trait T2 {
+ fn f() {
+ unsafe {
+ let a = "T2::f\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c);
+ }
+ }
+}
+impl T2 for S {}
+
+fn main() -> i32 {
+ S::f();
+ <S as T1>::f();
+ <S as T2>::f();
+
+ 0
+}