aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-08-20 12:34:35 +0000
committerGitHub <noreply@github.com>2021-08-20 12:34:35 +0000
commit79754bd20bdfa64a4ce91e5b4a65154c313b2d83 (patch)
tree47dc551f706c4015c017a299a4054cb7db460857 /gcc
parent387f73626ae0e04c3f81d71d4de6780a4caad052 (diff)
parent048261647afd1a08f681b78c90c58a9baaeef76d (diff)
downloadgcc-79754bd20bdfa64a4ce91e5b4a65154c313b2d83.zip
gcc-79754bd20bdfa64a4ce91e5b4a65154c313b2d83.tar.gz
gcc-79754bd20bdfa64a4ce91e5b4a65154c313b2d83.tar.bz2
Merge #626
626: Optional trait items r=philberty a=philberty Optional trait items like function may contain associated types. These are dependant on the associated impl block for this type in order to correctly propagate the correct types for the associated trait item during type checking and compilation. Fixes #542 Co-authored-by: Philip Herron <philip.herron@embecosm.com>
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
+}